該文章筆記代碼是從慕課網(wǎng)自定義view課程中學(xué)習(xí)到的炕吸,有興趣的同學(xué)可以學(xué)習(xí)一下
我們需要實(shí)現(xiàn)的自定義view的樣式
看似簡單其實(shí),兩個(gè)button勉痴,一個(gè)textview赫模,但是其實(shí)用自定義都是需要我們在class中挨個(gè)添加的而且,這個(gè)耦合性低蒸矛,更好當(dāng)作一個(gè)應(yīng)用的標(biāo)題工具類進(jìn)行擴(kuò)展
第一步
創(chuàng)建一個(gè)自定義view的視圖瀑罗,我們需要把命名空間需要自己定義的屬性給定義好
- 在res/values/文件夾下創(chuàng)建attrs.xml文件,用來自定義屬性
- 需要聲明 declare-styleable 屬性名,這是我們自定義的一些屬性名,在這里要注意一下format為屬性格式雏掠,reference與color一起定義的話可以引用drawable下的圖片或者十六進(jìn)制的顏色格式斩祭。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Topbar">
<attr name="title" format="string" />
<attr name="titleTextSize" format="dimension" />
<attr name="titleTextColor" format="color" />
<attr name="leftTextColor" format="color" />
<attr name="leftBackground" format="reference|color" />
<attr name="leftText" format="string" />
<attr name="rightTextColor" format="color" />
<attr name="rightBackground" format="reference|color" />
<attr name="rightText" format="string" />
</declare-styleable>
</resources>
- 自定義一個(gè)類繼承自RelativeLayout,用相對布局進(jìn)行實(shí)現(xiàn),當(dāng)然線性布局也可以
package com.yinhao.myui;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* Created by yinhao on 2017/10/13.
*/
public class Topbar extends RelativeLayout {
private Button leftButton, rightButton;
private TextView tvTitle;
private int leftTextColor;
private Drawable leftBackground;
private String leftText;
private int rightTextColor;
private Drawable rightBackground;
private String rightText;
private int titleTextColor;
private float titleTextSize;
private String title;
private LayoutParams leftParams, rightParams, titleParams;
private TopbarClickListener listener;
public Topbar(Context context) {
this(context, null);
}
public Topbar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public Topbar(final Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.Topbar);
leftTextColor = ta.getColor(R.styleable.Topbar_leftTextColor, 0);
leftBackground = ta.getDrawable(R.styleable.Topbar_leftBackground);
leftText = ta.getString(R.styleable.Topbar_leftText);
rightTextColor = ta.getColor(R.styleable.Topbar_rightTextColor, 0);
rightBackground = ta.getDrawable(R.styleable.Topbar_rightBackground);
rightText = ta.getString(R.styleable.Topbar_rightText);
titleTextSize = ta.getDimension(R.styleable.Topbar_titleTextSize, 0);
titleTextColor = ta.getColor(R.styleable.Topbar_titleTextColor, 0);
title = ta.getString(R.styleable.Topbar_title);
ta.recycle();//回收乡话,避免浪費(fèi)資源摧玫,避免因?yàn)榫彺嬉鸬囊恍╁e(cuò)誤
leftButton = new Button(context);
rightButton = new Button(context);
tvTitle = new TextView(context);
leftButton.setTextColor(leftTextColor);
leftButton.setBackground(leftBackground);
leftButton.setText(leftText);
rightButton.setTextColor(rightTextColor);
rightButton.setBackground(rightBackground);
rightButton.setText(rightText);
tvTitle.setTextColor(titleTextColor);
tvTitle.setTextSize(titleTextSize);
tvTitle.setText(title);
tvTitle.setGravity(Gravity.CENTER);
setBackgroundColor(0xfff59563);
leftParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
addView(leftButton, leftParams);
rightParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
rightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, TRUE);
addView(rightButton, rightParams);
titleParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
titleParams.addRule(RelativeLayout.CENTER_IN_PARENT, TRUE);
addView(tvTitle, titleParams);
leftButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.leftClick();
}
});
rightButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.rightClick();
}
});
}
public interface TopbarClickListener {
void leftClick();
void rightClick();
}
public void setOnTopbarClickListener(TopbarClickListener listener) {
this.listener = listener;
}
}
我們來分步解釋一下代碼,在我寫的attrs.xml文件中绑青,定義了9個(gè)自定義的屬性诬像,分別是左邊右邊按鈕的名字,背景和文字顏色闸婴。中間是標(biāo)題名稱坏挠,文字大小以及顏色。
我們應(yīng)該如何在類中引用呢邪乍?context類中有一個(gè)方法obtainStyledAttributes降狠,調(diào)用context.obtainStyledAttributes方法返回一個(gè)TypedArray類对竣,我們自定義的屬性集都在這個(gè)類中,參數(shù)是我們開始定義的declare-styleable的name值
接著我們就可以調(diào)用ta.getXXX的方法把每個(gè)單獨(dú)的自定義屬性取出來,這時(shí)候的格式是declare-styleable的name值加上每個(gè)單獨(dú)的自定義的值喊熟。有些參數(shù)為兩個(gè)參數(shù)柏肪,第二個(gè)為默認(rèn)值,我們填0即可芥牌。
接著我們將自定義的button通過一些我們常用的Button或者TextView的一些方法將從TypedArray中取出來的值進(jìn)行綁定烦味。
那么現(xiàn)在還差一步,我們只是定義了顏色壁拉,可是在哪里聲明控件呢谬俄?控件的大小怎么辦,別急弃理,我們一步步來
控制大小和控件所在的位置溃论,我們需要new一個(gè)繼承自RelativeLayout的LayoutParams,通過ViewGroup下的LayoutParams設(shè)置寬高痘昌,接著我們要調(diào)用RelativeLayout下特有的方法钥勋,通過addRule方法這三個(gè)控件相對于布局中的哪個(gè)位置,第二個(gè)參數(shù)為RelativeLayout特有的TRUE值辆苔,并非boolean的那種true值算灸。最后通過addView方法將設(shè)置好的參數(shù)和控件放到咱們的主類里,也就是相對布局里面
如果我們想實(shí)現(xiàn)點(diǎn)擊方法驻啤,我們可以直接寫一個(gè)setOnClickListener內(nèi)置的方法去調(diào)用菲驴,我們也可以一個(gè)接口,通過接口骑冗,我們降低耦合性赊瞬,在以后每個(gè)不同的activity或者fragment中,自己再進(jìn)行修改
最后贼涩,我們就需要在xml中聲明控件了巧涧,把Topbar的全類名復(fù)制下來,這里要留意下遥倦,我們需要自定義一個(gè)命名空間褒侧,不然會(huì)出現(xiàn)找不到屬性名的問題。在這里谊迄,我定義了一個(gè)叫custom的名字。把命名空間最后一個(gè)android改成res-auto,如果你用的是eclipse開發(fā)項(xiàng)目烟央,可以使用Topbar的全類名统诺。
這樣,我們定義的自定義標(biāo)頭就算是完成了疑俭。