android(一) 菜单创建

android中当我们需要进行相应的页面跳转时,我们可以通过菜单的方式来对页面进行切换,如下是一个比较传统的menu布局:

"http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.demo.mianhai.woyaodushu.MainActivity" >
    <item
        android:id="@+id/action_new"
        android:orderInCategory="1"
        android:title="SubMenu"
        android:icon="@drawable/ic_drawer_home"
        app:showAsAction="always">
        
            <item android:id="@+id/submenu1"
                android:title="Accept"
                android:titleCondensed="Accept"
                android:icon="@drawable/ic_notifications" />
            <item android:id="@+id/submenu2"
                android:title="Cancel"
                android:titleCondensed="Cancel"
                android:icon="@drawable/ic_notifications" />
            <item android:id="@+id/submenu3"
                android:title="Unread"
                android:titleCondensed="Unread"
                android:icon="@drawable/ic_notifications" />
        
    item>
    <item
        android:id="@+id/action_overflow"
        android:orderInCategory="2"
        android:title="PopupWindow"
        android:icon="@drawable/ic_menu_more_overflow"
        app:showAsAction="always"/>

由上我们可以获得一个差不多类似于微信悬浮窗的效果,如图(+号所显示的内容,图片来自网络)android(一) 菜单创建_第1张图片

以上看名字都可以理解的我就不解释了

  • orderInCategory:通过设置数值的大小来决定优先级,值越大优先级就越低,这样当actionbar空间位置不够时就会被隐藏掉
  • showAsAction:可填的数值有ifRoom、never、always、withText、collapseActionView,可以混合使用。

  • ifRoom 会显示在Item中,但是如果已经有4个或者4个以上的Item时会隐藏在溢出列表中。当然个数并不仅仅局限于4个,依据屏幕的宽窄而定

  • never 永远不会显示。只会在溢出列表中显示,而且只显示标题,所以在定义item的时候,最好把标题都带上。

  • always 无论是否溢出,总会显示。

  • withText withText值示意Action bar要显示文本标题。Actionbar会尽可能的显示这个标题,但是,如果图标有效并且受到Action bar空间的限制,文本标题有可能显示不全。

  • collapseActionView 声明了这个操作视窗应该被折叠到一个按钮中,当用户选择这个按钮时,这个操作视窗展开。否则,这个操作视窗在默认的情况下是可见的,并且即便在用于不适用的时候,也要占据操作栏的有效空间。

一般我们设置ifroom就行了,当然也可以混合显示,看需求决定,那么如上的视图我们要如何实现呢?这里列举了几种比较常规的方法,看情况决定哪一种。
通过PopupWindow来实现,代码如下:

package com.demo.mianhai.woyaodushu;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.PopupWindow;

public class Main3Activity extends AppCompatActivity {

    Toolbar toolbar = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu items for use in the action bar
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu3, menu);
        return true;
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        switch (id) {
            case R.id.action_overflow:
                popUpMyOverflow();//弹出自定义overflow
                return true;
        }
        return super.onOptionsItemSelected(item);
    }


    public void popUpMyOverflow() {
        /**
         * 定位PopupWindow,让它恰好显示在Action Bar的下方。 通过设置Gravity,确定PopupWindow的大致位置。
         * 首先获得状态栏的高度,再获取Action bar的高度,这两者相加设置y方向的offset样PopupWindow就显示在action
         * bar的下方了。 通过dp计算出px,就可以在不同密度屏幕统一X方向的offset.但是要注意不要让背景阴影大于所设置的offset,
         * 否则阴影的宽度为offset.
         */
        // 获取状态栏高度
        Rect frame = new Rect();
        getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
//        状态栏高度:frame.top,这里的R.layout.activity_tool_bar其实就是上图中的第二个菜单按钮显示出来的视图
        int xOffset = frame.top+this.getSupportActionBar().getHeight()-25;//减去阴影宽度,适配UI.
        int yOffset = Dp2Px(this, 5f); //设置x方向offset为5dp
        View parentView = getLayoutInflater().inflate(R.layout.activity_main,
                null);
        View popView = getLayoutInflater().inflate(
                R.layout.activity_tool_bar, null);
        PopupWindow popWind = new PopupWindow(popView,
                Toolbar.LayoutParams.WRAP_CONTENT,  Toolbar.LayoutParams.WRAP_CONTENT, true);//popView即popupWindow的布局,ture设置focusAble.

        //必须设置BackgroundDrawable后setOutsideTouchable(true)才会有效。这里在XML中定义背景,所以这里设置为null;
        popWind.setBackgroundDrawable(new BitmapDrawable(getResources(),
                (Bitmap) null));
        popWind.setOutsideTouchable(true); //点击外部关闭。
        popWind.setAnimationStyle(android.R.style.Animation_Dialog);    //设置一个动画。
        //设置Gravity,让它显示在右上角。
        popWind.showAtLocation(parentView, Gravity.RIGHT | Gravity.TOP,
                yOffset, xOffset);
    }

    public int Dp2Px(Context context, float dp) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dp * scale + 0.5f);
    }
}

你以为这样就完了?不,由于我的安卓版本是5.0的,所以相应的继承的类是AppCompatActivity,默认的actionbar是悬浮效果的,我们需要在value/style.xml中更改如下代码:

   

    

如果你这边需要做到像知乎一样的菜单的话,只需将overlapAnchor改为true,如下:

第二种方法,通过设置在menu.xml中的item中设置actionProviderClass属性,来创建子菜单。菜单如下:


<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.demo.mianhai.woyaodushu.MainActivity"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/search_menu"
        android:icon="@mipmap/ic_search"
        android:title="@string/search_menu"
        app:actionProviderClass="com.demo.mianhai.woyaodushu.actionprovide.MenuProvide"
        app:showAsAction="always"
        />
    <item
        android:id="@+id/notify_menu"
        android:icon="@mipmap/ic_notifications"
        android:title="@string/notify_menu"
        app:showAsAction="ifRoom"
        />
    <item
        android:id="@+id/setting"
        android:icon="@mipmap/ic_menu_more_overflow"
        android:title="设置"
        app:showAsAction="never"
        />
    <item
        android:id="@+id/about"
        android:icon="@mipmap/ic_menu_more_overflow"
        android:title="关于"
        app:showAsAction="never"
        />
menu>

MenuProvide类的实现如下:

public class MenuProvide extends ActionProvider {
    /**
     * Creates a new instance.
     *
     * @param context Context for accessing resources.
     */
    public MenuProvide(Context context) {
        super(context);
    }

    @Override
    public View onCreateActionView() {
        return null;
    }

    @Override
    public void onPrepareSubMenu(SubMenu subMenu) {
        subMenu.clear();
        subMenu.add("sub item 1").setIcon(R.mipmap.ic_notifications)
                .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                    @Override
                    public boolean onMenuItemClick(MenuItem item) {
                        return true;
                    }
                });
        subMenu.add("sub item 2").setIcon(R.mipmap.ic_search)
                .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                    @Override
                    public boolean onMenuItemClick(MenuItem item) {
                        return false;
                    }
                });
    }
    @Override
    public boolean hasSubMenu() {
        return true;
    }
}

以上的类可以清晰的看出我们对submenu进行了重写赋值,为其添加了子菜单,这里我们同样可以获取类似于以下的效果
android(一) 菜单创建_第2张图片
一般我们用ActionProvider往往还要讲到他的儿子ShareActionProvider,但这里就不做特别的详解了,直接贴相关的代码,步骤如下:

1 在rest下创建Asset这个文件夹,放入你想放的图片
2. 在menu中进行配置文件,如下:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_search"
        android:icon="@drawable/ic_search"
        android:title="@string/action_search"
        app:showAsAction="ifRoom"
        app:actionViewClass="android.support.v7.widget.SearchView"/>
    <item
        android:id="@+id/action_share"
        android:icon="@drawable/ic_share"
        android:title="@string/action_share"
        app:actionProviderClass="android.support.v7.widget.ShareActionProvider"
        app:showAsAction="ifRoom"/>
menu>

在Activity中添加如下代码:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu items for use in the action bar
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);
    MenuItem shareItem = menu.findItem(R.id.action_share);
    ShareActionProvider shareActionProvider = (ShareActionProvider)
            MenuItemCompat.getActionProvider(shareItem);
    shareActionProvider.setShareIntent(getDefaultIntent());
    return super.onCreateOptionsMenu(menu);
}

private Intent getDefaultIntent() {
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("image/*");
    return intent;
}

一般可以获得如下的效果图:
android(一) 菜单创建_第3张图片

使用material design 来设计toolbar

相比与android自带的toolbar,我们更倾向于使用material design的设计风格,那么我们首先需要将我们需要的包给导进来,在app/build.gradle 下添加如下代码

 compile 'com.android.support:design:23.2.1'

由于我用的sdk是23的,所以这里的版本你要根据实际情况来写。
接下来我们可以新建一个layout,用于放我们的toolbar,如下:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:toolbar="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimaryDark"
        android:theme="@style/Theme.ToolBar.ZhiHu">
    android.support.v7.widget.Toolbar>
LinearLayout>

由于我们的布局存在了toolbar了,所以我们需要将默认的toolbar给关掉,在AndroidManifest.xml下对theme主题进行更改,如下:

android:theme="@style/Theme.ToolBar.Base"

res/value/style.xml 加入如下代码:

  <style name="Theme.ToolBar.Base" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:textColorPrimary">@color/colorPrimaryDark
    "actionOverflowButtonStyle">@style/ActionButton.Overflow.ZhiHu
  style>

  
  <style name="ActionButton.Overflow.ZhiHu" parent="android:style/Widget.Holo.Light.ActionButton.Overflow">
    <item name="android:src">@drawable/ic_menu_more_overflow
  style>

上面如果不加@style/ActionButton.Overflow.ZhiHu显示出来的效果图是这样的:
android(一) 菜单创建_第4张图片

接下来在我们的主类下添加如下代码:

public class MainActivity extends AppCompatActivity {

    Toolbar toolbar = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       // requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_tool_bar);
       initToolBar();
    }

    private void initToolBar(){
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setNavigationIcon(R.mipmap.ic_drawer_home);//设置导航栏图标
        //toolbar.setLogo(R.mipmap.ic_launcher);//设置app logo
        //toolbar.setTitle("Title");//设置主标题
        //toolbar.setSubtitle("Subtitle");//设置子标题

        toolbar.inflateMenu(R.menu.zhihu_menu);//设置右上角的填充菜单

        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                int menuItemId = item.getItemId();
                if (menuItemId == R.id.setting) {
                    Toast.makeText(MainActivity.this , R.string.item_01 , Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.about) {
                    Toast.makeText(MainActivity.this , R.string.item_02 , Toast.LENGTH_SHORT).show();

                }
                return true;
            }
        });
    }
}

menu菜单布局

"http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  tools:context="com.demo.mianhai.woyaodushu.MainActivity"
  xmlns:app="http://schemas.android.com/apk/res-auto">
  <item
    android:id="@+id/search_menu"
    android:icon="@drawable/ic_search"
    android:title="@string/search_menu"
    app:showAsAction="always"
    />
  <item
    android:id="@+id/notify_menu"
    android:icon="@drawable/ic_notifications"
    android:title="@string/notify_menu"
    app:showAsAction="ifRoom"
    />
  <item
    android:id="@+id/setting"
    android:icon="@drawable/ic_menu_more_overflow"
    android:title="设置"
    app:showAsAction="never"
    />
  <item
    android:id="@+id/about"
    android:icon="@drawable/ic_menu_more_overflow"
    android:title="关于"
    app:showAsAction="never"
    />

这就不添图了,这边我们只需要如何使用material design的toolbar就行了,下面我们再来讲解一下toolbar + drawerlayer 实现抽屉布局效果,这种效果一般对功能点比较多的可以考虑使用,如下就是一个我们比较常见的抽屉效果图:

android为我们提供了一个简单的drawerlayout布局然我们可以轻松实现这个效果,如下是实现代码:

package com.demo.mianhai.hbook;

import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

public class DrawerActivity extends AppCompatActivity {

  Toolbar toolbar = null;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_drawer);
    initToolBar();
  }

  private void initToolBar(){
    toolbar = (Toolbar) findViewById(R.id.toolBar);
    //toolbar.setNavigationIcon(R.drawable.ic_drawer_home);//设置导航栏图标
    //toolbar.setLogo(R.mipmap.ic_launcher);//设置app logo
    //toolbar.setTitle("Title");//设置主标题
    //toolbar.setSubtitle("Subtitle");//设置子标题

    DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
    toolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
    setSupportActionBar(toolbar);
    ActionBarDrawerToggle actionBarDrawerToggle=new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.open_string,R.string.close_string);
    actionBarDrawerToggle.syncState();

    drawerLayout.addDrawerListener(actionBarDrawerToggle);


  }
}

layout.xml代码如下:

.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/drawer"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context="com.demo.mianhai.hbook.DrawerActivity">

  "fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    .support.v7.widget.Toolbar
      android:id="@+id/toolBar"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:background="@color/colorPrimary"
      android:minHeight="?attr/actionBarSize"
      >

    .support.v7.widget.Toolbar>

    "@+id/contentFL"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:layout_below="@+id/toolBar" >
    

  


  "@+id/menuLL"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_gravity="start"
    android:clickable="true"
    android:background="@android:color/white"
    android:orientation="vertical">

    "wrap_content"
      android:layout_height="wrap_content"
      android:text="sss"
      />
  
.support.v4.widget.DrawerLayout>

需要注意的是,这边我们需要用到material design里面的toolbar来实现,如果是用系统默认的话,那么布局会往下跑,这个下面会讲,运行完就可以出现上面类似于上面的布局效果了。
如果我们要实现的效果是把布局放到toolbar下面呢,如图所示:

这边我们需要对我们的布局xml做一些微调,让他用的是我们的系统自带的那个,布局xml如下:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/drawer"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context="com.demo.mianhai.hbook.DrawerActivity">

  <RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <FrameLayout
      android:id="@+id/contentFL"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:layout_below="@+id/toolBar" >
    FrameLayout>

  RelativeLayout>


  <LinearLayout
    android:id="@+id/menuLL"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_gravity="start"
    android:clickable="true"
    android:background="@android:color/white"
    android:orientation="vertical">
    <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="sss"
      />
  LinearLayout>
android.support.v4.widget.DrawerLayout>

代码:

package com.demo.mianhai.hbook;

import android.os.Bundle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;

public class Drawer2Activity extends AppCompatActivity {

  private DrawerLayout drawerLayout = null;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_drawer2);

    drawerLayout= (DrawerLayout) findViewById(R.id.drawer);

    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    ActionBarDrawerToggle actionBarDrawerToggle=new ActionBarDrawerToggle(this,drawerLayout,R.string.open_string,R.string.close_string);
    actionBarDrawerToggle.syncState();
    drawerLayout.addDrawerListener(actionBarDrawerToggle);


  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    //noinspection SimplifiableIfStatement
    if (id == android.R.id.home) {
      if(  drawerLayout.isDrawerOpen(GravityCompat.START)
          ){
        drawerLayout.closeDrawers();
      }else{
        drawerLayout.openDrawer(GravityCompat.START);
      }
      return true;
    }
    return super.onOptionsItemSelected(item);
  }
}

androidmanifest.xml

<activity
            android:name=".activity.DrawerLayout2Activity"
            android:theme="@style/AppTheme"
            android:label="@string/title_activity_drawer_layout2" >
        activity>

好了上面的简单效果图也出来了

未完待续

参考文献:
http://www.jianshu.com/p/d70e2fd4d0be
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1120/2021.html
https://developer.android.google.cn/guide/index.html
http://m.blog.csdn.net/Guofengpu/article/details/51965925
http://www.jianshu.com/p/ae0013a4f71a
http://www.jianshu.com/p/0acc12c29c1b
http://www.jianshu.com/p/79604c3ddcae
http://www.jianshu.com/p/3fe2acac0ddb

你可能感兴趣的:(android开发)