转载

Android Theme主题菜单相关

Demo

学了一下Chris Banes大神的项目。总结一下theme相关的小知识点。先看个定义主题的不错的小case:在values目录下建立两个命名为themes的文件:

themes.xml

<resources xmlns:android="http://schemas.android.com/apk/res/android">

<style name="Platform.Theme.AnDream" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowActionModeOverlay">true</item>
</style>

<style name="Platform.Theme.AnDream.Dark" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowActionModeOverlay">true</item>
</style>

<style name="Base.Theme.AnDream" parent="Platform.Theme.AnDream">
<item name="android:windowContentOverlay">@null</item>
</style>

<style name="Base.Theme.AnDream.Dark" parent="Platform.Theme.AnDream.Dark">
<item name="android:windowContentOverlay">@null</item>
</style>

<style name="Theme.AnDream" parent="Base.Theme.AnDream">
<item name="android:textColorHighlight">@color/primary_color_translucent</item>

<item name="android:progressBarStyleHorizontal">@style/Widget.AnDream.ProgressBar</item>
<item name="android:ratingBarStyle">@style/Widget.AnDream.RatingBar</item>
// 这个是自定义主题的属性,在attrs里面
<item name="grey_shade">@color/light_gray</item>

<item name="windowActionModeOverlay">true</item>

<item name="colorPrimary">@color/primary_color</item>
<item name="colorPrimaryDark">@color/primary_color_dark</item>
<item name="colorAccent">@color/accent_color</item>
</style>

<style name="Theme.AnDream.Images" parent="Base.Theme.AnDream.Dark">
<item name="android:windowBackground">@android:color/black</item>
</style>

<style name="Theme.AnDream.Framed" parent="Theme.AnDream">
<item name="windowActionBarOverlay">false</item>
</style>

</resources>

themes.xml(v21):

<resources>
//这里体会一下 设置状态栏透明,设置windowDrawsSystemBarBackgrounds true
<style name="Platform.Theme.AnDream" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>

<style name="Platform.Theme.AnDream.Dark" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>

</resources>

分析

层次比较清晰。

  • 根据平台分别兼容holo和design的Platform.Theme.AnDream和Platform.Theme.AnDream.Dark
  • 子base主题:Base.Theme.AnDream和Base.Theme.AnDream.Dark
  • 然后程序用的主题Theme.AnDream。以及继承自Base.Theme.AnDream.Dark的Theme.AnDream.Images
  • 最后一个是程序主题Theme.AnDream的一个扩展Theme.AnDream.Framed。

层次非常清晰,是个不错的建主题的样例,基本各种需要的主题就都有了。

主题的源头是系统的Theme.AppCompat.Light.NoActionBar和Theme.AppCompat.NoActionBar。兼容包里没有ActionBar的浅色和深色主题,用这组主题方便我们后续自由的使用toolbar。

另外点进去看到appcompat源码里的:

<style name="Theme.AppCompat.Light.NoActionBar">
<item name="windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>

demo里意义比较模糊的属性有:

overlays 是覆盖物的意思。

  • <item name="android:windowActionModeOverlay">true</item>

    and the actionmode will be shown over the action bar instead of pushing it down.It basically lets AppCompat know that you have a toolbar located in the top of the screen and that it should draw the ActionMode on top of it.ActionMode显示在顶栏,而不是屏幕中的菜单。告诉appcompat你有个toolbar在屏幕顶上,它应该把ActionMode画到toolbar上面。

  • <item name="android:windowContentOverlay">@null</item>
    定义contentoverlay的背景的,ContentOverlay背景为null 和actionbar下面的阴影有关
  • <item name="android:textColorHighlight">@color/primary_color_translucent</item>
    高亮字体颜色
  • <item name="android:windowBackground">@android:color/black</item>
    屏幕背景色
  • <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    需要绘制系统操作栏背景
  • <item name="android:statusBarColor">@android:color/transparent</item> 设置状态栏透明

另外菜单的写法例如:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/new_game"
android:icon="@drawable/ic_new_game"
android:title="@string/new_game"
android:showAsAction="ifRoom"/>

<item android:id="@+id/help"
android:icon="@drawable/ic_help"
android:title="@string/help" />

</menu>
  • android:icon
    引用一个要用作项目图标的 Drawable 类。
  • android:title
    引用一个要用作项目标题的字符串。
  • android:showAsAction
    指定此项应作为操作项目显示在操作栏中的时间和方式。

toolbar右边的三个点是 操作栏右侧的操作溢出菜单,与手机物理菜单按键作用一样

需要支持快速访问的重要操作,可以在相应的 中添加 android:showAsAction=”ifRoom” ,从而将此项提升到操作栏中。

android:showAsAction总共有五个属性。

  • never:永远不会显示。只会在溢出列表中显示。
  • ifRoom:会显示在Item中,但是如果已经有4个或者4个以上的Item时会隐藏在溢出列表中。
  • always:无论是否溢出,总会显示。
  • withText:Title会显示。
  • collapseActionView:可拓展的Item。

小拓展:

Android 2.3.x 及更低版本的系统,则当用户首次打开选项菜单时,系统会调用 onCreateOptionsMenu() 来创建该菜单。如果您开发的应用是用于 Android 3.0 及更高版本的系统,则系统将在启动 Activity 时调用 onCreateOptionsMenu(),以便向操作栏显示项目。

在 Activity 生命周期中发生的事件修改选项菜单,则可通过 onPrepareOptionsMenu() 方法执行此操作。

在 Android 2.3.x 及更低版本中,每当用户打开选项菜单时(按“菜单”按钮),系统均会调用 onPrepareOptionsMenu()。

在 Android 3.0 及更高版本中,当菜单项显示在操作栏中时,选项菜单被视为始终处于打开状态。发生事件时,如果您要执行菜单更新,则必须调用 invalidateOptionsMenu() 来请求系统调用 onPrepareOptionsMenu()。

要想长按(或者选中复选框或视图内的类似 UI 组件)显示出来上下文操作模式,如网易新闻长按顶部出现的复制粘贴等。有的控件webview会默认实现。

为单个视图启用上下文操作模式

如果希望仅当用户选择特定视图时才调用上下文操作模式,则应:

实现 ActionMode.Callback 接口。在其回调方法中,您既可以为上下文操作栏指定操作,又可以响应操作项目的点击事件,还可以处理操作模式的其他生命周期事件。

当需要显示操作栏时(例如,用户长按视图),请调用 startActionMode()。

private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {

// Called when the action mode is created; startActionMode() was called
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
return true;
}

// Called each time the action mode is shown. Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}

// Called when the user selects a contextual menu item
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_share:
shareCurrentItem();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}

// Called when the user exits the action mode
@Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};
正文到此结束
Loading...