经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
Android如何创建自定义ActionBar
来源:jb51  时间:2018/11/25 19:38:43  对本文有异议

当多个界面都有很多相似部分时,可以考虑创建一个功能较全的模板。而在需要时,可以通过引用模板来实现自己想要实现的功能。比如适配器 Adapter,当很多的适配器都差不多时,就可以通过打造一个通用的适配器来实现。本例中主要是如何创建自定义的 ActionBar。

观察上图的,当切换界面时,每个界面的顶部最多只有两个图标,而且有4个界面具有类似特性。所以可以考虑通过自定义控件来创建UI模板。

由于是需要创建出具有重用功能的复合控件,所以通常需要继承 ViewGroup ,在给它添加指定功能的控制。给其指定一些可配置的属性,让其具有更强的扩展性。

本例可以简单的创建一个 TopBar 来继承 RelativeLayout,并在 values 文件下新建一个 attrs.xml 布局文件,该文件用于定义 ActionBar 的属性。

attrs.xml :

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <declare-styleable name="TopBar" >
  4. <attr name="topbar_left_icon" format="reference" />
  5. <attr name="topbar_right_icon" format="reference" />
  6. </declare-styleable>
  7. </resources>

其中:<declare-styleable name="TopBar" > 中的 name 值为继承自 RelativeLayout的类名,这样做的好处是在自定义属性较多时,能够很好的辨认出自定义的属性属于谁,属于哪个地方的自定义。当然也可以不用和继承自 RelativeLayout 的类名相同;由于 ActionBar 最多时只有 2 张图片,不需要其他属性(如果想在点击图标时改变图颜色等,还可以定义 format 的 color 值),所以给每张图片定义一个图片的引用即可,即:<attr name="topbar_left_icon" format="reference" /> 其中 format 指定的值为 reference,reference 表示图片的引用。

创建一个只有两张图片的布局文件,这样做的好处是在自定义控件的类中可以减少代码量,不必在该类中创建 ImageView ,也能更好的让 xml 完成 UI 界面设置,而 Java 程序则专门负责业务逻辑。

topbar_layout.xml :

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_margin="6dp"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content">
  6. <ImageView
  7. android:id="@+id/topbar_left_img"
  8. android:layout_marginLeft="6dp"
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content" />
  11. <ImageView
  12. android:id="@+id/topbar_right_img"
  13. android:layout_marginRight="20dp"
  14. android:layout_alignParentRight="true"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content" />
  17. </RelativeLayout>

该布局只有两个横向的 ImageView 且都没有指定 src 属性。

创建一个 TopBar 类用于继承 RelativeLayout。

TopBar.java :

  1. package com.crazy.gemi.ui.topbar;
  2. import android.content.Context;
  3. import android.content.res.TypedArray;
  4. import android.graphics.drawable.Drawable;
  5. import android.util.AttributeSet;
  6. import android.util.Log;
  7. import android.view.View;
  8. import android.widget.ImageView;
  9. import android.widget.RelativeLayout;
  10. import com.crazy.gemi.R;
  11. public class TopBar extends RelativeLayout {
  12. private Drawable draw_left;
  13. private Drawable draw_right;
  14. public TopBar(Context context) {
  15. this(context, null);
  16. }
  17. public TopBar(Context context, AttributeSet attrs) {
  18. this(context, attrs, 0);
  19. }
  20. public TopBar(Context context, AttributeSet attrs, int defStyleAttr) {
  21. super(context, attrs, defStyleAttr);
  22. init(attrs, defStyleAttr);
  23. }
  24. private void init(AttributeSet attrs, int defStyleAttr) {
  25. // 系统提供了 TypedArray 来获取自定义的属性集
  26. TypedArray typedArray = null;
  27. try {
  28. typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.TopBar,defStyleAttr,-1);
  29. draw_left = typedArray.getDrawable(R.styleable.TopBar_topbar_left_icon);
  30. draw_right = typedArray.getDrawable(R.styleable.TopBar_topbar_right_icon);
  31. } finally {
  32. // 获取完所有的属性值后要回收资源
  33. typedArray.recycle();
  34. }
  35. View view = View.inflate(getContext(), R.layout.topbar_layout, this);
  36. ImageView imgLeft = (ImageView)view.findViewById(R.id.topbar_left_img);
  37. ImageView imgRight = (ImageView)view.findViewById(R.id.topbar_right_img);
  38. imgLeft.setImageDrawable(draw_left);
  39. imgRight.setImageDrawable(draw_right);
  40. }
  41. }

其中需要注意的是:

        1. 获取完属性值后,要记得回收资源。将其放入 finally 语句块中,就一定能够回收,不管前面是否出问题等。
        2. 先加载该布局文件:View view = View.inflate(getContext(), R.layout.topbar_layout, this); 其中的 this 为该 TopBar 对象的引用,将其添加到 RelativeLayout 中;给图片赋值,如:imgLeft.setImageDrawable(draw_left);

        由此可以看出避免了在该类中出现 ImageView  imgLeft  =  new  ImageView(content); 的创建 ImageView 对象的代码,也避免可为组件元素设置相应的布局元素的问题,如:

  1. // 为组件设置相应的布局元素(左边)
  2. LayoutParams leftParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  3. leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
  4. // 添加到 ViewGroup
  5. addView(imgLeft, leftParams);
  6. // 为组件设置相应的布局元素(右边)
  7. LayoutParams rightParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  8. leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
  9. // 添加到 ViewGroup
  10. addView(imgRight,rightParams);

当然该自定义的空间还不完善,可以在该类中添加接口,以方便点击图标时有相应的回调。这里也就没有去创建该接口了。

接下来就是在需要的引用该模板:

先创建自己的名字空间:xmlns:custom="http://schemas.android.com/apk/res-auto" 其中 custom 为自定义的名字,res-auto 也可以改为该应用的包名。下面简单创建一个布局,以此来演示对该 UI 模板的引用。

效果如下:

代码如下:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. xmlns:custom="http://schemas.android.com/apk/res-auto"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. tools:context="com.crazy.gemi.ui.pocket.PocketFragment">
  7. <com.crazy.gemi.ui.topbar.TopBar
  8. android:id="@+id/pocket_top_bar"
  9. android:background="@drawable/bg_cheaper_fg"
  10. android:layout_width="match_parent"
  11. android:layout_height="wrap_content"
  12. custom:topbar_left_icon="@drawable/pocket_logo"
  13. custom:topbar_right_icon="@drawable/abc_btn_radio_to_on_mtrl_015"/>
  14. <com.warmtel.expandtab.ExpandPopTabView
  15. android:id="@+id/fg_pocket_expandtab_view"
  16. android:layout_below="@id/pocket_top_bar"
  17. android:layout_width="match_parent"
  18. android:layout_height="wrap_content"
  19. custom:tab_toggle_btn_bg="@drawable/bg_expa_near"
  20. custom:tab_toggle_btn_font_color="@android:color/black"/>
  21. <ImageView
  22. android:id="@+id/fg_pocket_img"
  23. android:layout_below="@id/fg_pocket_expandtab_view"
  24. android:scaleType="centerCrop"
  25. android:src="@drawable/pocket_bg"
  26. android:layout_width="match_parent"
  27. android:layout_height="match_parent" />
  28. </RelativeLayout>

其中用 custom:topbar_left_icon="" 来加载自己想要加载的图片(左边的图标)。这样就可以通过添加或者不添加 custom 属性来实现完对 UI 模板的引用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号