大家可能都用过QQ、微博,所谓的TopBar就是如图中的:
这里以上面的UI为例,记述一下怎么自定义View:
- 步骤一:新建一个attrs文件,定义视图属性
- 步骤二:继承一个View,或ViewGroup的子类,并可使用这些自定义的属性
- 步骤三:在资源文件或java代码中使用自己的View
自定义属性
在values文件夹下新建一个资源文件attrs.xml,整个项目的目录结构如下图所示:
由于整个Topbar由左右两个Button和中间一个TextView构成,所以设置的属性如下:
<declare-styleable name="TopBar" >
<!-- TextView的属性-->
<attr name="titleText" format="string"/>
<attr name="titleTextSize" format="dimension"/>
<attr name="titleTextColor" format="color"/>
<!-- LeftButton的属性-->
<attr name="leftText" format="string" />
<attr name="leftColor" format="color" />
<attr name="leftBackground" format="reference|color" />
<!-- RightButton的属性-->
<attr name="rightText" format="string" />
<attr name="rightColor" format="color" />
<attr name="rightBackground" format="reference|color" />
</declare-styleable>
自定义View
自定义一个View,继承一个View,或ViewGroup的子类,并可使用这些自定义的属性。我这里的TopBar继承的是RelativeLayout,下面直接贴出TopBar的代码,在代码里讲述实现的过程:
public class TopBar extends RelativeLayout{
//定义TopBar的组成控件
private Button leftButton,rightButton;
private TextView tvTitle;
//定义要获取的自定义属性
private String titleText,leftText,rightText;
private int leftTextColor,rightTextColor,titleTextColor;
private Drawable leftTextBackground,rightTextBackground;
private float titleTextSize;
//定义组成控件的布局
private RelativeLayout.LayoutParams leftParams,rightParams,titleParams;
private OnClickTopBarListener listener;
//接口回调,真正做到模版UI
public interface OnClickTopBarListener{
public void onLeftClickListener();
public void onRightClickListener();
}
//设置TopBar的左右Button点击事件
public void SetOnClickTopBarListener(OnClickTopBarListener listener){
this.listener=listener;
}
//由于自定义了属性值,所以选用带有AttributeSet参数的这个构造函数
public TopBar(Context context, AttributeSet attrs) {
super(context, attrs);
//.获取自定义属性的值/键值对
TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.TopBar);
//获取TypedArray里面的单个值,提取自定义属性
titleText=ta.getString(R.styleable.TopBar_titleText);
leftText =ta.getString(R.styleable.TopBar_leftText);
rightText=ta.getString(R.styleable.TopBar_rightText);
leftTextColor=ta.getColor(R.styleable.TopBar_leftColor,0);
rightTextColor=ta.getColor(R.styleable.TopBar_rightColor,0);
titleTextColor=ta.getColor(R.styleable.TopBar_titleTextColor,0);
leftTextBackground=ta.getDrawable(R.styleable.TopBar_leftBackground);
rightTextBackground=ta.getDrawable(R.styleable.TopBar_rightBackground);
titleTextSize=ta.getDimension(R.styleable.TopBar_titleTextSize,0);
//调用recycle()方法,对其进行回收
ta.recycle();
//设置Topbar的控件
leftButton=new Button(context);
rightButton=new Button(context);
tvTitle=new TextView(context);
//为控件绑定自定义的属性
leftButton.setText(leftText);
leftButton.setTextColor(leftTextColor);
leftButton.setBackground(leftTextBackground);
rightButton.setText(rightText);
rightButton.setTextColor(rightTextColor);
rightButton.setBackground(rightTextBackground);
tvTitle.setText(titleText);
tvTitle.setTextSize(titleTextSize);
tvTitle.setTextColor(titleTextColor);
tvTitle.setGravity(Gravity.CENTER);
//设置TopBar的背景色
setBackgroundColor(0xFFF59536);
//将leftButton添加到布局里,并设置宽高
leftParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);
addView(leftButton,leftParams);
//将rightButton添加到布局里,并设置宽高
rightParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
rightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);
addView(rightButton,rightParams);
//将tvTitle添加到布局里,并设置宽高
titleParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
titleParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);
addView(tvTitle,titleParams);
//通过接口回调机制设置左右Button的点击事件,使自定义View成为一个更好的模版UI,方便使用
leftButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.onLeftClickListener();
}
});
rightButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.onRightClickListener();
}
});
}
}
使用自定义的View
- 在布局文件中使用:
androidstudio里在布局中使用第三方控件时,修改命名空间:
xmlns:custom="http://schemas.android.com/apk/res-auto"
其中custom可以自定义。
布局文件activity_main.xml的代码如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<com.example.young.myapplication.TopBar
android:layout_height="40dp"
android:layout_width="match_parent"
android:id="@+id/topBar"
custom:titleText="自定义标题"
custom:titleTextColor="#123412"
custom:titleTextSize="10sp"
custom:leftText="back"
custom:leftColor="#FFFFFF"
custom:rightText="more"
custom:rightColor="#FFFFFF">
</com.example.young.myapplication.TopBar>
</RelativeLayout>
- 在代码中使用自定义View
MainActivity.java的代码如下:
public class MainActivity extends ActionBarActivity {
private TopBar myTopBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTopBar=(TopBar)this.findViewById(R.id.topBar);
myTopBar.SetOnClickTopBarListener(new TopBar.OnClickTopBarListener() {
@Override
public void onLeftClickListener() {
Toast.makeText(getApplicationContext(),"这是back",Toast.LENGTH_SHORT).show();
}
@Override
public void onRightClickListener() {
Toast.makeText(getApplicationContext(),"这是more",Toast.LENGTH_SHORT).show();
}
});
}
}
效果图
下面看一下效果图: