Android开发细节--查漏补缺(一):UI篇

转载请说明出处:Android开发细节--查漏补缺(一):UI篇

引言:一开始,先和大家可能从最开始接触Android开发时就存在的一些我们用过但不太关注的UI部件相关知识。第一篇,先说一下有关:Menu、标题栏 和 Android主题(Theme)的相关知识。

Android Theme(主题)


注意:一般我们使用或者自定义style等,大多用于单个View,称为View的样式。而样式也能用于Activity或整个Application,这时就需要在相应<activity>或<application>标签中设置android:theme属性,引用的其实也是style,但一般称为主题。

  • themes.xml: 低版本的主题,目标API level一般在10以下

  • themes_hole.xml: 从 API level 11添加的主题

一、 support v7库
作用:用于某些控件和主题等兼容至Android2.1版本(API 7)
对于Theme主题的影响:Theme.AppCompat系列兼容主题,在引用到v7包之后,就要求使用,而android3.0以上系统带有的Theme.Holo系列主题,则是未引用兼容包时注意使用。

  • Android3.0及以上的版本的Style一般写法:
<style name="XXX" parent="@android:style/Theme.Holo">
   <item name="android:xxx">yyy</item> 
</style>
  • Android2.1及以上兼容版本的Style一般写法:
<style name="XXX" parent="@style/Theme.AppCompat">
   <item name="xxx">yyy</item> 
</style>

二、 theme测试示例

  1. 无ActionBar
* 白色背景: `Activity`+ `android:theme="@style/Theme.AppCompat.Light"`
* 黑色背景: `Activity`+ `android:theme="@style/Theme.AppCompat"`
* 自定义默认背景:`Activity`  或者 `Activity`+`android:theme="@style/AppTheme"`
  1. 有ActionBar
  2. 旧版本:继承ActionBarActivity
  * 全白色背景:`ActionBarActivity`+`android:theme="@style/Theme.AppCompat.Light"`
  * 全黑色背景:`ActionBarActivity`+`android:theme="@style/Theme.AppCompat"`
  * 白色背景黑色ActionBar:`ActionBarActivity`+`android:theme="@style/Theme.AppCompat.Light.DarkActionBar"`
  * 自定义默认背景:`ActionBarActivity`  或者`ActionBarActivity`+`android:theme="@style/AppTheme"`

Menu


Android Menu 主要是两种:①OptionMenu【点击ActionBar的菜单选项或者手机硬件MENU按键触发显示菜单】 ②ContextMenu【指定的View或ViewGroup的长按触发】

一、 OptionMenu

  1. 方法执行流程


    OptionsMenu.png
  2. 具体实现代码示例
* Activity代码中添加:

```
  @Override
public boolean onCreateOptionsMenu(Menu menu) {
    //方式一(java)
     /*第一个参数是groupId,如果不需要可以设置为Menu.NONE。

将若干个menu item都设置在同一个Group中,可以使用setGroupVisible(),setGroupEnabled(),setGroupCheckable()这样的方法,
而不需要对每个item都进行setVisible(), setEnable(), setCheckable()这样的处理,这样对我们进行统一的管理比较方便
* 第二个参数就是item的ID,我们可以通过menu.findItem(id)来获取具体的item
* 第三个参数是item的顺序,一般可采用Menu.NONE,具体看本文最后MenuInflater的部分
* 第四个参数是显示的内容,可以是String,或者是引用Strings.xml的ID
*/
menu.add(Menu.NONE,ONE_ID,Menu.NONE,"1 Pixel");
menu.add(Menu.NONE, TWO_ID, Menu.NONE, "2 Pixels");
menu.add(Menu.NONE, EIGHT_ID, Menu.NONE, "8 Pixels");
……
///方式二(xml)
MenuInflater mi = getMenuInflater();
mi.inflate(R.menu.activity_actionbar,menu);

    // 子菜单设置
    //通过addSubMenu设置子菜单,作为item加入Menu。参数和addMenu一致,为了简单,我们这里的ID直接采用数字表示
    SubMenu submenu = menu.addSubMenu(Menu.NONE, 100, Menu.NONE, "子菜单测试");
    //在SubMenu中增加子菜单的item
    submenu.add(Menu.NONE,101,Menu.NONE,"sub One");
    submenu.add(Menu.NONE,102,Menu.NONE,"sub Two");
    submenu.add(Menu.NONE,103,Menu.NONE,"sub Three");
    submenu.add(Menu.NONE,104,Menu.NONE,"sub Four");
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    ///----------实现每次Menu打开时的操作---------------
    return super.onPrepareOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()){
        case R.id.action_search:
            Toast.makeText(this, "搜索",Toast.LENGTH_SHORT).show(); 
           break;
        case R.id.action_settings:
            Toast.makeText(this, "设置",Toast.LENGTH_SHORT).show();
            break;
    }
    return super.onOptionsItemSelected(item);
}
```
* 自定义的res/menu/activity_actionbar.xml:

```
<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yourapp="http://schemas.android.com/apk/res-auto" >



<item android:id="@+id/action_search"
android:icon="@android:drawable/ic_menu_search"
android:title="@android:string/search_go"
yourapp:showAsAction="ifRoom" />
<item android:id="@+id/action_settings"
android:title="设置"
yourapp:showAsAction="never" />
</menu>
```

二、 ContextMenu

  1. 方法执行流程:
    每次长按指定的View,自动在所按的位置处弹出menu。
  2. 设置流程:
  • Activity中获取一个组件,如一个Button:
    private Button btn;
  • 让这个Button进行初始化并让其注册到ContextMenu中:
     btn  = (Button) findViewById(R.id.btn_actionbar);
     registerForContextMenu(btn);
    
  1. 重写ContextMenu相关方法,让此方法触发时,弹出指定的ContextMenu【注意是ContextMenu类型的,不是Menu类型】:

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater mi = getMenuInflater();
///R.menu.activity_actionbar与上面OptionsMenu的一样!
mi.inflate(R.menu.activity_actionbar,menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
return super.onContextItemSelected(item);
}


## ActionBar
---
1. ActionBar的基本使用:
 1. Android 版本 >= 3.0 ,所有使用Theme.Holo主题(及其子类)的Activity都包含了ActionBar,当`targetSdkVersion` 或 `minSdkVersion `属性被设置成“11”或者更大时,他是默认主题
 2. Android版本>=2.1 ,要添加ActionBar,需要加载Android Support库:`v7 appcompat`库(现在AS在新建项目时,基本都会为我们添加这个库)。然后:①让`Activity`继承`ActionBarActivity` ②在manifast.xml文件中,给<activity>添加一句:`<activity android:theme="@style/Theme.AppCompat.Light" ... >`

2. xml中设定每个Activity的ActionBar上显示的标题(Label):
 通过设置清单文件中Activity标签中的label属性,如:`<activity android:name=".actionbar.MyActionBarActivity"    android:label="ActionBar活动" ……/>`
![](http://upload-images.jianshu.io/upload_images/2369895-3a277f9988102697.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

3. ActionBar从创建到行为实现
 * 创建相应的Activity:ActionBarActivity、AppCompatActivity(均位于v7 support库中,用于兼容到Android2.1版本,即API 7)
 * 创建Menu菜单:
   * 方式一:java代码
     在**onCreateOptionsMenu(Menu menu)**方法中,加入如下示例:
     ```
@Override
 public boolean onCreateOptionsMenu(Menu menu) {
menu.add(Menu.NONE,ONE_ID,Menu.NONE,"1 Pixel");
     menu.add(Menu.NONE, TWO_ID, Menu.NONE, "2 Pixels");
     menu.add(Menu.NONE, EIGHT_ID, Menu.NONE, "8 Pixels");
    ……
     return super.onCreateOptionsMenu(menu);
 }
     ```
   * 方式二:xml定义后再引用
     先创建xml菜单布局文件**res/menu/my_menu.xml**:
     ```
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
 <item android:id="@+id/action_search"
     android:icon="@android:drawable/ic_menu_search"
     android:title="@android:string/search_go"
     yourapp:showAsAction="ifRoom"
/>
 <item android:id="@+id/action_settings"
     android:title="设置"
     yourapp:showAsAction="never"
/>
…………
</menu>
     ```
       此时,ActionBar已经有了菜单列表了!
 * 完善ActionBar信息:
     在Java代码中完善ActionBar信息
     ```
getSupportActionBar().setIcon(R.mipmap.ic_launcher);
getSupportActionBar().setSubtitle("我是subTitle");
getSupportActionBar().setCustomView(R.layout.view_custom);
getSupportActionBar().setLogo(R.mipmap.ic_launcher);
getSupportActionBar().setElevation(50);
     ```
 * 最终截图
   ![](http://upload-images.jianshu.io/upload_images/2369895-e076b6dc075cb7c6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

3. ActionBar的自定义背景
完整示例:`res/values/themes.xml`

<?xml version="1.0" encoding="utf-8"?>
<resources>

<style name="CustomActionBarTheme"
parent="@style/Theme.AppCompat.Light.DarkActionBar">
<item name="android:actionBarStyle">@style/MyActionBar</item>
<item name="android:actionBarTabTextStyle">@style/MyActionBarTabText</item>
<item name="android:actionMenuTextColor">@android:color/holo_blue_bright</item>
<item name="android:windowActionBarOverlay">true</item>

<item name="actionBarStyle">@style/MyActionBar</item>
<item name="actionBarTabTextStyle">@style/MyActionBarTabText</item>
<item name="actionMenuTextColor">@android:color/holo_blue_bright</item>

<item name="windowActionBarOverlay">true</item>
</style>

<style name="MyActionBar"
parent="@style/Widget.AppCompat.ActionBar">
<item name="android:background">@android:color/holo_green_dark</item>
<item name="android:titleTextStyle">@style/MyActionBarTitleText</item>

<item name="background">@android:color/holo_green_dark</item>
<item name="titleTextStyle">@style/MyActionBarTitleText</item>
</style>

<style name="MyActionBarTitleText"
parent="@style/TextAppearance.AppCompat.Widget.ActionBar.Title">
<item name="android:textColor">@android:color/holo_red_light</item>

</style>

<style name="MyActionBarTabText"
parent="@style/Widget.AppCompat.ActionBar.TabText">
<item name="android:textColor">@android:color/holo_blue_light</item>

</style>
</resources>


4. 利用ActionBar快速构造返回上级的按钮
截图:
![](http://upload-images.jianshu.io/upload_images/2369895-c87d204f1f047b1f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
设置步骤:
  1. ActionBarActivity或者AppCompatActivity的onCreate()方法中设置:
    * `getSupportActionBar().setDisplayHomeAsUpEnabled(true);`  v7库兼容下使用
    * `getActionBar().setDisplayHomeAsUpEnabled(true);`  非兼容形式,minSdkVersion>=11时使用
  2. 在想要设置此功能的Activity的<activity>标签中设置如下:
    ```
      <activity android:name=".xxxx.SecondActivity"
  android:label="ActionBar活动"
  android:parentActivityName=".MyToolBarActivity"    >
  <!--meta-data用于兼容support4.0以下,指明上级活动-->
  <meta-data
      android:name="android.support.PARENT_ACTIVITY"
      android:value="com.xxxxx.xxxxx.MainActivity"
      />
</activity>
    ```

## Toolbar
---
**一、背景**
* Android5.0推出的一个MD风格的导航栏。
* 旨在取代ActionBar

**二、优势**
* 比ActionBar更加灵活:
  * 设置导航栏图标
  * 设置App的logo
  * 支持设置标题和子标题
  * 支持添加一个或多个的自定义控件
  * 支持Action Menu
* 可以放置任何位置

**三、用法**
1. 导入**appcompat-v7** 的兼容包,使用 **android.support.v7.widget.Toolbar** 进行开发。
  ```
///基本格式
<android.support.v7.widget.Toolbar
       android:id="@+id/toolbar"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
  >
</android.support.v7.widget.Toolbar>
  ```
2. 设置属性
  1. 方式一:xml中设置(* 注意:v7兼容包的缘故,toolbar的属性不在系统中而需要额外查找导入,所有不能用`android:xxx`,而需要自定义`xmlns:toolbar="http://schemas.android.com/apk/res-auto"`,另外,这种方式难以绑定menu菜单 *)
    ```
<android.support.v7.widget.Toolbar
      android:id="@+id/toolbar"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="@color/colorAccent"
      toolbar:navigationIcon="@mipmap/ic_launcher"
      toolbar:logo="@mipmap/ic_launcher"
      toolbar:title="Title"
      toolbar:subtitle="subTitle"
      toolbar:titleTextColor="@color/colorPrimary"
      toolbar:subtitleTextColor="@color/colorPrimaryDark"
  >
  <!--引入普通View-->
  <TextView
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
         android:layout_margin="20dp"
         android:text="点击"
      />
  <!--引入自定义View-->
  <include
          layout="@layout/view_custom"/>
  </android.support.v7.widget.Toolbar>
    ```

    ![方式一截图](http://upload-images.jianshu.io/upload_images/2369895-395aa3bbd52008a1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

  2. 方式二:Java中设置
    ```
Toolbar toolbar  = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.mipmap.ic_launcher);///导航icon
toolbar.setLogo(android.R.drawable.ic_menu_search);///logo
toolbar.setTitle("Title");///标题
toolbar.setSubtitle("subTitle");///子标题
toolbar.addView(new Button(this));//可自己动态加CustomView
toolbar.inflateMenu(R.menu.activity_actionbar);///设置menu
    ```
     ![方式二截图](http://upload-images.jianshu.io/upload_images/2369895-c4e559b8db4a60ad.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

3. 扩展
  * 改变menu item的文字颜色
    * 首先,在themes.xml文件中添加一个<style>,注意parent为**parent="Theme.AppCompat.Light.NoActionBar"**
      ```
<style name="MyToolbarStyle" parent="Theme.AppCompat.Light.NoActionBar">
  <item name="android:textColorPrimary">@android:color/holo_red_light</item>
</style>
      ```
    * 然后,给toolbar加上属性:** toolbar:popupTheme="@style/MyToolbarStyle"**
      ```
<android.support.v7.widget.Toolbar
  android:id="@+id/toolbar"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:background="@color/colorAccent"
  toolbar:popupTheme="@style/MyToolbarStyle"/>
      ```
     ![ 改变menu item的文字颜色](http://upload-images.jianshu.io/upload_images/2369895-e016baae7a52bd44.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

## 感谢阅读
---
点击进入:[我的博客](http://androidjp.cn)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,389评论 25 707
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,394评论 2 45
  • 曾经做大学毕业论文的某天,本来就心情不太好,发现夹在论文稿里面的封面不见了,就轻声说“肯定是有人拿走了”,旁边一室...
    AskYp阅读 310评论 4 1
  • 昨天,何洁和赫子铭出现婚姻危机上了热搜,疑似赫子铭的情感电台录音、何洁闺蜜和制片人的爆料、微博上情绪低落的文字,各...
    燚燚好运祈福阅读 792评论 1 6
  • 起床→刷牙→洗脸→喝水→喝奶→整理着装,这是大部分人醒来后做事情的秩序; 喝汤→送菜拌饭,这是大部分人吃饭时的秩序...
    珊珊0329阅读 368评论 0 0