自定义控件的基本要求
这篇文章就当是自定义控件入门,看了几篇 android 关于自定义控件的文章,了解了一下,android 自定义控件主要有 3 种方式:
这篇文章所要写的是第二种方式组合控件,来实现自定义标题栏。总结这 4 点实现一个组合控件的基本要求:
1. 在 XML 布局中可设置组合控件自定义的属性。
2. 在代码总可设置属性和方法。
3.UI 交互:布局美观,按下,点击等效果。
4. 自定义回调事件
先来看看最终实现的效果图:
自定义标题栏的实现(使用的是 include 标签)
自定义标题栏的好处:
我们先来看看布局文件:TitleBar.axml
- <?xml version="1.0" encoding="utf-8" ?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent" android:layout_height="56dp">
- <Button android:id="@+id/titleBar_left_btn" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:layout_alignParentLeft="true"
- android:layout_centerVertical="true" android:layout_marginLeft="5dp" android:text="返回"
- android:drawableLeft="@drawable/icon_white_arrow_left" android:background="@android:color/transparent"
- android:textSize="14sp" />
- <TextView android:id="@+id/title_bar_title" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:layout_centerInParent="true"
- android:text="测试标题" android:singleLine="true" android:textSize="17sp" />
- <Button android:id="@+id/titleBar_right_btn" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:layout_alignParentRight="true"
- android:layout_centerVertical="true" android:layout_marginLeft="5dp" android:text="提交"
- android:textSize="14sp" android:background="@android:color/transparent"
- />
- </RelativeLayout>
然后在需要的地方通过 include 标签引用
- <?xml version="1.0" encoding="utf-8" ?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
- <include layout="@layout/TitleBar" />
- </LinearLayout>
在 MainActivity 中添加单击事件,或者设置属性
- [Activity(Label = "CustomeTitleBar", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity: Activity {
- private TextView title_bar_title;
- private Button title_bar_left_btn;
- private Button title_bar_right_btn;
- protected override void OnCreate(Bundle bundle) {
- base.OnCreate(bundle);
- SetContentView(Resource.Layout.Main);
- title_bar_left_btn = FindViewById < Button > (Resource.Id.titleBar_left_btn);
- title_bar_right_btn = FindViewById < Button > (Resource.Id.titleBar_right_btn);
- title_bar_title = FindViewById < TextView > (Resource.Id.title_bar_title);
- title_bar_title.Text = "新的标题";
- title_bar_left_btn.Click += (s, e) = >{
- Finish();
- };
- title_bar_right_btn.Click += (s, e) = >{
- Toast.MakeText(this, "提交", ToastLength.Short).Show();
- };
- }
- }
上面的这种方式与我们自定义控件的要求相差较远,不能自定义属性,不能事件的回调。并不推荐这种方式。如果说一直用 include 标签的话,这个自定义标题栏好像是写给自己用的似的。
自定义标题栏的实现(自定义属性、回调事件)
(1) 定义标题栏的组合布局
我们还是写来自定义一个布局,还是用上面的那个布局,不过最外层的根布局 RelativeLayout 就不要了,使用 merge 标签,避免这种嵌套布局
- <?xml version="1.0" encoding="utf-8" ?>
- <merge xmlns:android="http://schemas.android.com/apk/res/android">
- <Button android:id="@+id/titleBar_left_btn" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:layout_alignParentLeft="true"
- android:layout_centerVertical="true" android:layout_marginLeft="5dp" android:gravity="left|center_vertical"
- android:background="@android:color/transparent" android:textSize="14sp"
- />
- <TextView android:id="@+id/title_bar_title" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:layout_centerInParent="true"
- android:singleLine="true" android:textSize="17sp" />
- <Button android:id="@+id/titleBar_right_btn" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:layout_alignParentRight="true"
- android:layout_centerVertical="true" android:layout_marginRight="5dp" android:background="@android:color/transparent"
- android:gravity="right|center_vertical" android:textSize="14sp" />
- </merge>
(2)自定标题栏相关的自定义属性
在 values 文件夹新建一个 xml 文件 attrs.xml,关于 android 中自定义属性 format 的取值类型有以下这些:
- <?xml version="1.0" encoding="utf-8" ?>
- <resources>
- <declare-styleable name="CustomeTitleBar">
- <attr name="title_background_color" format="color" />
- <attr name="title_text" format="string" />
- <attr name="title_text_color" format="color" />
- <attr name="right_button_text" format="string" />
- <attr name="right_button_text_color" format="color" />
- <attr name="right_button_drawable" format="reference|integer" />
- <attr name="right_button_visible" format="boolean" />
- <attr name="left_button_text" format="string" />
- <attr name="left_button_text_color" format="color" />
- <attr name="left_button_drawable" format="reference|integer" />
- <attr name="left_button_visible" format="boolean" />
- </declare-styleable>
- </resources>
(3)自定义标题栏代码的实现,根据不同的需求继承不同的原生 ViewGroup 类,这里继承的是 RelativeLayout,也可以 LinearLayout、EditText。
- public class MyTitleBar: RelativeLayout {
- private TextView title_bar_title;
- private Button title_bar_left_btn;
- private Button title_bar_right_btn;
- public MyTitleBar(Context context, IAttributeSet attrs) : base(context, attrs) {
- //base(context, attrs);
- LayoutInflater.From(context).Inflate(Resource.Layout.TitleBar, this, true);
- title_bar_left_btn = FindViewById < Button > (Resource.Id.titleBar_left_btn);
- title_bar_right_btn = FindViewById < Button > (Resource.Id.titleBar_right_btn);
- title_bar_title = FindViewById < TextView > (Resource.Id.title_bar_title);
- try {
- TypedArray attributes = context.ObtainStyledAttributes(attrs, Resource.Styleable.CustomeTitleBar);
- if (attributes != null) {
- //titlebar 背景颜色
- int titleBarBackground = attributes.GetResourceId(Resource.Styleable.CustomeTitleBar_title_background_color, Resource.Color.color_primary);
- SetBackgroundResource(titleBarBackground);
- //左边按钮
- //是否显示
- bool leftButtonVisible = attributes.GetBoolean(Resource.Styleable.CustomeTitleBar_left_button_visible, true);
- if (leftButtonVisible) {
- title_bar_left_btn.Visibility = ViewStates.Visible;
- } else {
- title_bar_left_btn.Visibility = ViewStates.Gone;
- }
- //设置左边按钮的文字和图标(二者只能选其一)
- string leftButtonText = attributes.GetString(Resource.Styleable.CustomeTitleBar_left_button_text);
- if (!string.IsNullOrEmpty(leftButtonText)) {
- title_bar_left_btn.Text = leftButtonText;
- //设置左边按钮的文字颜色
- Color leftButtonTextColor = attributes.GetColor(Resource.Styleable.CustomeTitleBar_left_button_text_color, Color.White);
- title_bar_left_btn.SetTextColor(leftButtonTextColor);
- } else //(不设置文本,就只能设置图标)
- {
- int leftButtonDrawable = attributes.GetResourceId(Resource.Styleable.CustomeTitleBar_left_button_drawable, Resource.Drawable.icon_white_arrow_left);
- if (leftButtonDrawable != -1) {
- Drawable drawable = Resources.GetDrawable(leftButtonDrawable);
- drawable.SetBounds(0, 0, drawable.MinimumWidth, drawable.MinimumHeight); //不设置这句图标显示不出来
- title_bar_left_btn.SetCompoundDrawables(drawable, null, null, null);
- }
- }
- //右边按钮
- //是否显示
- bool rightButtonVisible = attributes.GetBoolean(Resource.Styleable.CustomeTitleBar_right_button_visible, true);
- if (rightButtonVisible) {
- title_bar_right_btn.Visibility = ViewStates.Visible;
- } else {
- title_bar_right_btn.Visibility = ViewStates.Gone;
- }
- //设置左边按钮的文字和图标(二者只能选其一)
- string rightButtonText = attributes.GetString(Resource.Styleable.CustomeTitleBar_right_button_text);
- if (!string.IsNullOrEmpty(rightButtonText)) {
- title_bar_right_btn.Text = rightButtonText;
- //设置左边按钮的文字颜色
- Color leftButtonTextColor = attributes.GetColor(Resource.Styleable.CustomeTitleBar_right_button_text_color, Color.White);
- title_bar_right_btn.SetTextColor(leftButtonTextColor);
- } else //(不设置文本,就只能设置图标)
- {
- int rightButtonDrawable = attributes.GetResourceId(Resource.Styleable.CustomeTitleBar_right_button_drawable, Resource.Drawable.icon_white_arrow_left);
- if (rightButtonDrawable != -1) {
- Drawable drawable = Resources.GetDrawable(rightButtonDrawable);
- drawable.SetBounds(0, 0, drawable.MinimumHeight, drawable.MinimumHeight);
- title_bar_right_btn.SetCompoundDrawables(null, null, drawable, null);
- }
- }
- //处理标题
- string titleText = attributes.GetString(Resource.Styleable.CustomeTitleBar_title_text);
- if (!string.IsNullOrEmpty(titleText)) {
- title_bar_title.Text = titleText;
- }
- Color color = attributes.GetColor(Resource.Styleable.CustomeTitleBar_title_text_color, Color.White);
- title_bar_title.SetTextColor(color);
- attributes.Recycle();
- }
- } catch(Exception ex) {
- System.Diagnostics.Debug.Write(ex.ToString());
- }
- }
- //设置事件的监听
- public void SetTitleClickListener(IOnClickListener onClickListener) {
- if (onClickListener != null) {
- title_bar_left_btn.SetOnClickListener(onClickListener);
- title_bar_right_btn.SetOnClickListener(onClickListener);
- }
- }
- //获取左边的Button
- public Button GetTitleBarLeftBtn() {
- return title_bar_left_btn;
- }
- //获取右边的Button
- public Button GetTitleRightBtn() {
- return title_bar_right_btn;
- }
- //获取标题
- public TextView GetTitleBarTitle() {
- return title_bar_title;
- }
- }
(4)使用自定义标题栏,并且自定义属性
- <?xml version="1.0" encoding="utf-8" ?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:mview="http://schemas.android.com/apk/res-auto" android:orientation="vertical"
- android:layout_width="match_parent" android:layout_height="match_parent">
- <CustomeTitleBar.MyTitleBar android:id="@+id/myTitleBar" android:layout_width="match_parent"
- android:layout_height="50dp" android:layout_marginTop="10dp" mview:title_text="测试标题"
- mview:right_button_text="" mview:right_button_text_color="@color/color_white"
- mview:right_button_visible="true" mview:left_button_text="返回" />
- <CustomeTitleBar.MyTitleBar android:id="@+id/myTitleBar" android:layout_width="match_parent"
- android:layout_height="50dp" android:layout_marginTop="10dp" mview:title_text="标题2"
- mview:right_button_text="提交" mview:right_button_text_color="@color/color_white"
- mview:left_button_text="返回" mview:left_button_text_color="@color/color_white"
- />
- <CustomeTitleBar.MyTitleBar android:id="@+id/myTitleBar" android:layout_width="match_parent"
- android:layout_height="50dp" android:layout_marginTop="10dp" mview:title_text="标题2"
- mview:right_button_visible="false" mview:left_button_text="返回" mview:left_button_text_color="@color/color_white"
- />
- <CustomeTitleBar.MyTitleBar android:id="@+id/myTitleBar" android:layout_width="match_parent"
- android:layout_height="50dp" android:layout_marginTop="10dp" mview:title_text="标题2"
- mview:title_background_color="@color/color_red" mview:right_button_text_color="@color/color_white"
- mview:left_button_text="返回" mview:left_button_text_color="@color/color_red"
- />
- </LinearLayout>
来源: http://blog.csdn.net/kebi007/article/details/75365917