您的位置:首页 > 移动开发 > Android开发

Android学习之界面篇(七)侧滑菜单的实现

2016-05-02 00:33 591 查看
侧滑菜单的实现方式:

SlidingMenu开源库:https://github.com/jfeinstein10/SlidingMenu
DrawerLayout:是2013年谷歌IO大会上由谷歌官方发布的,包含在support v4包中。

官方定义:http://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html

使用说明:http://developer.android.com/training/implementing-navigation/nav-drawer.html

接下来按照谷歌官方给定的创建步骤来实现一个侧滑菜单。

Create a Drawer Layout

To add a navigation drawer, declare your user interface with a
DrawerLayout
object
as the root view of your layout.

Inside the
DrawerLayout
,
add one view that contains the main content for the screen (your primary layout when the drawer is hidden) and another view that contains the contents of the navigation drawer.

按照谷歌官方给出的示例创建一个带有Drawer Layout的项目:

activity_main.xml配置如下:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/draw_layout"
android:layout_height="match_parent"
android:layout_width="match_parent">

<!--The main content view-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/content_frame">

</FrameLayout>

<!--The navigation view-->
<ListView
android:layout_width="240dp"
android:layout_height="match_parent"
android:id="@+id/left_drawer"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:background="#ffffcc"
android:divider="@android:color/transparent"
android:dividerHeight="0dp">

</ListView>

</android.support.v4.widget.DrawerLayout>


启动项目,通过从屏幕左端滑动来滑出菜单。

注:

android:layout_gravity="start"是从屏幕左边滑动,"end"则为从屏幕右端滑出。

android:choiceMode="singleChoice"模式为单选模式

android:divider="@android:color/transparent"分割线采用原始的透明分割线

android:dividerHeight="0dp"分割线高度为0,不可见。

注意事项:

主内容视图一定要是DrawerLayout的第一个子视图
主内容视图宽度高度要匹配父视图,即"match_parent",也就是说:当抽屉隐藏时,要让用户看到主视图的全部内容。
必须显示指定抽屉视图(如LiistView)的android:layout_gravity属性。

android:layout_gravity="start"从左向右滑出菜单
android:layout_gravity="end"从右向左滑出菜单
不推荐使用"left" 和"right"

4.抽屉视图的宽度以dp为单位,请不要超过320dp(为了总能看到一些主内容视图)

Initialize the Drawer List

In your activity, one of the first things to do is initialize the navigation drawer's list of items. How you do so depends on the content of your app, but a navigation drawer often consists of a
ListView
,
so the list should be populated by an
Adapter
(such
as
ArrayAdapter
or
SimpleCursorAdapter
).

接下来在项目中实现初始化Drawer List的操作。

1.首先对组件进行声明,包括DrawerLayout和ListView。

private DrawerLayout mDrawerLayout;

private ListView mDrawerList;

2.使用ArrayList集合来储存菜单项,使用ArrayAdapter对ListView的内容进行填充。

//使用集合来储存侧滑菜单的菜单项

private ArrayList<String> menuLists;

//使用ArrayAdapter来对ListView的内容进行填充

private ArrayAdapter<String> adapter;

3.在onCreate方法中对z组件进行查找和初始化数据操作。

mDrawerLayout= (DrawerLayout) findViewById(R.id.draw_layout);

mDrawerList= (ListView) findViewById(R.id.left_drawer);

//初始化menulists

menuLists=new ArrayList<String>();

for (int i=0;i<5;i++){

menuLists.add("测试菜单"+i);

}

//初始化adapter

adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,menuLists);

//为侧边菜单填充上内容

mDrawerList.setAdapter(adapter);



Handle Navigation Click Events

When the user selects an item in the drawer's list, the system calls
onItemClick()
on
the
OnItemClickListener
given
to
setOnItemClickListener()
.

What you do in the
onItemClick()
method depends on how you've implemented your app
structure.

1.为菜单项添加点击事件监听器,并让主类实现事件监听器接口

mDrawerList.setOnItemClickListener(this);

2.复写事件监听器中的方法,动态插入一个Fragment到FrameLayout中去

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

//动态插入一个Fragment到FrameLayout当中

Fragment contentFragment=new ContentFragment();

Bundle args=new Bundle();

args.putString("text",menuLists.get(position));

contentFragment.setArguments(args);//?

//新建一个Fragment

FragmentManager fm=getFragmentManager();

fm.beginTransaction().replace(R.id.content_frame,contentFragment).commit();

//点击完成后关闭菜单栏

mDrawerLayout.closeDrawer(mDrawerList);

}

3.新建一Fragment ContentFragment,对应配置文件为fragment_content.xml

fragment_content.xml配置如下:

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

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:id="@+id/content_frame"

tools:context="com.example.icarus.drawerlayoutusing.ContentFragment">

<!-- TODO: Update blank fragment layout -->

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:id="@+id/textView"

android:textSize="25sp"

/>

</FrameLayout>

ContentFragment.java具体代码:

public class ContentFragment extends Fragment {

private TextView textView;

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {

//动态加载视图

View view=inflater.inflate(R.layout.fragment_content,container,false);

//查找组件id

textView= (TextView) view.findViewById(R.id.textView);

//通过Arguments来传递数据

String text=getArguments().getString("text");

//给textview设置文字

textView.setText(text);

//返回加载的视图

return view;

}

}



问题:

1. 为什么要用Fragment.setArguments(Bundle
bundle)来传递参数


Activity重新创建时,会重新构建它所管理的Fragment,原先的Fragment的字段值将会全部丢失,但是通过Fragment.setArguments(Bundle
bundle)方法设置的bundle会保留下来。所以尽量使用Fragment.setArguments(Bundle bundle)方式来传递参数

具体:/article/1648943.html

Listen for Open and Close Events

To listen for drawer open and close events, call
setDrawerListener()
on
your
DrawerLayout
and pass it an implementation of
DrawerLayout.DrawerListener
.
This interface provides callbacks for drawer events such as
onDrawerOpened()
and
onDrawerClosed()
.
However, rather than implementing the
DrawerLayout.DrawerListener
,
if your activity includes the action bar, you can instead extend the
ActionBarDrawerToggle
class.
The
ActionBarDrawerToggle
implements
DrawerLayout.DrawerListener
so
you can still override those callbacks, but it also facilitates the proper interaction behavior between the action bar icon and the navigation drawer (discussed further in the next section).

As discussed in the Navigation
Drawer design guide, you should modify the contents of the action bar when the drawer is visible, such as to change the title and remove action items that are contextual to the main content.
知识点介绍:
1.mDrawerLayout.setDrawerListener(DrawerLayout.DrawerListener);
2.ActionBarDrawerToggle是 DrawerLayout.DrawerListener的具体实现类。
1)改变android.R.id.home图标(构造方法)
2)Drawer拉出、隐藏,带有android.R.id.home动画效果(syncState())
3)监听Drawer拉出、隐藏事件
3.复写ActionBarDrawerToggle的onDrawerOpended()和onDrawerClosed()以监听抽屉拉出或隐藏事件。
4.复写Activity中的onPostCreate()方法和onConfigurationChange()方法,是为了结合syncState()方法来s实现左上角图标动画的效果。当设备的y一些参数发生变化时(屏幕旋转等)就会调用onConfigurationChange方法,在方法中对ActionBarDrawerToggle进行配置。

在代码中实现:
(一)设置菜单被拉出时Title文字的改变

1.首先声明一个ActionBarDrawerToggle,注意是support.v7包中的(support.v4包中的已经失效)
使用v7替换v4方法请看:ActionBarDrawerToggle
is Deprecated


private ActionBarDrawerToggle mDrawerToggle;

2.接着初始化ActionBarDrawerToggle,(具体参数为:ActionBarDrawerToggle(Activity activity,
DrawerLayout drawerLayout,
int openDrawerContentD
escRes, int closeDrawerContentDescRes))并复写其中的onDrawerOpended()和onDrawerClosed()方法来实现拉出或隐藏抽屉时对Title的更改。
注:使用v7包的时候得使用getSupportActionBar()来设置Title信息

mDrawerToggle=new ActionBarDrawerToggle(this,mDrawerLayout,

R.string.drawer_open,R.string.drawer_close){

/**

* 当抽屉被打开是执行

* 设置抽屉被打开时的Title

* 通过getActionBar()来改变

* @param drawerView

*/

@Override

public void onDrawerOpened(View drawerView) {

super.onDrawerOpened(drawerView);

//BUG:此处产生空指针异常,使用getSupportActionBar()

//getActionBar().setTitle("请选择");

getSupportActionBar().setTitle("请选择");

invalidateOptionsMenu();//重绘actionbar上的菜单项,会自动调用onPrepareOptionsMenu方法

}

/**

* 当抽屉被关闭时执行

* 设置抽屉被关闭时的Title

* @param drawerView

*/

@Override

public void onDrawerClosed(View drawerView) {

super.onDrawerClosed(drawerView);

getSupportActionBar().setTitle(mTitle);

invalidateOptionsMenu();//重绘actionbar上的菜单项

}

};

3.给DrawerLayout添加DrawerListener。setDrawerListener以失效,使用addDrawerListener

mDrawerLayout.addDrawerListener(mDrawerToggle);

(二)在ActionBar上添加搜索图标
1.在res中新建menu文件夹,在其中添加main.xml,其中
android:showAsAction。
  这个属性可接受的值有:
  1、always:这个值会使菜单项一直显示在Action Bar上。
  2、ifRoom:如果有足够的空间,这个值会使菜单项显示在Action Bar上。
  3、never:这个值使菜单项永远都不出现在Action Bar上。
  4、withText:这个值使菜单项和它的图标,菜单文本一起显示。
main.xml配置如下:

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

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

xmlns:app="http://schemas.android.com/apk/res-auto">

<item

android:id="@+id/action_websearch"

android:icon="@drawable/action_search"

android:title="webSearch"

app:showAsAction="ifRoom|withText"/>

</menu>

2.在MainActivity中使用onCreateOptionsMenu()来加载menu

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.main,menu);

return true;

}

3.在执行invalidateOptionsMenu()方法时会调用onPrepareOptionsMenu(),复写此方法来实现菜单图标的显示状态。首先先获取Drawer的打开状态,当Drawer打开时菜单图标被隐藏,当Drawer关闭时显示菜单图标。即菜单图标的显示状态与Drawer的打开状态正好相反。

public boolean onPrepareOptionsMenu(Menu menu) {

//获取Drawer的打开状态

boolean isDrawerOpen=mDrawerLayout.isDrawerOpen(mDrawerList);

//对menuItem的可见状态进行改变,总是跟Drawer的打开状态相反

menu.findItem(R.id.action_websearch).setVisible(!isDrawerOpen);

return super.onPrepareOptionsMenu(menu);

}

4.使用onOptionsItemSelected()方法来为菜单项设置点击事件。让其使用系统浏览器打开指定的网页(百度)。

public boolean onOptionsItemSelected(MenuItem item) {

switch (item.getItemId()) {

case R.id.action_websearch:

Intent intent=new Intent();

intent.setAction("android.intent.action.VIEW");

Uri uri=Uri.parse("http://www.baidu.com");

intent.setData(uri);

startActivity(intent);

break;

}

return super.onOptionsItemSelected(item);

}



Open and Close with the App Icon

Users can open and close the navigation drawer with a swipe gesture from or towards the left edge of the screen, but if you're using the action
bar, you should also allow users to open and close it by touching the app icon. And the app icon should also indicate the presence of the navigation drawer with a special icon. You can implement all this behavior by using the
ActionBarDrawerToggle
shown
in the previous section.
To make
ActionBarDrawerToggle
work,
create an instance of it with its constructor, which requires the following arguments:

The
Activity
hosting the drawer.
The
DrawerLayout
.
A drawable resource to use as the drawer indicator.
The standard navigation drawer icon is available in the Download
the Action Bar Icon Pack.

A String resource to describe the "open drawer" action (for accessibility).
A String resource to describe the "close drawer" action (for accessibility).

Then, whether or not you've created a subclass of
ActionBarDrawerToggle
as
your drawer listener, you need to call upon your
ActionBarDrawerToggle
in
a few places throughout your activity lifecycle:
我们希望使用app的图标来打开和关闭侧边栏,根据谷歌开发者文档
1.首先打开ActionBar Icon的功能

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

2.使左上角的Home-Button可用,因为左上角的Home-Button也属于menu的一种所以点击时会回调onOptionItemSelected方法。

getSupportActionBar().setHomeButtonEnabled(true);

3.在 onOptionItemSelected方法中将ActionBar上的图标与Drawer结合起来。

if (mDrawerToggle.onOptionsItemSelected(item)){

return true;

}

4.需要将ActionDrawerToggler与DrawerLayout的状态同步 ,将ActionBarDrawerTaggler中的drawer图标,设置为ActionBar中的Home-Button的icon

public void onPostCreate(Bundle savedInstanceState, PersistableBundle persistentState) {

super.onPostCreate(savedInstanceState, persistentState);

mDrawerToggle.syncState();

}

5.谷歌开发者文档建议使用onConfigurationChanged方法 ,当屏幕旋转等发生Configuration变化的时候执行

public void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);

mDrawerToggle.onConfigurationChanged(newConfig);

}



到此,我们使用谷歌开发者文档提供的DrawerLayout成功完成了侧滑菜单的开发!
项目源码下载:
https://github.com/icaruswang/DrawerLayoutUsing
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: