当前位置:   article > 正文

Android自定义标题栏ActionBar_android action_bar_title

android action_bar_title

在日常的工作中,ActionBar使用的频率非常的高,而系统自带的ActionBar捆绑的东西有太多,而上面多数的效果我们都用不到。

如果不用系统的ActionBar,我们该怎样把自定义ActionBar的工作做到最简化呢。

首先我们做一个基本的需求分析。



如上图所示,我们的ActionBar通常包括了:左菜单, 标题, 右菜单 。如果要再细分一下, 菜单 = (图标 + 文本)。


需求确定后,代码就非常简单了。


actionbar_dft.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/lay_transroot"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content"
  6. android:background="@color/primary"
  7. android:orientation="vertical">
  8. <View
  9. android:id="@+id/v_statusbar"
  10. android:layout_width="match_parent"
  11. android:layout_height="1.0dp" />
  12. <RelativeLayout
  13. android:layout_width="match_parent"
  14. android:layout_height="@dimen/actionbar_height"
  15. android:orientation="vertical">
  16. <RelativeLayout
  17. android:id="@+id/lay_actionbar_left"
  18. android:layout_width="100dp"
  19. android:layout_height="match_parent"
  20. android:orientation="horizontal">
  21. <ImageView
  22. android:id="@+id/iv_actionbar_left"
  23. android:layout_width="20dp"
  24. android:layout_height="20dp"
  25. android:layout_centerVertical="true"
  26. android:layout_marginLeft="10dp"
  27. android:background="@mipmap/ic_left_light"
  28. android:visibility="gone" />
  29. <TextView
  30. android:id="@+id/tv_actionbar_left"
  31. style="@style/text_white"
  32. android:layout_height="match_parent"
  33. android:layout_marginLeft="10dp"
  34. android:layout_toRightOf="@+id/iv_actionbar_left"
  35. android:gravity="center_vertical"
  36. android:maxLength="2"
  37. android:singleLine="true"
  38. android:text="@string/cancel"
  39. android:visibility="gone" />
  40. </RelativeLayout>
  41. <TextView
  42. android:id="@+id/tv_actionbar_title"
  43. style="@style/text_white"
  44. android:layout_centerInParent="true"
  45. android:maxLength="15"
  46. android:text="@string/app_name"
  47. android:textSize="16sp" />
  48. <RelativeLayout
  49. android:id="@+id/lay_actionbar_right"
  50. android:layout_width="100dp"
  51. android:layout_height="match_parent"
  52. android:layout_alignParentRight="true"
  53. android:gravity="right"
  54. android:orientation="horizontal">
  55. <View
  56. android:id="@+id/v_actionbar_right"
  57. android:layout_width="20dp"
  58. android:layout_height="20dp"
  59. android:layout_alignParentRight="true"
  60. android:layout_centerVertical="true"
  61. android:layout_marginRight="10dp"
  62. android:visibility="gone" />
  63. <TextView
  64. android:id="@+id/tv_actionbar_right"
  65. style="@style/text_white"
  66. android:layout_height="match_parent"
  67. android:layout_marginRight="10dp"
  68. android:layout_toLeftOf="@+id/v_actionbar_right"
  69. android:gravity="center_vertical|right"
  70. android:singleLine="true"
  71. android:text="@string/confirm"
  72. android:visibility="gone" />
  73. </RelativeLayout>
  74. </RelativeLayout>
  75. </LinearLayout>


到这里,有的人可能会说,你把标题栏做这么简单,稍微有复杂一点的需求,根本满足不了。对此,我只想表示,我做过的项目类似老外趣聊、英语趣配音、淘wifi,其中不乏千万用户的APP,这样的ActionBar基本上能满足产品需求,而且非常轻便。如果内聚做的好,更可以定制出你想要actionbar样式。

有了 布局文件,我们再结合需求,添加一个点击回调,一般项目中标题是没有点击事件的,所以只要有左菜单、右菜单的点击回调就行。

回调接口:


  1. public interface ActionBarClickListener {
  2. void onLeftClick();
  3. void onRightClick();
  4. }


接下来我们就讨论一下,代码中如何集成、封装。


做法一: 代码中使用 <include ... /> 函数。


示例:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical">
  6. <include
  7. android:id="@+id/actionbar"
  8. layout="@layout/actionbar_dft"
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content" />
  11. <TextView
  12. android:id="@+id/tv_description"
  13. style="@style/text_black"
  14. android:padding="20dp" />
  15. </LinearLayout>

 做法非常的简单,曾经和一个面试官讨论过这种做法的弊端,面试官认为这种加载方式对性能有影响。这我是不认同的,include不但能提高代码的复用率,使代码更简洁,它还没有增加系统的GPU任务,所以,不会对性能造成影响。

使用的时候,inlude函数里一定要添加id,因为include的布局,layout中的id是不能传递的。


然后就是 Activity 里的实现了。


  1. protected View layRoot;
  2. protected View vStatusBar;
  3. protected View layLeft;
  4. protected View layRight;
  5. protected TextView tvTitle;
  6. protected TextView tvLeft;
  7. protected TextView tvRight;
  8. protected View iconLeft;
  9. protected View iconRight;
  10. /**
  11. * 设置数据
  12. *
  13. * @param strTitle
  14. * @param resIdLeft
  15. * @param strLeft
  16. * @param resIdRight
  17. * @param strRight
  18. * @param listener
  19. */
  20. public void setMyActionBar(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener) {
  21. View actionBar = findViewById(R.id.actionbar);
  22. layRoot = actionBar.findViewById(R.id.lay_transroot);
  23. vStatusBar = actionBar.findViewById(R.id.v_statusbar);
  24. tvTitle = (TextView) actionBar.findViewById(R.id.tv_actionbar_title);
  25. tvLeft = (TextView) actionBar.findViewById(R.id.tv_actionbar_left);
  26. tvRight = (TextView) actionBar.findViewById(R.id.tv_actionbar_right);
  27. iconLeft = actionBar.findViewById(R.id.iv_actionbar_left);
  28. iconRight = actionBar.findViewById(R.id.v_actionbar_right);
  29. if (!TextUtils.isEmpty(strTitle)) {
  30. tvTitle.setText(strTitle);
  31. } else {
  32. tvTitle.setVisibility(View.GONE);
  33. }
  34. if (!TextUtils.isEmpty(strLeft)) {
  35. tvLeft.setText(strLeft);
  36. tvLeft.setVisibility(View.VISIBLE);
  37. } else {
  38. tvLeft.setVisibility(View.GONE);
  39. }
  40. if (!TextUtils.isEmpty(strRight)) {
  41. tvRight.setText(strRight);
  42. tvRight.setVisibility(View.VISIBLE);
  43. } else {
  44. tvRight.setVisibility(View.GONE);
  45. }
  46. if (resIdLeft == 0) {
  47. iconLeft.setVisibility(View.GONE);
  48. } else {
  49. iconLeft.setBackgroundResource(resIdLeft);
  50. iconLeft.setVisibility(View.VISIBLE);
  51. }
  52. if (resIdRight == 0) {
  53. iconRight.setVisibility(View.GONE);
  54. } else {
  55. iconRight.setBackgroundResource(resIdRight);
  56. iconRight.setVisibility(View.VISIBLE);
  57. }
  58. if (listener != null) {
  59. layLeft = findViewById(R.id.lay_actionbar_left);
  60. layRight = findViewById(R.id.lay_actionbar_right);
  61. layLeft.setOnClickListener(new View.OnClickListener() {
  62. @Override
  63. public void onClick(View v) {
  64. listener.onLeftClick();
  65. }
  66. });
  67. layRight.setOnClickListener(new View.OnClickListener() {
  68. @Override
  69. public void onClick(View v) {
  70. listener.onRightClick();
  71. }
  72. });
  73. }
  74. }


有了上述代码,我们ActionBar的基本功能就可以使用了。但是,如果每个Activity里面都这么写,是不是会很繁琐。所以我们需要简单的封装一下。封装代码如下:

  1. package com.myactionbar.base;
  2. import android.os.Bundle;
  3. import android.support.annotation.Nullable;
  4. import android.support.v7.app.AppCompatActivity;
  5. import android.text.TextUtils;
  6. import android.view.View;
  7. import android.widget.TextView;
  8. import com.myactionbar.R;
  9. import com.myactionbar.impl.ActionBarClickListener;
  10. /**
  11. * Created by 晖仔(Milo) on 2017-03-21.
  12. * email:303767416@qq.com
  13. */
  14. public abstract class FirstBaseActivity extends AppCompatActivity {
  15. protected View layRoot;
  16. protected View vStatusBar;
  17. protected View layLeft;
  18. protected View layRight;
  19. protected TextView tvTitle;
  20. protected TextView tvLeft;
  21. protected TextView tvRight;
  22. protected View iconLeft;
  23. protected View iconRight;
  24. protected abstract int getContentViewId();
  25. protected abstract void init();
  26. @Override
  27. protected void onCreate(@Nullable Bundle savedInstanceState) {
  28. super.onCreate(savedInstanceState);
  29. setContentView(getContentViewId());
  30. init();
  31. }
  32. /**
  33. * 设置数据
  34. *
  35. * @param strTitle
  36. * @param resIdLeft
  37. * @param strLeft
  38. * @param resIdRight
  39. * @param strRight
  40. * @param listener
  41. */
  42. public void setMyActionBar(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener) {
  43. View actionBar = findViewById(R.id.actionbar);
  44. layRoot = actionBar.findViewById(R.id.lay_transroot);
  45. vStatusBar = actionBar.findViewById(R.id.v_statusbar);
  46. tvTitle = (TextView) actionBar.findViewById(R.id.tv_actionbar_title);
  47. tvLeft = (TextView) actionBar.findViewById(R.id.tv_actionbar_left);
  48. tvRight = (TextView) actionBar.findViewById(R.id.tv_actionbar_right);
  49. iconLeft = actionBar.findViewById(R.id.iv_actionbar_left);
  50. iconRight = actionBar.findViewById(R.id.v_actionbar_right);
  51. if (!TextUtils.isEmpty(strTitle)) {
  52. tvTitle.setText(strTitle);
  53. } else {
  54. tvTitle.setVisibility(View.GONE);
  55. }
  56. if (!TextUtils.isEmpty(strLeft)) {
  57. tvLeft.setText(strLeft);
  58. tvLeft.setVisibility(View.VISIBLE);
  59. } else {
  60. tvLeft.setVisibility(View.GONE);
  61. }
  62. if (!TextUtils.isEmpty(strRight)) {
  63. tvRight.setText(strRight);
  64. tvRight.setVisibility(View.VISIBLE);
  65. } else {
  66. tvRight.setVisibility(View.GONE);
  67. }
  68. if (resIdLeft == 0) {
  69. iconLeft.setVisibility(View.GONE);
  70. } else {
  71. iconLeft.setBackgroundResource(resIdLeft);
  72. iconLeft.setVisibility(View.VISIBLE);
  73. }
  74. if (resIdRight == 0) {
  75. iconRight.setVisibility(View.GONE);
  76. } else {
  77. iconRight.setBackgroundResource(resIdRight);
  78. iconRight.setVisibility(View.VISIBLE);
  79. }
  80. if (listener != null) {
  81. layLeft = findViewById(R.id.lay_actionbar_left);
  82. layRight = findViewById(R.id.lay_actionbar_right);
  83. layLeft.setOnClickListener(new View.OnClickListener() {
  84. @Override
  85. public void onClick(View v) {
  86. listener.onLeftClick();
  87. }
  88. });
  89. layRight.setOnClickListener(new View.OnClickListener() {
  90. @Override
  91. public void onClick(View v) {
  92. listener.onRightClick();
  93. }
  94. });
  95. }
  96. }
  97. }

完成以上代码,我们只需要在具体的Activity中实现方法

 public void setMyActionBar(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener)

就行了。


但是,不知道心细的同学发现没有。这样写代码有一个非常大的弊端,就是BaseActivity里多出了好多代码(我们知道BaseActivity肯定还有非常多的其他代码,所以,尽量让我们的BaseActivity越简单越好)。那有什么办法减少BaseActivity里的代码量呢,同时也提高我们自身代码的内聚(让actionBar只为actionBar而用)呢。

那这里我们就要用到做法二。


做法二:自定义名为MyActionBar 的 widget。

大致思想就是自定义View,选一个layout布局填充,layout里面包括ActionBar的所有内容(左菜单、标题、右菜单)。

代码如下:

  1. package com.myactionbar.widget;
  2. import android.content.Context;
  3. import android.support.v4.graphics.ColorUtils;
  4. import android.text.TextUtils;
  5. import android.util.AttributeSet;
  6. import android.view.View;
  7. import android.view.ViewGroup;
  8. import android.widget.LinearLayout;
  9. import android.widget.TextView;
  10. import com.myactionbar.R;
  11. import com.myactionbar.impl.ActionBarClickListener;
  12. /**
  13. * 支持渐变的 actionBar
  14. * Created by 晖仔(Milo) on 2016/12/28.
  15. * email:303767416@qq.com
  16. */
  17. public final class MyActionBar extends LinearLayout {
  18. private View layRoot;
  19. private View vStatusBar;
  20. private View layLeft;
  21. private View layRight;
  22. private TextView tvTitle;
  23. private TextView tvLeft;
  24. private TextView tvRight;
  25. private View iconLeft;
  26. private View iconRight;
  27. public MyActionBar(Context context) {
  28. this(context, null);
  29. }
  30. public MyActionBar(Context context, AttributeSet attrs) {
  31. super(context, attrs);
  32. init();
  33. }
  34. public MyActionBar(Context context, AttributeSet attrs, int defStyleAttr) {
  35. super(context, attrs, defStyleAttr);
  36. }
  37. private void init() {
  38. setOrientation(HORIZONTAL);
  39. View contentView = inflate(getContext(), R.layout.actionbar_dft, this);
  40. layRoot = contentView.findViewById(R.id.lay_transroot);
  41. vStatusBar = contentView.findViewById(R.id.v_statusbar);
  42. tvTitle = (TextView) contentView.findViewById(R.id.tv_actionbar_title);
  43. tvLeft = (TextView) contentView.findViewById(R.id.tv_actionbar_left);
  44. tvRight = (TextView) contentView.findViewById(R.id.tv_actionbar_right);
  45. iconLeft = contentView.findViewById(R.id.iv_actionbar_left);
  46. iconRight = contentView.findViewById(R.id.v_actionbar_right);
  47. }
  48. /**
  49. * 设置状态栏高度
  50. *
  51. * @param statusBarHeight
  52. */
  53. public void setStatusBarHeight(int statusBarHeight) {
  54. ViewGroup.LayoutParams params = vStatusBar.getLayoutParams();
  55. params.height = statusBarHeight;
  56. vStatusBar.setLayoutParams(params);
  57. }
  58. /**
  59. * 设置是否需要渐变
  60. *
  61. * @param translucent
  62. */
  63. public void setNeedTranslucent(boolean translucent) {
  64. if (translucent) {
  65. layRoot.setBackgroundDrawable(null);
  66. }
  67. }
  68. /**
  69. * 设置标题
  70. *
  71. * @param strTitle
  72. */
  73. public void setTitle(String strTitle) {
  74. if (!TextUtils.isEmpty(strTitle)) {
  75. tvTitle.setText(strTitle);
  76. tvTitle.setVisibility(View.VISIBLE);
  77. } else {
  78. tvTitle.setVisibility(View.GONE);
  79. }
  80. }
  81. /**
  82. * 设置透明度
  83. *
  84. * @param transAlpha 0-255 之间
  85. */
  86. public void setTranslucent(int transAlpha) {
  87. layRoot.setBackgroundColor(ColorUtils.setAlphaComponent(getResources().getColor(R.color.primary), transAlpha));
  88. tvTitle.setAlpha(transAlpha);
  89. tvLeft.setAlpha(transAlpha);
  90. tvRight.setAlpha(transAlpha);
  91. iconLeft.setAlpha(transAlpha);
  92. iconRight.setAlpha(transAlpha);
  93. }
  94. /**
  95. * 设置数据
  96. *
  97. * @param strTitle
  98. * @param resIdLeft
  99. * @param strLeft
  100. * @param resIdRight
  101. * @param strRight
  102. * @param listener
  103. */
  104. public void setData(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener) {
  105. if (!TextUtils.isEmpty(strTitle)) {
  106. tvTitle.setText(strTitle);
  107. } else {
  108. tvTitle.setVisibility(View.GONE);
  109. }
  110. if (!TextUtils.isEmpty(strLeft)) {
  111. tvLeft.setText(strLeft);
  112. tvLeft.setVisibility(View.VISIBLE);
  113. } else {
  114. tvLeft.setVisibility(View.GONE);
  115. }
  116. if (!TextUtils.isEmpty(strRight)) {
  117. tvRight.setText(strRight);
  118. tvRight.setVisibility(View.VISIBLE);
  119. } else {
  120. tvRight.setVisibility(View.GONE);
  121. }
  122. if (resIdLeft == 0) {
  123. iconLeft.setVisibility(View.GONE);
  124. } else {
  125. iconLeft.setBackgroundResource(resIdLeft);
  126. iconLeft.setVisibility(View.VISIBLE);
  127. }
  128. if (resIdRight == 0) {
  129. iconRight.setVisibility(View.GONE);
  130. } else {
  131. iconRight.setBackgroundResource(resIdRight);
  132. iconRight.setVisibility(View.VISIBLE);
  133. }
  134. if (listener != null) {
  135. layLeft = findViewById(R.id.lay_actionbar_left);
  136. layRight = findViewById(R.id.lay_actionbar_right);
  137. layLeft.setOnClickListener(new OnClickListener() {
  138. @Override
  139. public void onClick(View v) {
  140. listener.onLeftClick();
  141. }
  142. });
  143. layRight.setOnClickListener(new OnClickListener() {
  144. @Override
  145. public void onClick(View v) {
  146. listener.onRightClick();
  147. }
  148. });
  149. }
  150. }
  151. }

完成上述代码后,BaseActivity相应的封装就变得非常简单,只要简单的几行就能完成。

  1. /**
  2. * 设置ActionBar
  3. *
  4. * @param strTitle
  5. * @param resIdLeft
  6. * @param strLeft
  7. * @param resIdRight
  8. * @param strRight
  9. * @param listener
  10. */
  11. protected void setMyActionBar(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener) {
  12. actionBar = (MyActionBar) findViewById(R.id.actionbar);
  13. actionBar.setData(strTitle, resIdLeft, strLeft, resIdRight, strRight, listener);
  14. }
  15. /**
  16. * 获取actionBar
  17. *
  18. * @return
  19. */
  20. protected MyActionBar getMyActionBar() {
  21. return actionBar;
  22. }

是不是非常简单。

而它的用法和做法一种是一致的,只需要在具体Activity中实现:

protected void setMyActionBar(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener)
即可。


至此,自定义ActionBar大部分内容都已经讲完,下面提供一下DEMO下载地址,免积分的。

CSDN:http://download.csdn.net/detail/yanjunhui2011/9788974

GitHub: https://github.com/yanjunhui2014/MyActionbar




声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/186031
推荐阅读
相关标签
  

闽ICP备14008679号