Android實戰技巧之組合控件
組合控件是自定義控件的一種,只不過它是由其他幾個原生控件組合而成,故名組合控件。
在實際項目中,GUI會遇到一些可以提取出來做成自定義控件情況。
一個自定義控件的好處就是把一些需要模塊化的UI和邏輯放在一起,做到了高內聚,向其他模塊提供接口并很少
依賴外界,這樣就是低耦合。一個自定義控件就是一個封閉的王國,這里由你掌控。
上述是我自己的一個體會,想必大家也會常做自定義控件吧,就像邏輯部分的模塊化一樣。
下面我要做一個例子,請看完成圖。
下面一排圖片加文字就是組合控件了,我是怎么做的呢?
其實這里用到了兩個組合控件,一個是圖片+文字,我把它叫一個Item,而三個在一起就是另一個控件了。
重點看這個Item,它有自己的屬性如圖片、文字、圖片大小、文字大小、不透明度等等。這些把它定義在attr文件中,然后在xml文件中
配置,就像我們用原生控件一樣。
先看attr文件。
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="LevelMenuItem"> <attr name="text" format="string" /> <attr name="text_color" format="color"/> <attr name="text_size" format="dimension" /> <attr name="image_src" format="reference"/> <attr name="image_bg" format="reference"/> <attr name="image_alpha" format="integer" /> <attr name="image_height" format="dimension"></attr> <attr name="image_width" format="dimension" /> </declare-styleable> </resources>這個文件在values下,和string文件同級。把你自己要定義的屬性都寫在這里吧。format是屬性的“單位”,如果你要問有多少中format呀?答案在這里。
有了屬性了,下面看看布局文件level_menu_item.xml。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ImageView android:id="@+id/image_item" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="fitCenter" /> <TextView android:id="@+id/tv_item" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:textColor="#23ffffff" android:textSize="25sp" /> </LinearLayout>這里唯一值得一說的是文本的顏色。大家看見他是8位的,前兩位是表示不透明度的,后六位是表示顏色的,三色,范圍都是00~ff。如果在java中設置顏色,需要這樣。
setTextColor(0x23ffffff);關于不透明度,一般美工會定義。有些要求不透明如30%這樣的,可以用整型換算一下。00~ff對應十進制為0~255,那么30%就是255x0.3=76.5,用科學計算機換算為4c。
然后我們就要寫一個類,我這繼承子線性布局。有兩個構造函數,我們主要在兩個參數的函數中工作。
public class LevelMenuItem extends LinearLayout { public LevelMenuItem(Context context, AttributeSet attrs) { super(context, attrs); }這個類中我們要完成的工作是,初始化控件屬性、提供外部修改屬性的接口、控件點擊的回調接口。
此類完整代碼:
package com.linc.game; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; /** * 自定義一個關卡 * 共有7個屬性,看attr文件 * 在程序中提供修改這7個屬性的接口, * 一個自定義控件的任務就算完成。 * 一個自定義控件的好處就是把一些需要模塊化的 * UI和邏輯放在一起,做到了高內聚,向其他模塊提供接口并很少 * 依賴外界,這樣就是低耦合。一個自定義控件就是一個封閉的王國, * 這里由你掌控。 * * 編寫時,如果遇到在attr里寫好屬性,但是在這里認不出來, * 就clean一下項目。切記。 * * @author linc * */ public class LevelMenuItem extends LinearLayout { private TextView mTextView = null; private ImageView mImageView = null; private OnItemClickListener mOnClickListener = null; public LevelMenuItem(Context context) { super(context); } public LevelMenuItem(Context context, AttributeSet attrs) { super(context, attrs); LayoutInflater layoutInflater = (LayoutInflater) context. getSystemService(Context.LAYOUT_INFLATER_SERVICE); layoutInflater.inflate(R.layout.level_menu_item, this); TypedArray typedArray = context.obtainStyledAttributes(attrs ,R.styleable.LevelMenuItem); initWidget(typedArray); } private void initWidget(TypedArray typedArray) { mTextView = (TextView)findViewById(R.id.tv_item); String textString = typedArray.getString(R.styleable.LevelMenuItem_text); int textColor = typedArray.getColor(R.styleable.LevelMenuItem_text_color, 0xffffffff); float textSize = typedArray.getDimension(R.styleable.LevelMenuItem_text_size, 20); mTextView.setText(textString); mTextView.setTextColor(textColor); mTextView.setTextSize(textSize); mImageView = (ImageView)findViewById(R.id.image_item); int imageHeight = (int) typedArray.getDimension(R.styleable.LevelMenuItem_image_height, 25); int imageWidth = (int) typedArray.getDimension(R.styleable.LevelMenuItem_image_width, 25); int imageSrc = typedArray.getResourceId(R.styleable.LevelMenuItem_image_src, 0); int imageBg = typedArray.getResourceId(R.styleable.LevelMenuItem_image_bg, 0); int imageAlpha = typedArray.getInt(R.styleable.LevelMenuItem_image_alpha, 255); mImageView.setAlpha(imageAlpha); mImageView.setImageResource(imageSrc); mImageView.setBackgroundResource(imageBg); LayoutParams layoutParams = new LayoutParams(imageWidth, imageHeight); mImageView.setLayoutParams(layoutParams); typedArray.recycle(); } /** * 設置此控件的文本 * @param text */ public void setText(String text) { mTextView.setText(text); } /** * 設置文字顏色 * @param textColor */ public void setTextColor(int textColor) { mTextView.setTextColor(textColor); } /** * 設置字體大小 * @param textSize */ public void setTextSize(int textSize) { mTextView.setTextSize(textSize); } /** * 設置圖片 * @param resId */ public void setImageResource(int resId) { mImageView.setImageResource(resId); } /** * 設置圖片背景 */ public void setBackgroundResource(int resId) { mImageView.setBackgroundResource(resId); } /** * 設置圖片的不透名度 * @param alpha */ public void setImageAlpha(int alpha) { mImageView.setAlpha(alpha); } /** * 設置圖片的大小 * 這里面需要使用LayoutParams這個布局參數來設置 * @param width * @param height */ public void setImageSize(int width,int height) { LayoutParams layoutParams = new LayoutParams(width, height); mImageView.setLayoutParams(layoutParams); } /** * image點擊事件的回調 * @param listener */ public void setOnClickListener(OnItemClickListener listener) { this.mOnClickListener = listener; mImageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mOnClickListener.onImageClick(); } }); } /** * 點擊事件接口 * @author linc * */ public interface OnItemClickListener { public void onImageClick(); } }好,一個完整的組合控件就做好了,那么,我們如何使用呢?
我要在LevelMenu中用它。xml文件如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:linc="http://schemas.android.com/apk/res/com.linc.game" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal"> <com.linc.game.LevelMenuItem android:id="@+id/item1" android:layout_width="70dp" android:layout_height="80dp" linc:text="@string/item1" linc:text_size="14sp" linc:text_color="#80fa8072" linc:image_src="@drawable/orange_button_selector" linc:image_alpha="128" linc:image_height="48dp" linc:image_width="48dp" /> <com.linc.game.LevelMenuItem android:id="@+id/item2" android:layout_marginLeft="20dp" android:layout_width="70dp" android:layout_height="80dp" linc:text="@string/item2" linc:text_size="14sp" linc:text_color="#ffeee8aa" linc:image_src="@drawable/red_button_selector" linc:image_alpha="255" linc:image_height="48dp" linc:image_width="48dp" /> <com.linc.game.LevelMenuItem android:id="@+id/item3" android:layout_marginLeft="20dp" android:layout_width="70dp" android:layout_height="80dp" linc:text="@string/item3" linc:text_size="14sp" linc:text_color="#80cd853f" linc:image_src="@drawable/yellow_button_selector" linc:image_alpha="128" linc:image_height="48dp" linc:image_width="48dp" /> </LinearLayout>加入自己包名的索引剩下的就一目了然了。
LevelMenu.java
package com.linc.game; import com.linc.game.LevelMenuItem.OnItemClickListener; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.widget.LinearLayout; public class LevelMenu extends LinearLayout { private LevelMenuItem item1,item2,item3; public LevelMenu(Context context) { super(context); } public LevelMenu(Context context, AttributeSet attrs) { super(context, attrs); LayoutInflater layoutInflater = (LayoutInflater) context. getSystemService(Context.LAYOUT_INFLATER_SERVICE); layoutInflater.inflate(R.layout.level_menu, this); initWidget(); } private void initWidget() { item1 = (LevelMenuItem)findViewById(R.id.item1); item2 = (LevelMenuItem)findViewById(R.id.item2); item3 = (LevelMenuItem)findViewById(R.id.item3); item1.setOnClickListener(new OnItemClickListener() { @Override public void onImageClick() { Log.e("dfjdkfjd","dfdfd"); } }); } }在處理圖片點擊事件的時候,我用到了選擇器(selector),這是我們實際開發中最常用的小技巧了。它能描述的狀態很多,各位看官可以去查查。
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_pressed="true" android:drawable="@drawable/button_push"/> <item android:drawable="@drawable/orange_button"/> </selector>好,組合控件的例子先到這里,實際功能在下一個實戰技巧中演練。
大家在做自定義控件時需要注意的是:
1、自定義控件類不能是是抽象類
2、要用(Context context, AttributeSet attrs)這個構造函數
否則報錯:android.view.InflateException: Binary XML file line #15: Error inflating cla。。。
本文由用戶 fmms 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!