前言:很多时候我们需要将一些控件组合起来封装成一个新的完整的控件重复地运用在APP中,这篇博客通过一个例子把完整的步骤记录下来。
接下来封装一个简单的标题栏,效果如下:
简单分析一下该标题栏,标题栏整体是一个RelativeLayout,该布局下左右各一个Button,中间是一个TextView用来显示标题,然后该整体作为一个新的UI模板控件重复使用。
1.既然是一个UI模板,必须得具有属性更改的灵活性,因此将其中可能需要修改的属性定义出来,在/res/values下创建attrs.xml文件,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TopBar">
<attr name="leftText" format="string" />
<attr name="leftTextSize" format="dimension" />
<attr name="leftTextBackground" format="reference|color" />
<attr name="titleText" format="string" />
<attr name="titleTextSize" format="dimension" />
<attr name="rightText" format="string" />
<attr name="rightTextSize" format="dimension" />
<attr name="rightTextBackground" format="reference|color" />
<attr name="textColor" format="color" />
<attr name="mainBackground" format="reference|color" />
</declare-styleable>
</resources>
2.新建一个类TopBar.java,继承自RelativeLayout,并添加三个构造方法,代码如下:
public class TopBar extends RelativeLayout {
private String mLeftText;
private float mLeftTextSize;
private Drawable mLeftTextBackground;
private String mTitleText;
private float mTitleTextSize;
private String mRightText;
private float mRightTextSize;
private Drawable mRightTextBackground;
private int mTextColor;
private Drawable mMainBackground;
private Button mLeftButton;
private TextView mTitleView;
private Button mRightButton;
public TopBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public TopBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TopBar(Context context) {
this(context, null);
}
}
原本父布局应该是继承自ViewGroup的,由于我们使用的是RelativeLayout,因此直接继承RelativeLayout,这样既拥有了ViewGroup的特性又获得了RelativeLayout的方法,简单方便。
3.在构造方法中添加如下代码用于获取attrs.xml中定义的属性:
//获取属性
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TopBar, defStyle, 0);
int n = a.getIndexCount();
for (int i=0; i<n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.TopBar_leftText:
mLeftText = a.getString(attr);
break;
case R.styleable.TopBar_leftTextSize:
mLeftTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 24, getResources().getDisplayMetrics()
));
break;
case R.styleable.TopBar_leftTextBackground:
mLeftTextBackground = a.getDrawable(attr);
break;
case R.styleable.TopBar_titleText:
mTitleText = a.getString(attr);
break;
case R.styleable.TopBar_titleTextSize:
mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 24, getResources().getDisplayMetrics()
));
break;
case R.styleable.TopBar_rightText:
mRightText = a.getString(attr);
break;
case R.styleable.TopBar_rightTextSize:
mRightTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 24, getResources().getDisplayMetrics()
));
break;
case R.styleable.TopBar_rightTextBackground:
mRightTextBackground = a.getDrawable(attr);
break;
case R.styleable.TopBar_textColor:
mTextColor = a.getColor(attr, 0xFFFFFF);
break;
case R.styleable.TopBar_mainBackground:
mMainBackground = a.getDrawable(attr);
break;
}
}
a.recycle();
TypedArray用来获取自定义的属性集,遍历获取后别忘了调用recycle()方法释放资源。
4.向RelativeLayout添加子View,将控件组合起来:
//组合控件
mLeftButton = new Button(context);
mTitleView = new TextView(context);
mRightButton = new Button(context);
mLeftButton.setText(mLeftText);
mLeftButton.setTextSize(mLeftTextSize);
mLeftButton.setBackground(mLeftTextBackground);
mLeftButton.setTextColor(mTextColor);
mTitleView.setText(mTitleText);
mTitleView.setTextSize(mTitleTextSize);
mTitleView.setGravity(Gravity.CENTER);
mTitleView.setTextColor(mTextColor);
mRightButton.setText(mRightText);
mRightButton.setTextSize(mRightTextSize);
mRightButton.setBackground(mRightTextBackground);
mRightButton.setTextColor(mTextColor);
this.setBackground(mMainBackground); //设定RelativeLayout背景图
//给控件设定属性
LayoutParams leftParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
addView(mLeftButton, leftParams);
LayoutParams titleParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
titleParams.addRule(RelativeLayout.CENTER_IN_PARENT, TRUE);
addView(mTitleView, titleParams);
LayoutParams rightParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
rightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, TRUE);
addView(mRightButton, rightParams);
5.为了Butoon的灵活性创建回调接口供其使用:
public interface TopBarOnClickListener {
void leftClick();
void rightClick();
}
6.创建一个方法用于注册接口回调:
//暴露一个方法给调用者注册接口回调
public void setTopBarOnClickListener(TopBarOnClickListener listener) {
mListener = listener;
}
7.给两个Button设定按键监听,回调接口方法:
//按键监听
mLeftButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mListener.leftClick();
}
});
mRightButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mListener.rightClick();
}
});
8.在activity_main.xml运用该控件:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.administrator.topbar.TopBar
android:id="@+id/id_top_bar"
android:layout_width="match_parent"
android:layout_height="40dp"
custom:leftText="返回"
custom:leftTextSize="5sp"
custom:leftTextBackground="@drawable/top_bar_back_bg"
custom:titleText="标题"
custom:titleTextSize="5sp"
custom:rightText="编辑"
custom:rightTextSize="5sp"
custom:rightTextBackground="@drawable/top_bar_edit_bg"
custom:textColor="#FFFFFF"
custom:mainBackground="@drawable/top_bar_bg" />
<TextView
android:id="@+id/id_tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello World!"
android:gravity="center"/>
</LinearLayout>
使用自定义属性别忘了加上xmlns:custom="http://schemas.android.com/apk/res-auto
9.在MainActivity.java下给按键编写具体实现代码:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView tv = (TextView) findViewById(R.id.id_tv);
TopBar topBar = (TopBar) findViewById(R.id.id_top_bar);
topBar.setTopBarOnClickListener(new TopBar.TopBarOnClickListener() {
@Override
public void leftClick() {
tv.setText("你点击了返回!");
}
@Override
public void rightClick() {
tv.setText("你点击了编辑!");
}
});
}
}
至此该组合控件编码完毕,在需要使用的xml下<com.xxx.TopBar>即可。
源码地址:http://download.csdn.net/detail/chenhao0428/9581774