写Android的时候,可能有多个界面。在风格统一的软件中,写Activity时会有很多重复。例如我所在软工课程小组的项目:Github链接 ,里面的TaskListActivity和TeacherListActivity就在Navigation的处理上有重复。还有一个双击退出APP的方法onBackPressed()也重复实现了。之前让负责界面的同学把这些代码放到一个BaseActivity里面,让其他Activity继承它。他说不好做,他尝试过,但失败了。

于是这次我独自做 英语词典APP 的时候 ,经过在Google上的一番搜索和实践探索,写出一个还可以的BaseActivity。现在做个记录,以后还会用得到。

BaseActivity项目的Github链接

这个BaseActivity包括侧滑菜单(Navigation Drawer)和工具栏(Tool Bar)。

先看最终效果:

一、Navigation Drawer

由于Navigation Drawer涉及到BaseActivity的主要布局,所以先说明。

  1. Activity的布局文件

    先看Android官方Navigation Drawer说明:Creating a Navigation Drawer

    根据说明,将 layout/activity_base.xml 设置为以下内容:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- 主内容布局 -->
    <FrameLayout
    android:id="@+id/content_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
    <!-- 侧滑菜单 -->
    <ListView
    android:id="@+id/left_drawer"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:background="#111"
    android:choiceMode="singleChoice"
    android:divider="@android:color/transparent"
    android:dividerHeight="0dp"/>
    </android.support.v4.widget.DrawerLayout>

    Android Studio不会提示android:layout_gravity这一项,但是整行敲完之后,可以正常运行。

  2. 侧滑菜单列表布局

    这里只做简单的布局,所以侧滑菜单项都是TextView。

    创建 layout/list_item_drawer.xml

    <?xml version="1.0" encoding="utf-8"?>
    
    <TextView
    android:id="@+id/tv_na_draw"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="30sp"
    android:textColor="#fff"/>

    因为等会儿要用ArrayAdapter,所以这里最外层一定要是TextView。

  3. 侧滑菜单项的文本

    StringArray

    创建 values/string_array_test.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <string-array name="planets_array">
    <item>主界面</item>
    <item>关于</item>
    <item>设置</item>
    <item>退出</item>
    </string-array>
    </resources>
  4. Activity初始化

    Initialize the Drawer List

    这里由于要将Activity做成BaseActivity,所以和官方文档上的代码不太一样。

    public class BaseActivity extends AppCompatActivity {
    protected String[] planetTitles;
    protected DrawerLayout drawerLayout;
    protected ListView drawerList;
    protected FrameLayout frameLayout; @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    } /**
    * 重写setContentView,以便于在保留侧滑菜单的同时,让子Activity根据需要加载不同的界面布局
    */
    @Override
    public void setContentView(@LayoutRes int layoutResID) {
    drawerLayout = (DrawerLayout) getLayoutInflater().inflate(R.layout.activity_base, null);
    frameLayout = (FrameLayout) drawerLayout.findViewById(R.id.content_frame);
    // 将传入的layout加载到activity_base的content_frame里面
    getLayoutInflater().inflate(layoutResID, frameLayout, true);
    super.setContentView(drawerLayout); setUpNavigation();
    } private void setUpNavigation() {
    planetTitles = getResources().getStringArray(R.array.planets_array);
    drawerList = (ListView) findViewById(R.id.left_drawer);
    drawerList.setAdapter(new ArrayAdapter<>(BaseActivity.this,
    R.layout.list_item_drawer, planetTitles));
    }
    }
  5. MainActivity

    先创建个Activity查看效果。

    创建MainActivity继承BaseActivity :

    public class MainActivity extends BaseActivity {
    
        @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    }
    }

    layout_main用的是默认布局。

    在启动前要更改 AndroidManifest.xml ,将MainActivity设置成Launcher:

    <activity android:name=".MainActivity">
    <intent-filter>
    <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
    </activity>

    启动后,手指从最左往右划,打开侧滑菜单。

  6. 添加侧滑菜单点击事件

    Handle Navigation Click Events

    先创建ClickListener,这里简单地设置点击后显示所点击的文本。

    在BaseActivity中添加:

    private class DrawerItemClickListener implements ListView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    selectItem(position);
    }
    } private void selectItem(int position) {
    Toast.makeText(BaseActivity.this, planetTitles[position], Toast.LENGTH_SHORT).show();
    }

    在BaseActivity的 setUpNavigation() 中添加:

    drawerList.setOnItemClickListener(new DrawerItemClickListener());

二、ToolBar

  1. ToolBar 布局

    ToolBar的各个成分:



    Setting Up the App Bar

    打开AndroidManifest.xml,将里面的 android:theme="@style/AppTheme" 替换成 android:theme="@style/Theme.AppCompat.Light.NoActionBar",如下:

    <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/Theme.AppCompat.Light.NoActionBar">
    ...(三点表示省略,下同)

    创建 layout/toolbar.xml

    <?xml version="1.0" encoding="utf-8"?>
    <merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:elevation="4dp"
    android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> </merge>
  2. ToolBar 初始化

    在BaseActivity里添加:

    public class BaseActivity extends AppCompatActivity {
    ...
    private Toolbar toolbar; ...
    private void setUpToolBar() {
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    }
    }

    在BaseActivity的 setContentView() 里的 setUpNavigation();下面添加setUpToolBar();,如下:

    @Override
    public void setContentView(@LayoutRes int layoutResID) {
    ...
    setUpNavigation();
    setUpToolBar();
    }

    如果想要在MainActivity里显示ToolBar,还需要在 activity_main.xml 里include一个ToolBar的布局:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout ...> <include layout="@layout/toolbar"/> </RelativeLayout>

    显示的效果如下:

  3. 加入侧滑菜单打开键

    Material Design Icons 下载图标。搜索menu,下载PNG版本。



    解压后,将 ic_menu_black_24dp/android 文件夹下面的所有文件夹复制到 res/ 里面。



    在BaseActivity的 setUpToolBar() 中添加:

    toolbar.setNavigationIcon(R.drawable.ic_menu_black_24dp);



    虽然有图标,但是还没设置点击事件,所以点击的时候没有任何反应。

  4. 点击ToolBar的home按钮打开Navigation Drawer

    在BaseActivity里添加:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
    drawerLayout.openDrawer(GravityCompat.START);
    return true;
    default:
    break;
    }
    return super.onOptionsItemSelected(item);
    }

    这里就省略ActionBarDrawerToggle的部分了,影响不是特别大。实际应用中再去添加。

  5. 添加Option Menu

    values/strings.xml 里添加等会儿会用到的字符串:

    <resources>
    ...
    <string name="edit">编辑</string>
    <string name="search">搜索</string>
    <string name="change_history">变更记录</string>
    </resources>

    Material Design Icons 下载相关图标。

    创建 res/menu/menu_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <menu android:id="@+id/expanded_menu"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"> <item
    android:id="@+id/menu_edit"
    android:icon="@drawable/ic_mode_edit_black_24dp"
    android:title="@string/edit"
    app:showAsAction="ifRoom"/> <item
    android:id="@+id/menu_search"
    android:icon="@drawable/ic_search_black_24dp"
    android:title="@string/search"
    app:showAsAction="ifRoom"/> <item
    android:id="@+id/menu_change_history"
    android:icon="@drawable/ic_change_history_black_24dp"
    android:title="@string/change_history"
    app:showAsAction="never"/> </menu>

    其中ifRoom表示如果ToolBar空间足够,则将其图标显示在ToolBar上面。never表示永不显示在ToolBar上面,只有当点击option menu按钮的时候,才会出现。

    在BaseActivity中添加:

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    super.onCreateOptionsMenu(menu);
    return true;
    }

    启动APP:



    点击menu按钮后:

  6. Option Menu的点击事件

    在BaseActivity里的 onOptionsItemSelected() 增加case即可。

  7. 隐藏ActionBar的Option Menu

    有时候不想在某个Activity中显示Option Menu,于是修改BaseActivity:

    public class BaseActivity extends AppCompatActivity {
    ...
    private boolean showOptionMenu = true; ...
    protected void hideOptionMenu() {
    showOptionMenu = false;
    } @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    if (showOptionMenu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    }
    super.onCreateOptionsMenu(menu);
    return true;
    } }

三、参考链接

  1. ToolBar

    https://developer.android.com/training/appbar/setting-up.html

    https://developer.android.com/training/appbar/actions.html

    http://stackoverflow.com/questions/32367041/calling-toolbar-on-each-activity

    http://stackoverflow.com/questions/30824324/clicking-hamburger-icon-on-toolbar-does-not-open-navigation-drawer

    http://stackoverflow.com/questions/19724567/how-to-add-menu-indicator-next-to-action-bars-app-icon

    http://stackoverflow.com/questions/26582075/cannot-catch-toolbar-home-button-click-event

  2. Navigation Drawer

    https://developer.android.com/training/implementing-navigation/nav-drawer.html

    http://stackoverflow.com/questions/33009469/baseactivity-for-navigation

    http://stackoverflow.com/questions/22652556/creating-base-activity-with-navigation-drawer-in-android

  3. ArrayAdapter

    http://stackoverflow.com/questions/9280965/arrayadapter-requires-the-resource-id-to-be-a-textview-xml-problems

    http://stackoverflow.com/questions/29591546/unable-to-use-layout-gravity-for-listview-inside-drawerlayout

  4. String Array

    https://developer.android.com/guide/topics/resources/string-resource.html#StringArray

  5. Material icons

    https://design.google.com/icons/

Android带侧滑菜单和ToolBar的BaseActivity的更多相关文章

  1. Android SlidingMenu侧滑菜单使用

    把下载的侧滑菜单压缩包打开,会有一个library文件夹,在eclipse中import existing android code into workspace,导入library文件夹,并且选择作 ...

  2. no drawer view found with gravity RIGHT(Android实现侧滑菜单从右面滑出) 解决办法

    代码如下: <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width ...

  3. 【转】android官方侧滑菜单DrawerLayout详解

    原文网址:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0925/1713.html drawerLayout是Support ...

  4. android官方侧滑菜单DrawerLayout详解

    drawerLayout是Support Library包中实现了侧滑菜单效果的控件,可以说drawerLayout是因为第三方控件如MenuDrawer等的出现之后,google借鉴而出现的产物.d ...

  5. Android之侧滑菜单DrawerLayout的使用

    在android support.v4 中有一个抽屉视图控件DrawerLayout.使用这个控件,可以生成通过在屏幕上水平滑动打开或者关闭菜单,能给用户一个不错的体验效果. DrawerLayout ...

  6. Android DrawerLayout侧滑菜单

    本教程已经录制视频,欢迎大家观看我在CSDN学院录制的课程:http://edu.csdn.net/lecturer/944

  7. Android组件——使用DrawerLayout仿网易新闻v4.4侧滑菜单

    摘要: 转载请注明出处:http://blog.csdn.net/allen315410/article/details/42914501 概述        今天这篇博客将记录一些关于DrawerL ...

  8. Android-自定义侧滑菜单

    效果图: 需要继承ViewGroup,因为包含了子控件,菜单子控件 与 主页面子控件 Activity Xml布局相关: <!-- 自定义侧滑菜单 SlideMenu --> <Li ...

  9. android 应用架构随笔五(ActionBar与侧滑菜单DrawerLayout)

    ActionBar(V7)的添加非常简单,只需要在AndroidManifest.xml中指定Application或Activity的theme是Theme.Holo或其子类就可以了,在Androi ...

随机推荐

  1. 自己制作QQ空间音乐的具体方法

    1.打开QQ邮箱找到左栏下方的“文件中转站”--点击收藏文件--上传到收藏  将MP3或WMA音乐文件上传 上传完成点下载 下图:   2.点“保存”将最上面一排的地址全部复制  下图   3.为了更 ...

  2. 第十篇:扩展SOUI的控件及绘图对象(ISkinObj)

    尽管SOUI已经内置了大部分常用的控件,很显然内置控件很难满足各种应用的形式各异的需求. 因此只有提供足够的扩展性才能满足真实应用场景. 除了将系统尽可能的组件化外,SOUI在控件自绘(SWindow ...

  3. ASP.NET 4.0 取消表单危险字符验证

    /// <summary> /// ASP.NET4.0 表单验证类 /// </summary> public class FormRequestValidation : R ...

  4. github 使用网址

    [Github教程]史上最全github使用方法:github入门到精通 http://blog.csdn.net/hcbbt/article/details/11651229 githup的使用 h ...

  5. LoadRunner参数化之数据生成方式

    一般需要使用多条数据来完成实际事务的时候,需要参数化.而使用参数化可以方便实现很多实际事务,记得在哪里看到过,参数化是比C函数更高级的函数. 参数化的方法 先来个最常见的LR示例的登录脚本: Acti ...

  6. SQLServer批量创建有规则的数据

    根据需求要生成从kkk001,kkk002开始的100个递增账号 手插要死人的,用SQL脚本轻松完成: declare @a int ) ) begin ) ) end declare:申明变量, @ ...

  7. 数值的三种表示--C语言

    在C语言中,数值常数可以是3中形式: (1)在数值前面加0表示的是8进制数据: (2)在数字前面加0x表示的是16进制数: (3)在数值前面什么也不加,表示的是10进制数值.        目前C语言 ...

  8. clear both

    原文地址:http://www.codefans.net/articles/653.shtml 因CSS很多布局是需要浮动的,当属性设置float(浮动)时,其所在的物理位置已经脱离文档流了,为了使f ...

  9. 疯狂java学习笔记之面向对象(六) - 构造器重载、方法重载和方法重写

    一.方法重载(Overload): Java允许同一个类中定义多个同名方法,只要形参不一样就可以,如果同一个类中包含了两个或两个以上方法名相同的方法,但形参列表不同,则被成为方法重载(两同一异). 同 ...

  10. 快速搭建Webservice接口测试环境

    一.必备工具: apache-tomcat.Axis2(WebService引擎).实例类 二.部署步骤: 1.到apache官网 http://apache.org/ 下载apache-tomcat ...