自定义控件的基本要求

这篇文章就当是自定义控件入门,看了几篇android关于自定义控件的文章,了解了一下,android自定义控件主要有3种方式:

  1. 自绘控件:继承View类,所展示的内容在OnDraw方法中绘制出来
  2. 组合控件:不需要绘制视图显示的内容,只用系统原生的控件,将几个控件组合起来,(这就是这篇文章要写的自定义标题栏)
  3. 继承控件:继承原生的控件类,在原生的属性上增加新的功能。

这篇文章所要写的是第二种方式组合控件,来实现自定义标题栏。总结这4点实现一个组合控件的基本要求:

1.在XML布局中可设置组合控件自定义的属性。

2.在代码总可设置属性和方法。

3.UI交互:布局美观,按下,点击等效果。

4.自定义回调事件

先来看看最终实现的效果图:

自定义标题栏的实现(使用的是include标签)

自定义标题栏的好处:

  • 提高布局效率
  • 降低布局文件的维护成本
  • 方便使用,容易扩展
  • 降低标题栏和Activity代码逻辑的耦合

我们先来看看布局文件:TitleBar.axml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="56dp">
  5. <Button
  6. android:id="@+id/titleBar_left_btn"
  7. android:layout_width="wrap_content"
  8. android:layout_height="wrap_content"
  9. android:layout_alignParentLeft="true"
  10. android:layout_centerVertical="true"
  11. android:layout_marginLeft="5dp"
  12. android:text="返回"
  13. android:drawableLeft="@drawable/icon_white_arrow_left"
  14. android:background="@android:color/transparent"
  15. android:textSize="14sp" />
  16. <TextView
  17. android:id="@+id/title_bar_title"
  18. android:layout_width="wrap_content"
  19. android:layout_height="wrap_content"
  20. android:layout_centerInParent="true"
  21. android:text="测试标题"
  22. android:singleLine="true"
  23. android:textSize="17sp" />
  24. <Button
  25. android:id="@+id/titleBar_right_btn"
  26. android:layout_width="wrap_content"
  27. android:layout_height="wrap_content"
  28. android:layout_alignParentRight="true"
  29. android:layout_centerVertical="true"
  30. android:layout_marginLeft="5dp"
  31. android:text="提交"
  32. android:textSize="14sp"
  33. android:background="@android:color/transparent"/>
  34. </RelativeLayout>

然后在需要的地方通过include标签引用

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent">
  6. <include layout="@layout/TitleBar" />
  7. </LinearLayout>

在MainActivity中添加单击事件,或者设置属性

  1. [Activity(Label = "CustomeTitleBar", MainLauncher = true, Icon = "@drawable/icon")]
  2. public class MainActivity : Activity
  3. {
  4. private TextView title_bar_title;
  5. private Button title_bar_left_btn;
  6. private Button title_bar_right_btn;
  7. protected override void OnCreate(Bundle bundle)
  8. {
  9. base.OnCreate(bundle);
  10. SetContentView (Resource.Layout.Main);
  11. title_bar_left_btn = FindViewById<Button>(Resource.Id.titleBar_left_btn);
  12. title_bar_right_btn = FindViewById<Button>(Resource.Id.titleBar_right_btn);
  13. title_bar_title = FindViewById<TextView>(Resource.Id.title_bar_title);
  14. title_bar_title.Text = "新的标题";
  15. title_bar_left_btn.Click += (s, e) => {
  16. Finish();
  17. };
  18. title_bar_right_btn.Click += (s, e) =>
  19. {
  20. Toast.MakeText(this,"提交",ToastLength.Short).Show();
  21. };
  22. }
  23. }

上面的这种方式与我们自定义控件的要求相差较远,不能自定义属性,不能事件的回调。并不推荐这种方式。如果说一直用include标签的话,这个自定义标题栏好像是写给自己用的似的。

自定义标题栏的实现(自定义属性、回调事件)

(1)定义标题栏的组合布局

我们还是写来自定义一个布局,还是用上面的那个布局,不过最外层的根布局RelativeLayout就不要了,使用merge标签,避免这种嵌套布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <merge xmlns:android="http://schemas.android.com/apk/res/android">
  3. <Button
  4. android:id="@+id/titleBar_left_btn"
  5. android:layout_width="wrap_content"
  6. android:layout_height="wrap_content"
  7. android:layout_alignParentLeft="true"
  8. android:layout_centerVertical="true"
  9. android:layout_marginLeft="5dp"
  10. android:gravity="left|center_vertical"
  11. android:background="@android:color/transparent"
  12. android:textSize="14sp" />
  13. <TextView
  14. android:id="@+id/title_bar_title"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:layout_centerInParent="true"
  18. android:singleLine="true"
  19. android:textSize="17sp" />
  20. <Button
  21. android:id="@+id/titleBar_right_btn"
  22. android:layout_width="wrap_content"
  23. android:layout_height="wrap_content"
  24. android:layout_alignParentRight="true"
  25. android:layout_centerVertical="true"
  26. android:layout_marginRight="5dp"
  27. android:background="@android:color/transparent"
  28. android:gravity="right|center_vertical"
  29. android:textSize="14sp" />
  30. </merge>

(2)自定标题栏相关的自定义属性

在values文件夹新建一个xml文件attrs.xml,关于android中自定义属性format的取值类型有以下这些:

  1. reference:如android:background = “@drawable/图片ID”
  2. color:如android:textColor = “#000000”
  3. boolean:如android:focusable = “false”
  4. dimenion:如android:layout_width = “10dp”
  5. float :如android:fromAlpha = “1.0”
  6. integer:如android:background = “@drawable/图片ID”
  7. string:如android:text=”123”
  8. fraction:百分数如:android:pivotY = “300%”
  9. enum:如android:orientation=”vertical”
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <resources>
  3. <declare-styleable name="CustomeTitleBar">
  4. <attr name="title_background_color" format="color"/>
  5. <attr name="title_text" format="string"/>
  6. <attr name="title_text_color" format="color"/>
  7. <attr name="right_button_text" format="string"/>
  8. <attr name="right_button_text_color" format="color"/>
  9. <attr name="right_button_drawable" format="reference|integer"/>
  10. <attr name="right_button_visible" format="boolean"/>
  11. <attr name="left_button_text" format="string"/>
  12. <attr name="left_button_text_color" format="color"/>
  13. <attr name="left_button_drawable" format="reference|integer"/>
  14. <attr name="left_button_visible" format="boolean"/>
  15. </declare-styleable>
  16. </resources>

(3)自定义标题栏代码的实现,根据不同的需求继承不同的原生ViewGroup类,这里继承的是RelativeLayout,也可以LinearLayout、EditText。

  1. public class MyTitleBar : RelativeLayout
  2. {
  3. private TextView title_bar_title;
  4. private Button title_bar_left_btn;
  5. private Button title_bar_right_btn;
  6. public MyTitleBar(Context context, IAttributeSet attrs) : base(context, attrs)
  7. {
  8. //base(context, attrs);
  9. LayoutInflater.From(context).Inflate(Resource.Layout.TitleBar, this, true);
  10. title_bar_left_btn = FindViewById<Button>(Resource.Id.titleBar_left_btn);
  11. title_bar_right_btn = FindViewById<Button>(Resource.Id.titleBar_right_btn);
  12. title_bar_title = FindViewById<TextView>(Resource.Id.title_bar_title);
  13. try
  14. {
  15. TypedArray attributes = context.ObtainStyledAttributes(attrs, Resource.Styleable.CustomeTitleBar);
  16. if (attributes != null)
  17. {
  18. //titlebar 背景颜色
  19. int titleBarBackground = attributes.GetResourceId(Resource.Styleable.CustomeTitleBar_title_background_color,Resource.Color.color_primary);
  20. SetBackgroundResource(titleBarBackground);
  21. //左边按钮
  22. //是否显示
  23. bool leftButtonVisible = attributes.GetBoolean(Resource.Styleable.CustomeTitleBar_left_button_visible, true);
  24. if (leftButtonVisible)
  25. {
  26. title_bar_left_btn.Visibility = ViewStates.Visible;
  27. }
  28. else
  29. {
  30. title_bar_left_btn.Visibility = ViewStates.Gone;
  31. }
  32. //设置左边按钮的文字和图标(二者只能选其一)
  33. string leftButtonText = attributes.GetString(Resource.Styleable.CustomeTitleBar_left_button_text);
  34. if (!string.IsNullOrEmpty(leftButtonText))
  35. {
  36. title_bar_left_btn.Text = leftButtonText;
  37. //设置左边按钮的文字颜色
  38. Color leftButtonTextColor = attributes.GetColor(Resource.Styleable.CustomeTitleBar_left_button_text_color, Color.White);
  39. title_bar_left_btn.SetTextColor(leftButtonTextColor);
  40. }
  41. else //(不设置文本,就只能设置图标)
  42. {
  43. int leftButtonDrawable = attributes.GetResourceId(Resource.Styleable.CustomeTitleBar_left_button_drawable, Resource.Drawable.icon_white_arrow_left);
  44. if (leftButtonDrawable != -1)
  45. {
  46. Drawable drawable = Resources.GetDrawable(leftButtonDrawable);
  47. drawable.SetBounds(0, 0, drawable.MinimumWidth,drawable.MinimumHeight);//不设置这句图标显示不出来
  48. title_bar_left_btn.SetCompoundDrawables(drawable,null,null,null);
  49. }
  50. }
  51. //右边按钮
  52. //是否显示
  53. bool rightButtonVisible = attributes.GetBoolean(Resource.Styleable.CustomeTitleBar_right_button_visible, true);
  54. if (rightButtonVisible)
  55. {
  56. title_bar_right_btn.Visibility = ViewStates.Visible;
  57. }
  58. else
  59. {
  60. title_bar_right_btn.Visibility = ViewStates.Gone;
  61. }
  62. //设置左边按钮的文字和图标(二者只能选其一)
  63. string rightButtonText = attributes.GetString(Resource.Styleable.CustomeTitleBar_right_button_text);
  64. if (!string.IsNullOrEmpty(rightButtonText))
  65. {
  66. title_bar_right_btn.Text = rightButtonText;
  67. //设置左边按钮的文字颜色
  68. Color leftButtonTextColor = attributes.GetColor(Resource.Styleable.CustomeTitleBar_right_button_text_color, Color.White);
  69. title_bar_right_btn.SetTextColor(leftButtonTextColor);
  70. }
  71. else //(不设置文本,就只能设置图标)
  72. {
  73. int rightButtonDrawable = attributes.GetResourceId(Resource.Styleable.CustomeTitleBar_right_button_drawable, Resource.Drawable.icon_white_arrow_left);
  74. if (rightButtonDrawable != -1)
  75. {
  76. Drawable drawable = Resources.GetDrawable(rightButtonDrawable);
  77. drawable.SetBounds(0,0,drawable.MinimumHeight,drawable.MinimumHeight);
  78. title_bar_right_btn.SetCompoundDrawables(null, null,drawable, null);
  79. }
  80. }
  81. //处理标题
  82. string titleText = attributes.GetString(Resource.Styleable.CustomeTitleBar_title_text);
  83. if (!string.IsNullOrEmpty(titleText))
  84. {
  85. title_bar_title.Text = titleText;
  86. }
  87. Color color = attributes.GetColor(Resource.Styleable.CustomeTitleBar_title_text_color,Color.White);
  88. title_bar_title.SetTextColor(color);
  89. attributes.Recycle();
  90. }
  91. }
  92. catch (Exception ex)
  93. {
  94. System.Diagnostics.Debug.Write(ex.ToString());
  95. }
  96. }
  97. //设置事件的监听
  98. public void SetTitleClickListener(IOnClickListener onClickListener)
  99. {
  100. if (onClickListener != null)
  101. {
  102. title_bar_left_btn.SetOnClickListener(onClickListener);
  103. title_bar_right_btn.SetOnClickListener(onClickListener);
  104. }
  105. }
  106. //获取左边的Button
  107. public Button GetTitleBarLeftBtn()
  108. {
  109. return title_bar_left_btn;
  110. }
  111. //获取右边的Button
  112. public Button GetTitleRightBtn()
  113. {
  114. return title_bar_right_btn;
  115. }
  116. //获取标题
  117. public TextView GetTitleBarTitle()
  118. {
  119. return title_bar_title;
  120. }
  121. }

(4)使用自定义标题栏,并且自定义属性

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:mview="http://schemas.android.com/apk/res-auto"
  4. android:orientation="vertical"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent">
  7. <CustomeTitleBar.MyTitleBar
  8. android:id="@+id/myTitleBar"
  9. android:layout_width="match_parent"
  10. android:layout_height="50dp"
  11. android:layout_marginTop="10dp"
  12. mview:title_text="测试标题"
  13. mview:right_button_text=""
  14. mview:right_button_text_color="@color/color_white"
  15. mview:right_button_visible="true"
  16. mview:left_button_text="返回"/>
  17. <CustomeTitleBar.MyTitleBar
  18. android:id="@+id/myTitleBar"
  19. android:layout_width="match_parent"
  20. android:layout_height="50dp"
  21. android:layout_marginTop="10dp"
  22. mview:title_text="标题2"
  23. mview:right_button_text="提交"
  24. mview:right_button_text_color="@color/color_white"
  25. mview:left_button_text="返回"
  26. mview:left_button_text_color="@color/color_white"/>
  27. <CustomeTitleBar.MyTitleBar
  28. android:id="@+id/myTitleBar"
  29. android:layout_width="match_parent"
  30. android:layout_height="50dp"
  31. android:layout_marginTop="10dp"
  32. mview:title_text="标题2"
  33. mview:right_button_visible="false"
  34. mview:left_button_text="返回"
  35. mview:left_button_text_color="@color/color_white"/>
  36. <CustomeTitleBar.MyTitleBar
  37. android:id="@+id/myTitleBar"
  38. android:layout_width="match_parent"
  39. android:layout_height="50dp"
  40. android:layout_marginTop="10dp"
  41. mview:title_text="标题2"
  42. mview:title_background_color="@color/color_red"
  43. mview:right_button_text_color="@color/color_white"
  44. mview:left_button_text="返回"
  45. mview:left_button_text_color="@color/color_red"/>
  46. </LinearLayout>

上面的代码基本实现了与activity逻辑代码的分离、UI界面要求、可配置自定义属性的要求,可最关键的事件的回调还没写,的确这是最核心的地方,这个自定义标题栏的两个按钮的单击事件最终还是要在activity中去调用。

这个就留着下次再写吧。

如果觉得还有点懵逼的话,看看github:https://github.com/MaChuZhang/Xamarin-Android-Custom-View/tree/master/CustomeTitleBar

作者:张林

标题:xamarin android自定义标题栏(自定义属性、回调事件)

原文地址:http://blog.csdn.net/kebi007/article/details/75365917

转载随意注明出处

[置顶] xamarin android自定义标题栏(自定义属性、回调事件)的更多相关文章

  1. [置顶] xamarin android自定义spinner

    以前弄的一个下拉框时自带的spinner,感觉好丑,实际效果实在满足不了基本的UI界面要求,还是自己动手丰衣足食,看了网上关于android中自定义spinner的文章,感觉实现原理还是比较简单,所以 ...

  2. [置顶] Xamarin android沉浸式状态栏

    虽然关于android "沉浸式"状态栏有很多博客介绍过,从小菜到大神无一例外.我第一次看到这种"沉浸"式的效果我也以为真的是这么叫,然而根本不是这么回事,完全 ...

  3. [置顶] xamarin android使用zxing扫描二维码

    好久没写了,这片文章篇幅不长,概述一下在xamarin android中用 ZXing.Net.Mobile库扫描二维码读取url的示例.扫码支付,扫码登录,App上各种各样的扫码,好像没个扫码的就有 ...

  4. [置顶] xamarin android toolbar(踩坑完全入门详解)

    网上关于toolbar的教程有很多,很多新手,在使用toolbar的时候踩坑实在太多了,不好好总结一下,实在浪费.如果你想学习toolbar,你肯定会去去搜索androd toolbar,既然你能看到 ...

  5. [置顶] xamarin android使用gps定位获取经纬度

    看了文章你会得出以下几个结论 1.android定位主要有四种方式GPS,Network(wifi定位.基站定位),AGPS定位 2.绝大部分android国产手机使用network进行定位是没有作用 ...

  6. [置顶] xamarin android 布局尺寸了解

    为了使UI界面在不同大小的移动端显示器上能够正常显示,大家可能都知道使用sp作为字体大小的单位,dp作为其他元素长度的单位. 前几天看了一篇文章关于 App设计规范的,文章用心写的非常好,这里是链接  ...

  7. [置顶] xamarin android Fragment实现底部导航栏

    前段时间写了篇关于Fragment的文章,介绍了基础的概念,用静态和动态的方式加载Fragment  Xamarin Android Fragment的两种加载方式.下面的这个例子介绍xamarin ...

  8. [置顶] Xamarin android中使用signalr实现即时通讯

    前面几天也写了一些signalr的例子,不过都是在Web端,今天我就来实践一下如何在xamarin android中使用signalr,刚好工作中也用到了这个,也算是总结一下学到的东西吧,希望能帮助你 ...

  9. [置顶] Xamarin android如何调用百度地图入门示例(一)

    在Xamarin android如何调用百度地图呢? 首先我们要区分清楚,百度地图这是一个广泛的概念,很多刚刚接触这个名词"百度地图api",的确是泛泛而谈,我们来看一下百度地图的 ...

随机推荐

  1. python/numpy/tensorflow中,对矩阵行列操作,下标是怎么回事儿?

    Python中的list/tuple,numpy中的ndarrray与tensorflow中的tensor. 用python中list/tuple理解,仅仅是从内存角度理解一个序列数据,而非数学中标量 ...

  2. iBatis & myBatis & Hibernate 要点记录

    iBatis & myBatis & Hibernate 要点记录 这三个是当前常用三大持久层框架,对其各自要点简要记录,并对其异同点进行简单比较. 1. iBatis iBatis主 ...

  3. 跨域请求cookie获取与设置问题

    描述:最近做项目遇到了cookie的问题,项目为前后端分离项目,前台有分外网IP(A外)和内网IP(A内),后台服务只有一个内网IP(B内). 现象:当我前台异步请求发送给后台的时候,后台并不能获取到 ...

  4. 网络分析法(Analytic Network Process,ANP)

    什么是网络分析法 网络分析法(ANP)是美国匹兹堡大学的T.L.Saaty教授于1996年提出的一种适应非独立的递阶层次结构的决策方法,它是在层次分析法(Analytic Hierarchy Proc ...

  5. 照虎画猫写自己的Spring——自定义注解

    Fairy已经实现的功能 读取XML格式配置文件,解析得到Bean 读取JSON格式配置文件,解析得到Bean 基于XML配置的依赖注入 所以,理所当然,今天该实现基于注解的依赖注入了. 基于XML配 ...

  6. selenium 定位input输入框下的选择项

    今天的问题与下图中的类似 这是一个input型输入框,当我点击或输入值时,输入框下方会显示选择项帮助快速输入,代码如下: <input class="v-input some" ...

  7. [PHP]Symfony or Laravel 在 console 中结合 Workerman

    在web框架的console中,命令不再是直接指定入口文件,如以往 php test.php start,而是类似 php app/console do 的形式. workerman 对命令的解析是 ...

  8. 前端测试框架Jest系列教程 -- 简介

    写在前面: 随着互联网日新月异的发展,用户对于页面的美观度,流畅度以及各方面的体验有了更高的要求,我们的网页不再是简单的承载文字,图片等简单的信息传递给用户,我们需要的是更加美观的页面展示,更快的浏览 ...

  9. CCF-201312-3-最大的矩形

    问题描述 试题编号: 201312-3 试题名称: 最大的矩形 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i(1 ≤ ...

  10. Selenium中如何使用xpath更快定位

    在学习Selenium路上,踩了也不少坑,这是我最近才发现的一个新写法,好吧,"才发现"又说明我做其他事了.对的,我现在还在加班! 开车~~~ 例子:知乎网 标签:Python3. ...