自定義控件
當android提供的控件不滿足需求時, 我們需要自己去定製所需要的控件. 例如在一個TV項目中, 我們需要一種button, 當不選擇時, 文本顏色是白色, 當選中時, 文本顏色是黑色, 這時android中自帶的button是無法實現的, 那麼我們需要去自己定製這種控件.
自定義控件的步驟一般分爲:
(1). 聲明一個view對象, 繼承相對佈局,或者線性佈局或者其他的ViewGroup.
(2). 在自定義的View對象的構造方法裏面就把佈局都初始化完畢.
(3). 根據需求, 擴展自定義控件.
根據需求我們去實現改變文本顏色的button, 命名爲DButton, 首先:
1. 設置自定屬性
在 value 目錄下創建 名爲 attrs.xml文件, 在此文件中聲明自定義的屬性
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<declare-styleable name="DButton">
<attr name="normalColor" format="reference|color" />
<attr name="selectedColor" format="reference|color" />
<attr name="text" format="reference|string" />
<attr name="textSize" format="dimension" />
</declare-styleable>
</resources>
通過normalColor屬性來設置button沒有選中時的文本顏色, selectedColor屬性來設置button選中時的文本狀態.
關於format屬性有:
dimension 尺寸值
reference 資源ID
color 顏色值
boolean 布爾值
float 浮點值
integer 整型值
string 字符串
enum 枚舉值
flag 位或運算
這些屬性可以組合使用, 例如上面的 format="reference | color"
2. 創建DButton對象, 繼承LinearLayout
public class DButton extends LinearLayout {
private TextView mTextView;
private Context mContext = null;
private int mNormalColor;
private int mSelectedColor;
public DButton(Context context) {
super(context);
initController(context);
setGravity(Gravity.CENTER);
LayoutParams params = new LayoutParams(R.dimen.ltbutton_default_width, R.dimen.ltbutton_default_height);
setLayoutParams(params);
}
public DButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initController(context);
setAttributeSet(attrs);
}
public DButton(Context context, AttributeSet attrs) {
super(context, attrs);
initController(context);
setAttributeSet(attrs);
}
private void initController(Context context) {
mContext = context;
mNormalColor = Color.WHITE;
mSelectedColor = Color.BLACK;
mTextView = new TextView(context);
mTextView.setTextColor(mNormalColor);
addView(mTextView);
setProperty();
setFocusDrawer(getResources().getDrawable(R.drawable.focus_1));
}
private void setProperty() {
setFocusable(true);
setFocusableInTouchMode(true);
}
private void setAttributeSet(AttributeSet attrs) {
TypedArray typeArray = mContext.obtainStyledAttributes(attrs, R.styleable.DButton);
final String text = typeArray.getString(R.styleable.DButton_text);
if (!TextUtils.isEmpty(text)) {
setText(text);
}
final int normalColor = typeArray.getColor(R.styleable.DButton_normalColor, Color.WHITE);
if (normalColor != Color.WHITE) {
mNormalColor = normalColor;
setTextColor(mNormalColor);
}
final int selectColor = typeArray.getColor(R.styleable.DButton_selectedColor, Color.BLACK);
if (selectColor != Color.BLACK) {
mSelectedColor = selectColor;
}
final int size = typeArray.getDimensionPixelOffset(R.styleable.DButton_textSize, 0);
if (size != 0) {
setTextSize(size);
}
typeArray.recycle();
}
public void setTextColor(int color) {
mTextView.setTextColor(color);
}
public void setTextSize(float size) {
mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
}
public void setText(String text) {
mTextView.setText(text);
}
@Override
protected void onFocusChanged(boolean gainFocus, int direction,
Rect previouslyFocusedRect) {
int color = isFocused() ? mSelectedColor : mNormalColor;
mTextView.setTextColor(color);
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
}
}
這段代碼主要是重寫onFocusChanged方法, 來實現選中與不選中時控制文本顏色.
在setAttributeSet方法中調用 obtainStyledAttributes獲取attrs中的屬性, 存入到typearray數組容器中.當操作完需要調用recycle()方法來實現回收.
這樣就能解析自定義控件的屬性設置, 來進行後續操作, 在這裏去獲取兩種color, 設置button的text與textsize.
3. 使用自定義控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/custom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#999999"
android:orientation="vertical" >
<com.example.DButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
custom:text="DButton" />
</LinearLayout>
聲明自定義空間 xmlns:custom="http://schemas.android.com/apk/res/custom“ 使用自定義控件屬性。下面會說道在其他項目中使用自定義控件的聲明定義空間不太一樣。
至此, 自定義控件實現完成.
如何在其他工程中使用自定義控件?
1. 在eclipse(或ADT)中
(1) 通過jar包的方式
將自定義控件工程打成jar包, 然後將此jar包copy到引用的工程的libs目錄下, 這時候需要注意:(當你的自定義控件引用了資源文件,需要將這些資源文件copy一份到引用控件的工程中. 例如DButton中使用了focus_1的圖片作爲DButton的背景, 那麼這個時候我們再去使用DButton控件時, 需要將圖片資源和attrs.xml複製到引用工程中).
在xml中去使用DButton控件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto/custom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#999999"
android:orientation="vertical"
tools:ignore="ResAuto">
<com.example.DButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
custom:text="DButton" />
</LinearLayout>
使用 xmlns:custom="http://schemas.android.com/apk/res-auto/custom"來加載命名空間, 這時候會報錯, 需要加上tools:ignore="ResAuto" 來忽視錯誤.
(2) 通過library方式
如果不想將資源文件和attrs.xml複製到工程中, 將自定義控件作爲library來進行編譯, 在引用工程中去add這個library.
將項目作爲library:
選中項目, 右鍵-->properties->android->選中is library--> 點擊確定. 此時項目作爲library.
引用項目使用自定義控件:
1).選中項目, 右鍵-->properties->android->在is library下有add按鈕去添加library, 點擊add選中自定義控件library.
2).在項目的配置文件中增加:android.library.reference.1=../library的名字
注意: 引入的project需要與當前使用項目統一目錄,而且R文件會生成在當前項目中,要避免資源重名
接下來使用自定義控件方式和上面一樣.
2. 在android studio中
android studio提供一種類似jar包的方式, aar包.通過aar包我們也不需要將資源文件與attrs文件copy到引用工程中.
生成aar包需要將項目作爲android library, 所以如果想使用aar包, 需要在android studio中創建一個moudle(其實就是eclipse中的project) 作爲android library, 然後再把代碼移植到這裏, 然後編譯出aar包, aar包在build-->outputs-->aar目錄下.
使用aar包:
(1) 把打好的aar包copy到引用的工程libs目錄下
(2) 修改Android studio的gradle設置
添加下面代碼
repositories{
flatDir{
dirs 'libs'
}
}
並且在dependencies中導入arr包
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
compile(name: 'app', ext: 'aar') //導入名爲app的aar包
}
接下來就可以使用自定義控件了, 使用方法和在eclipse中一樣.