[android]android attributeset 用法與時機


用得時機

  • 自己客製化的View
  • 有用到LayoutInflater
  • 需要使用的人動態改變View禮拜的屬性

範例說明

簡單的圖片在上,文字在下的View

Layout檔

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
  
  <LinearLayout
  android:layout_width="100dp"
  android:layout_height="100dp"
  android:orientation="vertical" >
    
    <ImageView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_launcher" />
    
    <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />
  </LinearLayout>
  
</RelativeLayout>

此時把它做成客製化的View

  • 先創一個 FrameView.java 
package com.kirin.attrtest;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.LinearLayout;

public class FrameView extends LinearLayout {

 public FrameView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public FrameView(Context context) {
  super(context);
  init();
 }

 private void init() {
  LayoutInflater mInflater = (LayoutInflater) getContext()
    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  mInflater.inflate(R.layout.frame_view, this);
 }

}


frame_view.xml
xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</LinearLayout>


使用後的layout檔

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <com.kirin.attrtest.FrameView
        android:layout_width="100dp
        android:layout_height="100dp" 
        android:orientation="vertical" >
    </com.kirin.attrtest.FrameView>

</RelativeLayout>

  • 使用後這就變成專屬的View了
  • 可讀性變高了
  • 有group的效果

問題

  • 使用者要換圖片或文字這麼辦?
  • 先在{project}\res\values創建attr.xml
xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="frameView">
        <attr name="description" format="string" />
        <attr name="image" format="reference" />
    </declare-styleable>
</resources>

  • format種類如下
  • reference
  • string
  • color
  • dimension
  • boolean
  • integer
  • float
  • fraction
  • enum
  • flag
可參考這一篇
  • 設定完成後,更改 FrameView
  • package com.kirin.attrtest; import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.view.LayoutInflater;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView; public class FrameView extends LinearLayout { private TextView descriptionView = null; private ImageView imageView = null; public FrameView(Context context, AttributeSet attrs) { super(context, attrs); init(); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.frameView); descriptionView.setText(typedArray.getString(R.styleable.frameView_description)); imageView.setImageResource(typedArray.getResourceId(R.styleable.frameView_image_src, R.drawable.ic_launcher)); typedArray.recycle(); } public FrameView(Context context) { super(context); init(); } private void init() { LayoutInflater mInflater = (LayoutInflater) getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); mInflater.inflate(R.layout.frame_view, this); descriptionView = (TextView) findViewById(R.id.description); imageView = (ImageView) findViewById(R.id.image); } }

重點是下列這幾行

TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.frameView);
descriptionView.setText(typedArray.getString(R.styleable.frameView_description));
imageView.setImageResource(typedArray.getResourceId(R.styleable.frameView_image_src, R.drawable.ic_launcher));
typedArray.recycle()
;


layout 檔如下
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:myapp="http://schemas.android.com/apk/res/com.kirin.attrtest"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <com.kirin.attrtest.FrameView
        android:layout_width="100dp"
        android:layout_height="100dp"
        myapp:description="TEST"
        myapp:image_src="@drawable/test"
        android:orientation="vertical" >
    </com.kirin.attrtest.FrameView>

</RelativeLayout>
效果如這
範例連結

https://www.evernote.com/shard/s183/sh/13b79756-a88d-42ef-9be6-a4155c890486/9066c8c41b12199a13a0d9d9da9767be






留言

張貼留言

這個網誌中的熱門文章

angular 如何Http 如何設定 CORS (Cross-Origin Resource Sharing)

Google Map 單車路徑計算坡度和角度小工具

Google URL Shortener API 快速教學