赞
踩
在日常的工作中,ActionBar使用的频率非常的高,而系统自带的ActionBar捆绑的东西有太多,而上面多数的效果我们都用不到。
如果不用系统的ActionBar,我们该怎样把自定义ActionBar的工作做到最简化呢。
首先我们做一个基本的需求分析。
如上图所示,我们的ActionBar通常包括了:左菜单, 标题, 右菜单 。如果要再细分一下, 菜单 = (图标 + 文本)。
需求确定后,代码就非常简单了。
actionbar_dft.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/lay_transroot"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@color/primary"
- android:orientation="vertical">
-
- <View
- android:id="@+id/v_statusbar"
- android:layout_width="match_parent"
- android:layout_height="1.0dp" />
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="@dimen/actionbar_height"
- android:orientation="vertical">
-
- <RelativeLayout
- android:id="@+id/lay_actionbar_left"
- android:layout_width="100dp"
- android:layout_height="match_parent"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/iv_actionbar_left"
- android:layout_width="20dp"
- android:layout_height="20dp"
- android:layout_centerVertical="true"
- android:layout_marginLeft="10dp"
- android:background="@mipmap/ic_left_light"
- android:visibility="gone" />
-
- <TextView
- android:id="@+id/tv_actionbar_left"
- style="@style/text_white"
- android:layout_height="match_parent"
- android:layout_marginLeft="10dp"
- android:layout_toRightOf="@+id/iv_actionbar_left"
- android:gravity="center_vertical"
- android:maxLength="2"
- android:singleLine="true"
- android:text="@string/cancel"
- android:visibility="gone" />
- </RelativeLayout>
-
- <TextView
- android:id="@+id/tv_actionbar_title"
- style="@style/text_white"
- android:layout_centerInParent="true"
- android:maxLength="15"
- android:text="@string/app_name"
- android:textSize="16sp" />
-
- <RelativeLayout
- android:id="@+id/lay_actionbar_right"
- android:layout_width="100dp"
- android:layout_height="match_parent"
- android:layout_alignParentRight="true"
- android:gravity="right"
- android:orientation="horizontal">
-
- <View
- android:id="@+id/v_actionbar_right"
- android:layout_width="20dp"
- android:layout_height="20dp"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:layout_marginRight="10dp"
- android:visibility="gone" />
-
- <TextView
- android:id="@+id/tv_actionbar_right"
- style="@style/text_white"
- android:layout_height="match_parent"
- android:layout_marginRight="10dp"
- android:layout_toLeftOf="@+id/v_actionbar_right"
- android:gravity="center_vertical|right"
- android:singleLine="true"
- android:text="@string/confirm"
- android:visibility="gone" />
- </RelativeLayout>
-
- </RelativeLayout>
- </LinearLayout>
到这里,有的人可能会说,你把标题栏做这么简单,稍微有复杂一点的需求,根本满足不了。对此,我只想表示,我做过的项目类似老外趣聊、英语趣配音、淘wifi,其中不乏千万用户的APP,这样的ActionBar基本上能满足产品需求,而且非常轻便。如果内聚做的好,更可以定制出你想要actionbar样式。
有了 布局文件,我们再结合需求,添加一个点击回调,一般项目中标题是没有点击事件的,所以只要有左菜单、右菜单的点击回调就行。
回调接口:
- public interface ActionBarClickListener {
-
- void onLeftClick();
-
- void onRightClick();
-
- }
接下来我们就讨论一下,代码中如何集成、封装。
做法一: 代码中使用 <include ... /> 函数。
示例:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <include
- android:id="@+id/actionbar"
- layout="@layout/actionbar_dft"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- <TextView
- android:id="@+id/tv_description"
- style="@style/text_black"
- android:padding="20dp" />
-
- </LinearLayout>
使用的时候,inlude函数里一定要添加id,因为include的布局,layout中的id是不能传递的。
然后就是 Activity 里的实现了。
- protected View layRoot;
- protected View vStatusBar;
- protected View layLeft;
- protected View layRight;
- protected TextView tvTitle;
- protected TextView tvLeft;
- protected TextView tvRight;
- protected View iconLeft;
- protected View iconRight;
-
-
- /**
- * 设置数据
- *
- * @param strTitle
- * @param resIdLeft
- * @param strLeft
- * @param resIdRight
- * @param strRight
- * @param listener
- */
- public void setMyActionBar(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener) {
- View actionBar = findViewById(R.id.actionbar);
- layRoot = actionBar.findViewById(R.id.lay_transroot);
- vStatusBar = actionBar.findViewById(R.id.v_statusbar);
- tvTitle = (TextView) actionBar.findViewById(R.id.tv_actionbar_title);
- tvLeft = (TextView) actionBar.findViewById(R.id.tv_actionbar_left);
- tvRight = (TextView) actionBar.findViewById(R.id.tv_actionbar_right);
- iconLeft = actionBar.findViewById(R.id.iv_actionbar_left);
- iconRight = actionBar.findViewById(R.id.v_actionbar_right);
-
- if (!TextUtils.isEmpty(strTitle)) {
- tvTitle.setText(strTitle);
- } else {
- tvTitle.setVisibility(View.GONE);
- }
- if (!TextUtils.isEmpty(strLeft)) {
- tvLeft.setText(strLeft);
- tvLeft.setVisibility(View.VISIBLE);
- } else {
- tvLeft.setVisibility(View.GONE);
- }
- if (!TextUtils.isEmpty(strRight)) {
- tvRight.setText(strRight);
- tvRight.setVisibility(View.VISIBLE);
- } else {
- tvRight.setVisibility(View.GONE);
- }
-
- if (resIdLeft == 0) {
- iconLeft.setVisibility(View.GONE);
- } else {
- iconLeft.setBackgroundResource(resIdLeft);
- iconLeft.setVisibility(View.VISIBLE);
- }
-
- if (resIdRight == 0) {
- iconRight.setVisibility(View.GONE);
- } else {
- iconRight.setBackgroundResource(resIdRight);
- iconRight.setVisibility(View.VISIBLE);
- }
-
- if (listener != null) {
- layLeft = findViewById(R.id.lay_actionbar_left);
- layRight = findViewById(R.id.lay_actionbar_right);
- layLeft.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- listener.onLeftClick();
- }
- });
- layRight.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- listener.onRightClick();
- }
- });
- }
- }
- package com.myactionbar.base;
-
- import android.os.Bundle;
- import android.support.annotation.Nullable;
- import android.support.v7.app.AppCompatActivity;
- import android.text.TextUtils;
- import android.view.View;
- import android.widget.TextView;
-
- import com.myactionbar.R;
- import com.myactionbar.impl.ActionBarClickListener;
-
- /**
- * Created by 晖仔(Milo) on 2017-03-21.
- * email:303767416@qq.com
- */
-
- public abstract class FirstBaseActivity extends AppCompatActivity {
-
- protected View layRoot;
- protected View vStatusBar;
- protected View layLeft;
- protected View layRight;
- protected TextView tvTitle;
- protected TextView tvLeft;
- protected TextView tvRight;
- protected View iconLeft;
- protected View iconRight;
-
- protected abstract int getContentViewId();
-
- protected abstract void init();
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(getContentViewId());
- init();
- }
-
- /**
- * 设置数据
- *
- * @param strTitle
- * @param resIdLeft
- * @param strLeft
- * @param resIdRight
- * @param strRight
- * @param listener
- */
- public void setMyActionBar(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener) {
- View actionBar = findViewById(R.id.actionbar);
- layRoot = actionBar.findViewById(R.id.lay_transroot);
- vStatusBar = actionBar.findViewById(R.id.v_statusbar);
- tvTitle = (TextView) actionBar.findViewById(R.id.tv_actionbar_title);
- tvLeft = (TextView) actionBar.findViewById(R.id.tv_actionbar_left);
- tvRight = (TextView) actionBar.findViewById(R.id.tv_actionbar_right);
- iconLeft = actionBar.findViewById(R.id.iv_actionbar_left);
- iconRight = actionBar.findViewById(R.id.v_actionbar_right);
-
- if (!TextUtils.isEmpty(strTitle)) {
- tvTitle.setText(strTitle);
- } else {
- tvTitle.setVisibility(View.GONE);
- }
- if (!TextUtils.isEmpty(strLeft)) {
- tvLeft.setText(strLeft);
- tvLeft.setVisibility(View.VISIBLE);
- } else {
- tvLeft.setVisibility(View.GONE);
- }
- if (!TextUtils.isEmpty(strRight)) {
- tvRight.setText(strRight);
- tvRight.setVisibility(View.VISIBLE);
- } else {
- tvRight.setVisibility(View.GONE);
- }
-
- if (resIdLeft == 0) {
- iconLeft.setVisibility(View.GONE);
- } else {
- iconLeft.setBackgroundResource(resIdLeft);
- iconLeft.setVisibility(View.VISIBLE);
- }
-
- if (resIdRight == 0) {
- iconRight.setVisibility(View.GONE);
- } else {
- iconRight.setBackgroundResource(resIdRight);
- iconRight.setVisibility(View.VISIBLE);
- }
-
- if (listener != null) {
- layLeft = findViewById(R.id.lay_actionbar_left);
- layRight = findViewById(R.id.lay_actionbar_right);
- layLeft.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- listener.onLeftClick();
- }
- });
- layRight.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- listener.onRightClick();
- }
- });
- }
- }
-
- }
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的所有内容(左菜单、标题、右菜单)。
代码如下:
- package com.myactionbar.widget;
-
- import android.content.Context;
- import android.support.v4.graphics.ColorUtils;
- import android.text.TextUtils;
- import android.util.AttributeSet;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.LinearLayout;
- import android.widget.TextView;
-
- import com.myactionbar.R;
- import com.myactionbar.impl.ActionBarClickListener;
-
-
- /**
- * 支持渐变的 actionBar
- * Created by 晖仔(Milo) on 2016/12/28.
- * email:303767416@qq.com
- */
-
- public final class MyActionBar extends LinearLayout {
-
- private View layRoot;
- private View vStatusBar;
- private View layLeft;
- private View layRight;
- private TextView tvTitle;
- private TextView tvLeft;
- private TextView tvRight;
- private View iconLeft;
- private View iconRight;
-
- public MyActionBar(Context context) {
- this(context, null);
- }
-
- public MyActionBar(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public MyActionBar(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- private void init() {
- setOrientation(HORIZONTAL);
- View contentView = inflate(getContext(), R.layout.actionbar_dft, this);
- layRoot = contentView.findViewById(R.id.lay_transroot);
- vStatusBar = contentView.findViewById(R.id.v_statusbar);
- tvTitle = (TextView) contentView.findViewById(R.id.tv_actionbar_title);
- tvLeft = (TextView) contentView.findViewById(R.id.tv_actionbar_left);
- tvRight = (TextView) contentView.findViewById(R.id.tv_actionbar_right);
- iconLeft = contentView.findViewById(R.id.iv_actionbar_left);
- iconRight = contentView.findViewById(R.id.v_actionbar_right);
- }
-
- /**
- * 设置状态栏高度
- *
- * @param statusBarHeight
- */
- public void setStatusBarHeight(int statusBarHeight) {
- ViewGroup.LayoutParams params = vStatusBar.getLayoutParams();
- params.height = statusBarHeight;
- vStatusBar.setLayoutParams(params);
- }
-
- /**
- * 设置是否需要渐变
- *
- * @param translucent
- */
- public void setNeedTranslucent(boolean translucent) {
- if (translucent) {
- layRoot.setBackgroundDrawable(null);
- }
- }
-
- /**
- * 设置标题
- *
- * @param strTitle
- */
- public void setTitle(String strTitle) {
- if (!TextUtils.isEmpty(strTitle)) {
- tvTitle.setText(strTitle);
- tvTitle.setVisibility(View.VISIBLE);
- } else {
- tvTitle.setVisibility(View.GONE);
- }
- }
-
- /**
- * 设置透明度
- *
- * @param transAlpha 0-255 之间
- */
- public void setTranslucent(int transAlpha) {
- layRoot.setBackgroundColor(ColorUtils.setAlphaComponent(getResources().getColor(R.color.primary), transAlpha));
- tvTitle.setAlpha(transAlpha);
- tvLeft.setAlpha(transAlpha);
- tvRight.setAlpha(transAlpha);
- iconLeft.setAlpha(transAlpha);
- iconRight.setAlpha(transAlpha);
- }
-
-
- /**
- * 设置数据
- *
- * @param strTitle
- * @param resIdLeft
- * @param strLeft
- * @param resIdRight
- * @param strRight
- * @param listener
- */
- public void setData(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener) {
- if (!TextUtils.isEmpty(strTitle)) {
- tvTitle.setText(strTitle);
- } else {
- tvTitle.setVisibility(View.GONE);
- }
- if (!TextUtils.isEmpty(strLeft)) {
- tvLeft.setText(strLeft);
- tvLeft.setVisibility(View.VISIBLE);
- } else {
- tvLeft.setVisibility(View.GONE);
- }
- if (!TextUtils.isEmpty(strRight)) {
- tvRight.setText(strRight);
- tvRight.setVisibility(View.VISIBLE);
- } else {
- tvRight.setVisibility(View.GONE);
- }
-
- if (resIdLeft == 0) {
- iconLeft.setVisibility(View.GONE);
- } else {
- iconLeft.setBackgroundResource(resIdLeft);
- iconLeft.setVisibility(View.VISIBLE);
- }
-
- if (resIdRight == 0) {
- iconRight.setVisibility(View.GONE);
- } else {
- iconRight.setBackgroundResource(resIdRight);
- iconRight.setVisibility(View.VISIBLE);
- }
-
- if (listener != null) {
- layLeft = findViewById(R.id.lay_actionbar_left);
- layRight = findViewById(R.id.lay_actionbar_right);
- layLeft.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- listener.onLeftClick();
- }
- });
- layRight.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- listener.onRightClick();
- }
- });
- }
- }
-
- }
完成上述代码后,BaseActivity相应的封装就变得非常简单,只要简单的几行就能完成。
- /**
- * 设置ActionBar
- *
- * @param strTitle
- * @param resIdLeft
- * @param strLeft
- * @param resIdRight
- * @param strRight
- * @param listener
- */
- protected void setMyActionBar(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener) {
- actionBar = (MyActionBar) findViewById(R.id.actionbar);
- actionBar.setData(strTitle, resIdLeft, strLeft, resIdRight, strRight, listener);
- }
-
- /**
- * 获取actionBar
- *
- * @return
- */
- protected MyActionBar getMyActionBar() {
- return actionBar;
- }
是不是非常简单。
而它的用法和做法一种是一致的,只需要在具体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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。