抽屉式侧滑菜单详解,drawer详解

转载

前言rawerLayoutSupport Library包中实现滑菜效果的控件,可以drawerLayout是因第三方控件MenuDrawer等的出之后google而出drawerLayout为侧边和主内容区两部分,侧边可以根据手展开与drawerLayout自身特性),主内容区的内容可以随着菜的点化(需要使用者自己实现

drawerLayout的使用很方便,使用drawerLayout的要点如下:

1.drawerLayout是一个布局控件,跟LinearLayout等控件是一种西,但是drawerLayout有滑的功能。只要按照drawerLayout定布局方式写完布局,就能有滑的效果。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->

<android.support.v4.widget.DrawerLayout

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

    android:id="@+id/drawer_layout"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

    <!-- As the main content view, the view below consumes the entire

         space available using match_parent in both dimensions. -->

    <FrameLayout                                      //在这个地方可以写任何布局,也可以是FrameLayout布局然后嵌入fragement在里面即可

        android:id="@+id/content_frame"            //这个布局将显示到主界面上

        android:layout_width="match_parent"

        android:layout_height="match_parent" />


    <!-- android:layout_gravity="start" tells DrawerLayout to treat

         this as a sliding drawer on the left side for left-to-right

         languages and on the right side for right-to-left languages.

         The drawer is given a fixed width in dp and extends the full height of

         the container. A solid background is used for contrast

         with the content view. -->

    <ListView

        android:id="@+id/left_drawer"

        android:layout_width="240dp"

        android:layout_height="match_parent"

        android:layout_gravity="start"//这个属性很重要,设置为start时,抽屉将显示到屏幕的左边,为right时将显示到屏幕的右边

        android:choiceMode="singleChoice"

        android:divider="@android:color/transparent"

        android:dividerHeight="0dp"

        android:background="#111"/>

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

 

 

有两点要注意:主内容区的布局代码要放在侧滑菜单布局的前面,这可以帮助DrawerLayout判断谁是侧滑菜单,谁是主内容区;侧滑菜单的部分的布局(这里是ListView)可以设置layout_gravity属性,他表示侧滑菜单是在左边还是右边。

2.drawerLayout(或者右)的展开与藏可以被DrawerLayout.DrawerListener实现监听到,这样你就可以在菜展开与藏反生的刻做一些希望做的事情,比如更新actionbar等。如果你的activityactionbar是建你用ActionBarDrawerToggle听,ActionBarDrawerToggle实现DrawerListener,所以他能做DrawerListener可以做的任何事情,同能将drawerLayout的展开和藏与actionbarapp 图标起来,当展开与藏的图标有一定的平移效果,点击图标能展开或者藏菜

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

mDrawerToggle = new ActionBarDrawerToggle(

        this,                  /* host Activity */

        mDrawerLayout,         /* DrawerLayout object */

        R.drawable.ic_drawer,  /* nav drawer image to replace 'Up' caret */

        R.string.drawer_open,  /* "open drawer" description for accessibility */

        R.string.drawer_close  /* "close drawer" description for accessibility */

        ) {

    public void onDrawerClosed(View view) {

        getActionBar().setTitle(mTitle);

        invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()

    }

    public void onDrawerOpened(View drawerView) {

        getActionBar().setTitle(mDrawerTitle);

        invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()

    }

};

mDrawerLayout.setDrawerListener(mDrawerToggle);

 

3.为侧边

侧边只是一个普通的View,一般里面装的是ListView,看起来就像菜,他完全可以是一个buttontextView等等。然称,但跟Activity的菜形式是两事,Activity的菜只需要在源文件中定好,就能按照固定的形式示出来。而drawerLayout侧边单显示成什么完全是取决于你自己,同事件也完全由你自己去写。如下代所示我侧边是一个ListView示的:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

mDrawerList.setAdapter(new ArrayAdapter<String>(this,

            R.layout.drawer_list_item, mPlanetTitles));

mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

/* The click listner for ListView in the navigation drawer */

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) {

    // update the main content by replacing fragments

    Fragment fragment = new PlanetFragment();

    Bundle args = new Bundle();

    args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);

    fragment.setArguments(args);

    FragmentManager fragmentManager = getFragmentManager();

    fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();

    // update selected item and title, then close the drawer

    mDrawerList.setItemChecked(position, true);

    setTitle(mPlanetTitles[position]);

    mDrawerLayout.closeDrawer(mDrawerList);

}

 

4.在代中主展开与侧边

在点击侧边单选项候我往往需要藏菜示整个菜单对应的内容。DrawerLayout.closeDrawer方法用于侧边DrawerLayout.openDrawer方法用于展开侧边(参3点中的代部分)

5.如何在菜展开或者藏的候更新activitymenu

上面的的第2DrawerLayout.DrawerListener听展开与藏事件,在听的回方法中我invalidateOptionsMenu通知activitymenu,然后activity就有机会在onPrepareOptionsMenu方法中更新menu元素的示与

1

2

3

4

5

6

7

8

/* Called whenever we call invalidateOptionsMenu() */

@Override

public boolean onPrepareOptionsMenu(Menu menu) {

    // If the nav drawer is open, hide action items related to the content view

    boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);

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

    return super.onPrepareOptionsMenu(menu);

}

 

6.如何app图标候能展开或者侧边

一般的想法是在activityonOptionsItemSelected方法中判断点事件是否来自于app图标,然后用DrawerLayout.closeDrawerDrawerLayout.openDrawer藏与展开(参4点:在代中主展开与侧边)。但是drawerLayout提供了更雅的方式:使用ActionBarDrawerToggleonOptionsItemSelected方法。方法activityonOptionsItemSelected方法中根据传递进来的menu item做了上面我一般想法中提到的事情。用官方的法是”ActionBarDrawerTogglewill take care of this”。我只需这样做就ok了:

Activity中:

1

2

3

4

5

6

7

8

9

10

@Override

public booleanonOptionsItemSelected(MenuItem item) {

// The action bar home/up actionshould open or close the drawer.

// ActionBarDrawerToggle will takecare of this.

if(mDrawerToggle.onOptionsItemSelected(item)) {

return true;

}

……….//处理其他菜单点击事件

returnsuper.onOptionsItemSelected(item);

}

如果不仔细阅读官方文档,估(mDrawerToggle.onOptionsItemSelected(item)里的作用。也是我开始最疑惑的地方。

7. drawerLayoutFragment是什么关系?

看到很多使用drawerLayout的代中都同使用了Fragment会造成解,以使用drawerLayout用到Fragment,其实这错误的,使用Fragment是因滑菜被点候,主内容区如果内容比,用Fragment去填充会更容易,如果你的主内容区只是一个简单的字符串,只想在不同菜候更新一下字符串的内容,我得没必要用Fragment。不官方的例子其中,Fragment所做的就是更新字符串内容简单

最后我来看看一个完整的drawerLayout的例子,来源于官方网站的demo,代中反映了上述我提到的所有要点:

源码为negativeDrawer.zip

Activity

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

/*

 * Copyright 2013 The Android Open Source Project

 *

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */

package com.example.android.navigationdrawerexample;

import java.util.Locale;

import android.app.Activity;

import android.app.Fragment;

import android.app.FragmentManager;

import android.app.SearchManager;

import android.content.Intent;

import android.content.res.Configuration;

import android.os.Bundle;

import android.support.v4.app.ActionBarDrawerToggle;

import android.support.v4.view.GravityCompat;

import android.support.v4.widget.DrawerLayout;

import android.view.LayoutInflater;

import android.view.Menu;

import android.view.MenuInflater;

import android.view.MenuItem;

import android.view.View;

import android.view.ViewGroup;

import android.widget.AdapterView;

import android.widget.ArrayAdapter;

import android.widget.ImageView;

import android.widget.ListView;

import android.widget.Toast;

/**

 * This example illustrates a common usage of the DrawerLayout widget

 * in the Android support library.

 * <p/>

 * <p>When a navigation (left) drawer is present, the host activity should detect presses of

 * the action bar's Up affordance as a signal to open and close the navigation drawer. The

 * ActionBarDrawerToggle facilitates this behavior.

 * Items within the drawer should fall into one of two categories:</p>

 * <p/>

 * <ul>

 * <li><strong>View switches</strong>. A view switch follows the same basic policies as

 * list or tab navigation in that a view switch does not create navigation history.

 * This pattern should only be used at the root activity of a task, leaving some form

 * of Up navigation active for activities further down the navigation hierarchy.</li>

 * <li><strong>Selective Up</strong>. The drawer allows the user to choose an alternate

 * parent for Up navigation. This allows a user to jump across an app's navigation

 * hierarchy at will. The application should treat this as it treats Up navigation from

 * a different task, replacing the current task stack using TaskStackBuilder or similar.

 * This is the only form of navigation drawer that should be used outside of the root

 * activity of a task.</li>

 * </ul>

 * <p/>

 * <p>Right side drawers should be used for actions, not navigation. This follows the pattern

 * established by the Action Bar that navigation should be to the left and actions to the right.

 * An action should be an operation performed on the current contents of the window,

 * for example enabling or disabling a data overlay on top of the current content.</p>

 */

public class MainActivity extends Activity {

    private DrawerLayout mDrawerLayout;

    private ListView mDrawerList;

    private ActionBarDrawerToggle mDrawerToggle;

    private CharSequence mDrawerTitle;

    private CharSequence mTitle;

    private String[] mPlanetTitles;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mTitle = mDrawerTitle = getTitle();

        mPlanetTitles = getResources().getStringArray(R.array.planets_array);

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

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

        // set a custom shadow that overlays the main content when the drawer opens

        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

        // set up the drawer's list view with items and click listener

        mDrawerList.setAdapter(new ArrayAdapter<String>(this,

                R.layout.drawer_list_item, mPlanetTitles));

        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

        // enable ActionBar app icon to behave as action to toggle nav drawer

        getActionBar().setDisplayHomeAsUpEnabled(true);

        getActionBar().setHomeButtonEnabled(true);

        // ActionBarDrawerToggle ties together the the proper interactions

        // between the sliding drawer and the action bar app icon

        mDrawerToggle = new ActionBarDrawerToggle(

                this,                  /* host Activity */

                mDrawerLayout,         /* DrawerLayout object */

                R.drawable.ic_drawer,  /* nav drawer image to replace 'Up' caret */

                R.string.drawer_open,  /* "open drawer" description for accessibility */

                R.string.drawer_close  /* "close drawer" description for accessibility */

                ) {

            public void onDrawerClosed(View view) {

                getActionBar().setTitle(mTitle);

                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()

            }

            public void onDrawerOpened(View drawerView) {

                getActionBar().setTitle(mDrawerTitle);

                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()

            }

        };

        mDrawerLayout.setDrawerListener(mDrawerToggle);

        if (savedInstanceState == null) {

            selectItem(0);

        }

    }

    @Override

    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater inflater = getMenuInflater();

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

        return super.onCreateOptionsMenu(menu);

    }

    /* Called whenever we call invalidateOptionsMenu() */

    @Override

    public boolean onPrepareOptionsMenu(Menu menu) {

        // If the nav drawer is open, hide action items related to the content view

        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);

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

        return super.onPrepareOptionsMenu(menu);

    }

    @Override

    public boolean onOptionsItemSelected(MenuItem item) {

         // The action bar home/up action should open or close the drawer.

         // ActionBarDrawerToggle will take care of this.

        if (mDrawerToggle.onOptionsItemSelected(item)) {

            return true;

        }

        // Handle action buttons

        switch(item.getItemId()) {

        case R.id.action_websearch:

            // create intent to perform web search for this planet

            Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);

            intent.putExtra(SearchManager.QUERY, getActionBar().getTitle());

            // catch event that there's no activity to handle intent

            if (intent.resolveActivity(getPackageManager()) != null) {

                startActivity(intent);

            } else {

                Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show();

            }

            return true;

        default:

            return super.onOptionsItemSelected(item);

        }

    }

    /* The click listner for ListView in the navigation drawer */

    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) {

        // update the main content by replacing fragments

        Fragment fragment = new PlanetFragment();

        Bundle args = new Bundle();

        args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);

        fragment.setArguments(args);

        FragmentManager fragmentManager = getFragmentManager();

        fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();

        // update selected item and title, then close the drawer

        mDrawerList.setItemChecked(position, true);

        setTitle(mPlanetTitles[position]);

        mDrawerLayout.closeDrawer(mDrawerList);

    }

    @Override

    public void setTitle(CharSequence title) {

        mTitle = title;

        getActionBar().setTitle(mTitle);

    }

    /**

     * When using the ActionBarDrawerToggle, you must call it during

     * onPostCreate() and onConfigurationChanged()...

     */

    @Override

    protected void onPostCreate(Bundle savedInstanceState) {

        super.onPostCreate(savedInstanceState);

        // Sync the toggle state after onRestoreInstanceState has occurred.

        mDrawerToggle.syncState();

    }

    @Override

    public void onConfigurationChanged(Configuration newConfig) {

        super.onConfigurationChanged(newConfig);

        // Pass any configuration change to the drawer toggls

        mDrawerToggle.onConfigurationChanged(newConfig);

    }

    /**

     * Fragment that appears in the "content_frame", shows a planet

     */

    public static class PlanetFragment extends Fragment {

        public static final String ARG_PLANET_NUMBER = "planet_number";

        public PlanetFragment() {

            // Empty constructor required for fragment subclasses

        }

        @Override

        public View onCreateView(LayoutInflater inflater, ViewGroup container,

                Bundle savedInstanceState) {

            View rootView = inflater.inflate(R.layout.fragment_planet, container, false);

            int i = getArguments().getInt(ARG_PLANET_NUMBER);

            String planet = getResources().getStringArray(R.array.planets_array)[i];

            int imageId = getResources().getIdentifier(planet.toLowerCase(Locale.getDefault()),

                            "drawable", getActivity().getPackageName());

            ((ImageView) rootView.findViewById(R.id.image)).setImageResource(imageId);

            getActivity().setTitle(planet);

            return rootView;

        }

    }

}

 

Xml

activity_main.xml

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

<!--

  Copyright 2013 The Android Open Source Project

  Licensed under the Apache License, Version 2.0 (the "License");

  you may not use this file except in compliance with the License.

  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software

  distributed under the License is distributed on an "AS IS" BASIS,

  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  See the License for the specific language governing permissions and

  limitations under the License.

  -->

<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->

<android.support.v4.widget.DrawerLayout

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

    android:id="@+id/drawer_layout"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

    <!-- As the main content view, the view below consumes the entire

         space available using match_parent in both dimensions. -->

    <FrameLayout

        android:id="@+id/content_frame"

        android:layout_width="match_parent"

        android:layout_height="match_parent" />

    <!-- android:layout_gravity="start" tells DrawerLayout to treat

         this as a sliding drawer on the left side for left-to-right

         languages and on the right side for right-to-left languages.

         The drawer is given a fixed width in dp and extends the full height of

         the container. A solid background is used for contrast

         with the content view. -->

    <ListView

        android:id="@+id/left_drawer"

        android:layout_width="240dp"

        android:layout_height="match_parent"

        android:layout_gravity="start"

        android:choiceMode="singleChoice"

        android:divider="@android:color/transparent"

        android:dividerHeight="0dp"

        android:background="#111"/>

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

fragment_planet.xml

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<!--

  Copyright 2013 The Android Open Source Project

  Licensed under the Apache License, Version 2.0 (the "License");

  you may not use this file except in compliance with the License.

  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software

  distributed under the License is distributed on an "AS IS" BASIS,

  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  See the License for the specific language governing permissions and

  limitations under the License.

  -->

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

    android:id="@+id/image"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:background="#000000"

    android:gravity="center"

    android:padding="32dp" />

drawer_list_item.xml

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

<!--

  Copyright 2013 The Android Open Source Project

  Licensed under the Apache License, Version 2.0 (the "License");

  you may not use this file except in compliance with the License.

  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software

  distributed under the License is distributed on an "AS IS" BASIS,

  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  See the License for the specific language governing permissions and

  limitations under the License.

  -->

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

    android:id="@android:id/text1"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:textAppearance="?android:attr/textAppearanceListItemSmall"

    android:gravity="center_vertical"

    android:paddingLeft="16dp"

    android:paddingRight="16dp"

    android:textColor="#fff"

    android:background="?android:attr/activatedBackgroundIndicator"

    android:minHeight="?android:attr/listPreferredItemHeightSmall"/>

源码:http://download.csdn.net/detail/u011514076/8561385

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值