很久没更新 blog 了,最近在赶一个项目,所以时间特别紧,自己闲暇的时间也就少了许多,最近我的好朋友们一直在群里喊,杀!杀!杀!也都抽不出时间陪他们玩!今天周末,终于可以放松一下了,先更新 blog!^V^~~~~。
我们知道 Android ActionBar 的功能很强大,经过 Google 的改良后,使用起来页很灵活和便捷,但是!再好的东西都有它所不能及的一面,就像在豪华的别墅都应该有一个小小的 WC,就像…都有…,这里就不往下了。回到 ActionBar,有哪些它无法做到呢?
我们还是来看一张效果图
这种效果的 ActionBar,在 ActionBar 上添加一个按钮的效果,如果要用 原生的ActionBar实现够呛!虽然说可以通过 setView 来实现但是,个人感觉比较麻烦!ok,如果不用 setView 的方式来实现,那我们就只能通过自定义 布局 来实现,而把原来的 ActionBar 给隐藏掉。代码我相信大家都会写
如下:分三步走
第一步:编写 custom bar layout
<?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="@dimen/abc_action_bar_default_height_material" android:background="#ffffff">
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#eeeeee"
android:layout_alignParentBottom="true"/>
<RelativeLayout
android:id="@+id/id_actionBar_back" android:layout_width="@dimen/abc_action_bar_default_height_material" android:layout_height="@dimen/abc_action_bar_default_height_material"
android:clickable="true"
android:background="@drawable/actionbar_back_bg"
android:layout_marginBottom="0.5dp"
>
<ImageView
android:id="@+id/id_actionBar_back_icon"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_ab_back_black"
/>
</RelativeLayout>
<TextView
android:layout_toRightOf="@id/id_actionBar_back"
android:id="@+id/id_actionBar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/id_actionBar_confirm"
android:text="自己定义"
android:singleLine="true"
android:textSize="20sp"
android:textColor="#333333"
/>
<Button
android:layout_width="52dp"
android:layout_height="32dp"
android:id="@+id/id_actionBar_confirm"
android:text="保 存"
android:background="@drawable/color_btn_selector"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:textSize="14sp"
android:textColor="@android:color/white"
android:gravity="center"
android:layout_marginRight="10dp"
/>
</RelativeLayout>
第二步:在用使用的布局文件中嵌入这个布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
>
<include layout="@layout/custom_actionbar_layout"
android:id="@+id/id_custom_actionBar"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
android:layout_centerInParent="true"
android:textColor="@color/btn_color_normal"
android:text="自己的ActionBar"/>
</RelativeLayout>
最后一步:
在代码中设置点击事件等等操作
private void initCustomBar(){
mCustomBar = findViewById(R.id.id_custom_actionBar) ;
mBackBtn = mCustomBar.findViewById(R.id.id_actionBar_back) ;
mTitle = (TextView) mCustomBar.findViewById(R.id.id_actionBar_title);
mConfirmBtn = (Button) mCustomBar.findViewById(R.id.id_actionBar_confirm) ;
mIcon = (ImageView) mCustomBar.findViewById(R.id.id_actionBar_back_icon) ;
mBackBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
mTitle.setText(getTitle());
mConfirmBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,MyBarActivity.class) ;
startActivity(intent);
Toast.makeText(MainActivity.this,"点击了保存按钮",Toast.LENGTH_SHORT).show();
}
});
}
运行结果如下
嘿!效果不错,大功告成,可以提交代码了,可是过了一段时间,设计把其他页面的设计结果给你一看,哇,类似这种在 AcionBar 上加一个按钮的界面还有七八个,没办法了,只能复制、粘贴,复制、粘贴,复制、粘贴。可是作为一位合格的码农,应该清楚,只要是能重复利用的东西,我们都是能够抽取出来的,而我们也应该要把它抽取出来!接下来就进入本篇 blog 的核心内容。
我们的大致思路是这样的:
定义一个抽象的父类 Activity,在这个类中实现我们自己风格的 ActionBar,而其他类只需要继承这个类就能实现这样的 ActionBar 风格,并在子类中能设置监听按钮事件,修改标题内容等等一系列操作!
要实现这样一个抽象类,其实仔细想想也不难,这里我就直接上代码了:
package com.test.gyzhong.customactionbar;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* Created by gyzhong on 15/4/17.
*/
public abstract class CustomBarActivity extends ActionBarActivity {
/*我们定义的ActionBar*/
private View mCustomBar ;
/*放回按钮*/
private View mBackBtn ;
/*确定按钮*/
private Button mConfirmBtn ;
/*标题View*/
private TextView mTitle ;
/*返回箭头*/
private ImageView mIcon ;
/*返回按钮菜单*/
private MenuItemImpl mBackMenuItem ;
/*标题菜单*/
private MenuItemImpl mBackMenuTitle;
/*确定按钮菜单*/
private MenuItemImpl mConfirmMenuItem ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*隐藏系统的ActionBar*/
getSupportActionBar().hide();
/*初始化自己定义的ActionBar*/
initCustomBar() ;
}
private void initCustomBar(){
/*不解释*/
mCustomBar = getLayoutInflater().inflate(R.layout.custom_actionbar_layout, null) ;
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
(int) getResources().getDimension(R.dimen.abc_action_bar_default_height_material));
mBackBtn = mCustomBar.findViewById(R.id.id_actionBar_back) ;
mCustomBar.setLayoutParams(params);
mTitle = (TextView) mCustomBar.findViewById(R.id.id_actionBar_title);
mConfirmBtn = (Button) mCustomBar.findViewById(R.id.id_actionBar_confirm) ;
mIcon = (ImageView) mCustomBar.findViewById(R.id.id_actionBar_back_icon) ;
mBackBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onOptionsItemSelected(mBackMenuItem) ;
}
});
mTitle.setText(getTitle());
mConfirmBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onOptionsItemSelected(mConfirmMenuItem) ;
}
});
}
@Override
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
/*创建一个线性布局*/
LinearLayout content = new LinearLayout(this) ;
ViewGroup.LayoutParams contentParam = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT) ;
/*
*设置线性布局的方向为垂直
* 第一个子View 为我们定义的ActionBar
* 第二个子View 是我们整个 activity 原来的布局
*
* */
content.setOrientation(LinearLayout.VERTICAL);
content.setLayoutParams(contentParam);
content.addView(mCustomBar);
/*
*
* 以下操作的意思是:
* 从原来父View 中把原来Activity 的内容View 移除掉,
* 放入我们自己创建的那个线性布局,
* 因为线性布局中包含自己定义的ActionBar
* 和原来的内容区域,所以,最总就是我们想要的效果
* */
ViewGroup baseGroup = (ViewGroup) findViewById(android.R.id.content);
View originView = baseGroup.getChildAt(0) ;
baseGroup.removeView(originView);
content.addView(originView);
baseGroup.addView(content);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.id_actionBar_back:{
finish();
return true ;
}
}
return super.onOptionsItemSelected(item);
}
/*----------------------------以下操作是为了迎合我们的习惯----------------------*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuItem menuItem = menu.findItem(R.id.id_actionBar_confirm);
if (menuItem != null){
setActionBarCompatConfirmText(menuItem.getTitle());
}
menuItem = menu.findItem(R.id.id_actionBar_title);
if (menuItem != null){
setActionBarCompatTitle(menuItem.getTitle());
}
mBackMenuItem = new MenuItemImpl() ;
mBackMenuItem.addMenuItem(mBackBtn,R.id.id_actionBar_back);
mBackMenuTitle = new MenuItemImpl() ;
mBackMenuTitle.addMenuItem(mTitle,R.id.id_actionBar_title);
mConfirmMenuItem = new MenuItemImpl() ;
mConfirmMenuItem.addMenuItem(mConfirmBtn,R.id.id_actionBar_confirm);
return super.onCreateOptionsMenu(menu);
}
/*=========================以下方法是自定义Bar 的一些控制方法=======================*/
public View getActionBarCompat(){
return mCustomBar ;
}
public TextView getActionBarCompatTextView(){
return mTitle ;
}
public Button getActionBarCompatConfirmBtn(){
return mConfirmBtn ;
}
public void setActionBarCompatBg(int color){
mCustomBar.setBackgroundColor(color);
}
public void setActionBarCompatBg(Drawable bg){
mCustomBar.setBackgroundDrawable(bg);
}
public void setActionBarCompatHide(){
mCustomBar.setVisibility(View.GONE);
}
public void setActionBarCompatTitle(CharSequence title){
mTitle.setText(title);
}
public void setActionBarCompatTitle(int title){
mTitle.setText(title);
}
public void setActionBarCompatTitleColor(int color){
mTitle.setTextColor(color);
}
public void setActionBarCompatTitleColor(ColorStateList color){
mTitle.setTextColor(color);
}
public void setActionBarCompatConfirmText(CharSequence title){
mConfirmBtn.setText(title);
}
public void setActionBarCompatConfirmText(int title){
mConfirmBtn.setText(title);
}
public void setActionBarCompatIcon(int iconRes) {
mIcon.setImageResource(iconRes);
}
public void setActionBarCompatIcon(Drawable icon) {
mIcon.setImageDrawable(icon);
}
}
接下来看看如何使用它吧,看完之后会让你惊艳的!
1、使用的 Activity 代码
/**
* Created by gyzhong on 15/4/17.
*/
public class MyBarActivity extends CustomBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_bar_view);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.id_actionBar_confirm){
Toast.makeText(this,item.getTitle() + "按钮被点击了",Toast.LENGTH_SHORT).show();
}
return super.onOptionsItemSelected(item);
}
}
2、xml 代码
<?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"
android:layout_gravity="center">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="22sp"
android:gravity="center"
android:textColor="@color/btn_color_normal"
android:text="自己的ActionBar"/>
</LinearLayout>
我们的 Activity 和布局文件中什么都不需要做,唯一要实现的就是继承我们定义的抽象类,所以不管以后你有几十个这样的页面甚至几百个,我们都不需要做任何处理。
运行结果:
这篇文章的技术难点,可以说没什么技术难点,最主要的还是在开发的过程中,不断的总结,优化我们的代码。我在看别人的代码的时候,经常会带着欣赏的眼光去看,有时一份好的代码,会让我回味无穷。
点击下载
原文地址:http://blog.csdn.net/jxxfzgy/article/details/45110557