Android - 自定义控件(四)
在一个应用中,很多页面的titlebar布局都是类似的,比如,最左侧一个返回箭头,中间是title,右侧要么是文字要么是图标要么是空白,实现方式一般有以下几种:
1、分别针对每一种可能用到的布局写一个布局文件,然后根据需要在activity的布局中采用include的方式将title布局引入进来
2、类似Android - 自定义控件(三)的方式写一个自定义的titlebar
3、采用自定义属性的方式
本篇文章通过自定义属性来完成一个自定义的titlebar,假设该titlebar的左侧固定为图片,中间固定为文本,而右侧为图片或者文本。则完成步骤如下:
一、首先在res/values文件目录下创建一个attrs.xml文件。然后在attrs.xml文件中完成对属性的定义,代码片段如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- TitleBar -->
<declare-styleable name="TitleBar">
<attr name="background" format="reference|color" />
<attr name="title" format="string" localization="suggested" />
<attr name="leftImg" format="reference" />
<attr name="rightImg" format="reference" />
<attr name="rightText" format="reference" />
</declare-styleable>
</resources>
<attr>标签的format属性值代表属性的类型,这个类型值一共有10种,分别是:reference,float,color,dimension,boolean,string,enum,integer,fraction,flag。常用的基本上只有reference,float,color,dimension,boolean,string,enum这7种。枚举类型定义的格式为:
<attr name="flowDirection" format="enum">
<enum name="leftToRight" value="0" />
<enum name="topDown" value="1" />
<enum name="rightToLeft" value="2" />
<enum name="bottomUp" value="3" />
</attr>
在attrs.xml文件中的<declare-styleable>标签的name属性的值,按照惯例我们都是写成自定义控件类的名字。一个同名的<attr>在attrs.xml中只可以定义一次。
二、编写自定义的类,在构造方法中获取我们设置的值(即在XML文件中引入自定义控件时,设置的属性),代码:
public class TitleBar extends LinearLayout {
private RelativeLayout rlTitle;
/** 左按钮 */
private View btnleft;
/** 右按钮 */
private View btnRight;
/** 标题文本 */
private String title;
/** 标题控件 */
private TextView tvTitle;
public TitleBar(Context context) {
super(context);
}
public TitleBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public TitleBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
@SuppressLint("NewApi")
private void init(Context context, AttributeSet attrs) {
setOrientation(LinearLayout.HORIZONTAL);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitleBar);
CharSequence csTitle = a.getText(R.styleable.TitleBar_title);
Drawable bgDrawable = a.getDrawable(R.styleable.TitleBar_background);
int leftImg = a.getResourceId(R.styleable.TitleBar_leftImg, -1);
int rightImg = a.getResourceId(R.styleable.TitleBar_rightImg, -1);
CharSequence rightText = a.getText(R.styleable.TitleBar_rightText);
View view = null;
int type = 0;//0:右侧按钮模式;1:右侧文本模式
if (rightText != null && !"".equals(rightText)) {
type = 1;
view = LayoutInflater.from(getContext()).inflate(R.layout.layout_top_right_text, this, true);
} else {
view = LayoutInflater.from(getContext()).inflate(R.layout.layout_top, this, true);
}
rlTitle = (RelativeLayout) view.findViewById(R.id.rl_title);
tvTitle = (TextView) view.findViewById(R.id.tv_title);
ImageButton ib_left = (ImageButton) view.findViewById(R.id.btn_left);
btnleft = ib_left;
if (csTitle != null && !"".equals(csTitle)) {
tvTitle.setText(csTitle);
}
rlTitle.setVisibility(View.VISIBLE);
if (leftImg != -1) {
ib_left.setVisibility(View.VISIBLE);
ib_left.setImageResource(leftImg);
} else {
ib_left.setVisibility(View.INVISIBLE);
}
if (type == 0) {//0:右侧按钮模式
ImageButton ib_right = (ImageButton) view.findViewById(R.id.btn_right);
if (rightImg != -1) {
ib_right.setVisibility(View.VISIBLE);
ib_right.setImageResource(rightImg);
} else {
ib_right.setVisibility(View.INVISIBLE);
}
btnRight = ib_right;
} else {//1:右侧文本模式
Button btn_right = (Button) view.findViewById(R.id.btn_right);
if (rightText != null && !"".equals(rightText)) {
btn_right.setText(rightText);
btn_right.setVisibility(View.VISIBLE);
} else {
btn_right.setVisibility(View.INVISIBLE);
}
btnRight = btn_right;
}
if (bgDrawable != null) {
if (Build.VERSION.SDK_INT >= 16) {
rlTitle.setBackground(bgDrawable);
} else {
rlTitle.setBackgroundDrawable(bgDrawable);
}
} else {//缺省颜色
rlTitle.setBackgroundColor(Color.parseColor("#365663"));
}
a.recycle();
}
public View getBtnleft() {
return btnleft;
}
public View getBtnRight() {
return btnRight;
}
public String getTitle() {
return title;
}
/**
* 设置标题文本
* @param title
*/
public void setTitle(int title) {
setTitle(getResources().getString(title));
}
/**
* 设置标题文本
* @param title
*/
public void setTitle(String title) {
this.title = title;
if (title == null || "".equals(title)) {
rlTitle.setVisibility(View.GONE);
} else {
rlTitle.setVisibility(View.VISIBLE);
tvTitle.setText(title);
}
invalidate();
}
}
需要注意的是,TypedArray对象在使用完毕后一定要调用recycle()方法。
三、在布局文件中引入自定义的titlebar:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:hwgt="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.hwgttitlebar.MainActivity" >
<com.example.hwgttitlebar.view.TitleBar
android:id="@+id/titleBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
hwgt:leftImg="@drawable/ic_arrow"
hwgt:title="@string/hwgt_title"
hwgt:rightText="@string/hwgt_right_text"/>
</RelativeLayout>
需要注意的是,要在使用自定义属性的布局文件中声明命名空间:
xmlns:hwgt="http://schemas.android.com/apk/res-auto"
以上三步就搞定了,下边是其他涉及到的代码:
layout_top_right_text.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rl_title" android:layout_width="match_parent" android:layout_height="54dp"> <ImageButton android:id="@+id/btn_left" android:layout_width="54dp" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:src="@drawable/ic_arrow" android:visibility="visible" android:background="@drawable/sel_bg_btn_title"/> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_centerVertical="true" android:layout_toRightOf="@id/btn_left" android:layout_toLeftOf="@+id/btn_right" android:paddingLeft="5dp" android:paddingRight="5dp" android:gravity="center" android:text="" android:textColor="@android:color/white" android:textSize="20dp" android:singleLine="true" android:maxLines="1" android:ellipsize="none"/> <Button android:id="@id/btn_right" android:layout_width="wrap_content" android:layout_height="match_parent" android:minWidth="54dp" android:text="" android:textColor="@android:color/white" android:textSize="15dp" android:paddingLeft="4dp" android:paddingRight="12dp" android:layout_alignParentRight="true" android:background="@drawable/sel_bg_btn_title"/> </RelativeLayout>
layout_top.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rl_title" android:layout_width="match_parent" android:layout_height="54dp"> <ImageButton android:id="@+id/btn_left" android:layout_width="54dp" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:src="@drawable/ic_arrow" android:visibility="visible"/> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_centerVertical="true" android:layout_toRightOf="@id/btn_left" android:layout_toLeftOf="@+id/btn_right" android:paddingLeft="5dp" android:paddingRight="5dp" android:gravity="center" android:text="" android:textColor="@android:color/white" android:textSize="20dp" android:singleLine="true" android:maxLines="1" android:ellipsize="none"/> <ImageButton android:id="@id/btn_right" android:layout_width="54dp" android:layout_height="match_parent" android:layout_alignParentRight="true" android:background="@drawable/sel_bg_btn_title" android:visibility="invisible"/> <ImageView android:id="@+id/iv_logo" android:layout_width="54dp" android:layout_height="match_parent" android:layout_alignParentRight="true" android:paddingLeft="2dp" android:paddingRight="2dp" android:scaleType="fitCenter" android:visibility="gone"/> </RelativeLayout>
drawable下的sel_bg_btn_title.xml:
<?xml version="1.0" encoding="UTF-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/bg_btn_title_press" android:state_pressed="true" /> <item android:drawable="@android:color/darker_gray"/> </selector>
bg_btn_title_press.xml:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#33ffffff"/>
</shape>
浙公网安备 33010602011771号