Android中如何自定义Menu菜单

我们又如何来自定义Menu呢?下面我就主要来讲讲如何在Android上自定义Menu菜单,希望对大家有所帮助。 用过UCWEB-Android版的人都应该对其特殊的menu有印象,把menu做成Tab-Menu(支持分页的Menu),可以容纳比 Android传统的menu更丰富的内容(Android的menu超过6项则缩略在[更多]里),本文参考网上的例子(作 者:CoffeeCole,email:longkefan@foxmail.com),对例子进行简化以及封装,使其作为一个复合控件融入自己的 framework。 先来看看本文程序运行的效果: TabMenu 本身就是一个PopupWindow,PopupWindow上面放了两个GridView,第一个GridView就是分页标签,位于 PopupWindow的顶部,第二个GridView是菜单,位于PopupWindow的主体。为了实现PopupWindow的弹出/退出的动画效 果,本文使用了以下代码: 在工程的res文件夹里添加anim子目录,再新建文件popup_enter.xml:

1

2

3

4

5

<?`xmlversion=“1.0”encoding=“utf-8”?>`

<`setxmlns:android=http://schemas.android.com/apk/res/android>`

<`translateandroid:fromYDelta=“100%p”android:toYDelta=“0”android:duration=“1000”/>`

<`alphaandroid:fromAlpha=“0.0”android:toAlpha=“1.0”android:duration=“1000”/>`

</`set>`

新建文件popup_exit.xml:

1

2

3

4

5

<?`xmlversion=“1.0”encoding=“utf-8”?>`

<`setxmlns:android=http://schemas.android.com/apk/res/android>`

<`translateandroid:fromYDelta=“0”android:toYDelta=“100%p”android:duration=“1000”/>`

<`alphaandroid:fromAlpha=“1.0”android:toAlpha=“0.0”android:duration=“1000”/>`

</`set>`

在工程的values文件夹里新建文件popup_animation.xml:

1

2

3

4

5

6

7

<?`xmlversion=“1.0”encoding=“utf-8”?>`

<`resources>`

<`stylename=“PopupAnimation”parent=“android:Animation”>`

<`itemname=“android:windowEnterAnimation”>@anim/popup_enter</item>`

<`itemname=“android:windowExitAnimation”>@anim/popup_exit</item>`

</`style>`

</`resources>`

main.xml的源码如下:

1

2

3

4

5

6

7

<?`xmlversion=“1.0”encoding=“utf-8”?>`

<`LinearLayoutandroid:id=“@+id/LinearLayout01”`

android:layout_width`="fill_parent"` `android:layout_height=“fill_parent”`

xmlns:android`="[http://schemas.android.com/apk/res/android](http://schemas.android.com/apk/res/android)">`

<`TextViewandroid:id=“@+id/TextView01”android:layout_height=“wrap_content”`

android:layout_width`="fill_parent"` `android:text="扩展Menu----hellogv"></TextView>`

</`LinearLayout>`

TabMenu的封装类TabMenu.java的源码如下:

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

214

215

package com.testTabMenu;

import android.content.Context;

import android.graphics.Color;

import android.graphics.drawable.ColorDrawable;

import android.view.Gravity;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.GridView;

import android.widget.ImageView;

import android.widget.LinearLayout;

import android.widget.PopupWindow;

import android.widget.TextView;

import android.widget.AdapterView.OnItemClickListener;

import android.widget.LinearLayout.LayoutParams;

public class TabMenu extends PopupWindow{

private GridView gvBody, gvTitle;

private LinearLayout mLayout;

private MenuTitleAdapter titleAdapter;

public TabMenu(Context context,OnItemClickListener titleClick,OnItemClickListener bodyClick,

MenuTitleAdapter titleAdapter,`intcolorBgTabMenu,intaniTabMenu){`

super`(context);`

mLayout = new LinearLayout(context);

mLayout.setOrientation(LinearLayout.VERTICAL);

//标题选项栏

gvTitle = new GridView(context);

gvTitle.setLayoutParams(`newLayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));`

gvTitle.setNumColumns(titleAdapter.getCount());

gvTitle.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);

gvTitle.setVerticalSpacing(`1);`

gvTitle.setHorizontalSpacing(`1);`

gvTitle.setGravity(Gravity.CENTER);

gvTitle.setOnItemClickListener(titleClick);

gvTitle.setAdapter(titleAdapter);

gvTitle.setSelector(`newColorDrawable(Color.TRANSPARENT));//选中的时候为透明色`

this`.titleAdapter=titleAdapter;`

//子选项栏

gvBody = new GridView(context);

gvBody.setLayoutParams(`newLayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));`

gvBody.setSelector(`newColorDrawable(Color.TRANSPARENT));//选中的时候为透明色`

gvBody.setNumColumns(`4);`

gvBody.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);

gvBody.setVerticalSpacing(`10);`

gvBody.setHorizontalSpacing(`10);`

gvBody.setPadding(`10,` `10,10,` `10);`

gvBody.setGravity(Gravity.CENTER);

gvBody.setOnItemClickListener(bodyClick);

mLayout.addView(gvTitle);

mLayout.addView(gvBody);

//设置默认项

this`.setContentView(mLayout);`

this`.setWidth(LayoutParams.FILL_PARENT);`

this`.setHeight(LayoutParams.WRAP_CONTENT);`

this`.setBackgroundDrawable(new` `ColorDrawable(colorBgTabMenu));// 设置TabMenu菜单背景`

this`.setAnimationStyle(aniTabMenu);`

this`.setFocusable(true);// menu菜单获得焦点 如果没有获得焦点menu菜单中的控件事件无法响应`

}

public void SetTitleSelect(`intindex)`

{

gvTitle.setSelection(index);

this`.titleAdapter.SetFocus(index);`

}

public void SetBodySelect(`intindex,intcolorSelBody)`

{

int count=gvBody.getChildCount();

for`(int` `i=0;i<count;i++)`

{

if`(i!=index)`

((LinearLayout)gvBody.getChildAt(i)).setBackgroundColor(Color.TRANSPARENT);

}

((LinearLayout)gvBody.getChildAt(index)).setBackgroundColor(colorSelBody);

}

public void SetBodyAdapter(MenuBodyAdapter bodyAdapter)

{

gvBody.setAdapter(bodyAdapter);

}

/**

* 自定义Adapter,TabMenu的每个分页的主体

*

*/

static public class MenuBodyAdapter extends BaseAdapter {

private Context mContext;

private int fontColor,fontSize;

private String[] texts;

private int`[] resID;`

/**

* 设置TabMenu的分页主体

* @param context 调用方的上下文

* @param texts 按钮集合的字符串数组

* @param resID 按钮集合的图标资源数组

* @param fontSize 按钮字体大小

* @param color 按钮字体颜色

*/

public MenuBodyAdapter(Context context, String[] texts,`int[] resID,` `int` `fontSize,intfontColor)`

{

this`.mContext = context;`

this`.fontColor = fontColor;`

this`.texts = texts;`

this`.fontSize=fontSize;`

this`.resID=resID;`

}

public int getCount() {

return texts.length;

}

public Object getItem(`intposition) {`

return makeMenyBody(position);

}

public long getItemId(`intposition) {`

return position;

}

private LinearLayout makeMenyBody(`intposition)`

{

LinearLayout result=`newLinearLayout(this.mContext);`

result.setOrientation(LinearLayout.VERTICAL);

result.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL);

result.setPadding(`10,` `10,10,` `10);`

TextView text = new TextView(`this.mContext);`

text.setText(texts[position]);

text.setTextSize(fontSize);

text.setTextColor(fontColor);

text.setGravity(Gravity.CENTER);

text.setPadding(`5,` `5,5,` `5);`

ImageView img=`newImageView(this.mContext);`

img.setBackgroundResource(resID[position]);

result.addView(img,`newLinearLayout.LayoutParams(newLayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)));`

result.addView(text);

return result;

}

public View getView(`intposition, View convertView, ViewGroup parent) {`

return makeMenyBody(position);

}

}

/**

* 自定义Adapter,TabMenu的分页标签部分

*

*/

static public class MenuTitleAdapter extends BaseAdapter {

private Context mContext;

private int fontColor,unselcolor,selcolor;

private TextView[] title;

/**

* 设置TabMenu的title

* @param context 调用方的上下文

* @param titles 分页标签的字符串数组

* @param fontSize 字体大小

* @param fontcolor 字体颜色

* @param unselcolor 未选中项的背景色

* @param selcolor 选中项的背景色

*/

public MenuTitleAdapter(Context context, String[] titles, int fontSize,

int fontcolor,`intunselcolor,intselcolor) {`

this`.mContext = context;`

this`.fontColor = fontcolor;`

this`.unselcolor = unselcolor;`

this`.selcolor=selcolor;`

this`.title =newTextView[titles.length];`

for (`inti =0; i < titles.length; i++) {`

title[i] = new TextView(mContext);

title[i].setText(titles[i]);

title[i].setTextSize(fontSize);

title[i].setTextColor(fontColor);

title[i].setGravity(Gravity.CENTER);

title[i].setPadding(`10,` `10,10,` `10);`

}

}

public int getCount() {

return title.length;

}

public Object getItem(`intposition) {`

return title[position];

}

public long getItemId(`intposition) {`

return title[position].getId();

}

/**

* 设置选中的效果

*/

private void SetFocus(`intindex)`

{

for`(int` `i=0;i<title.length;i++)`

{

if`(i!=index)`

{

title[i].setBackgroundDrawable(`newColorDrawable(unselcolor));//设置没选中的颜色`

title[i].setTextColor(fontColor);`//设置没选中项的字体颜色`

}

}

title[index].setBackgroundColor(`0x00);//设置选中项的颜色`

title[index].setTextColor(selcolor);`//设置选中项的字体颜色`

}

public View getView(`intposition, View convertView, ViewGroup parent) {`

View v;

if (convertView == null`) {`

v = title[position];

} else {

v = convertView;

}

return v;

}

}

}

testTabMenu介绍了数据的定义以及TabMenu的使用,源码如下:

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

package com.testTabMenu;

import android.app.Activity;

import android.graphics.Color;

import android.os.Bundle;

import android.view.Gravity;

import android.view.Menu;

import android.view.View;

import android.widget.AdapterView;

import android.widget.AdapterView.OnItemClickListener;

import android.widget.Toast;

public class testTabMenu extends Activity {

TabMenu.MenuBodyAdapter []bodyAdapter=`newTabMenu.MenuBodyAdapter[3];`

TabMenu.MenuTitleAdapter titleAdapter;

TabMenu tabMenu;

int selTitle=`0;`

@Override

public void onCreate(Bundle savedInstanceState) {

super`.onCreate(savedInstanceState);`

setContentView(R.layout.main);

//设置分页栏的标题

titleAdapter = new TabMenu.MenuTitleAdapter(`this,` `new` `String[] {` `"常用",`

"设置"`,“工具”},16,` `0xFF222222,Color.LTGRAY,Color.WHITE);`

//定义每项分页栏的内容

bodyAdapter[`0]=newTabMenu.MenuBodyAdapter(this,new` `String[] {` `"常用1",“常用2”, },`

new int`[] { R.drawable.menu_test,`

R.drawable.menu_bookmark},`13,` `0xFFFFFFFF);`

bodyAdapter[`1]=newTabMenu.MenuBodyAdapter(this,new` `String[] {` `"设置1",“设置2”,`

"设置3"`},newint[] { R.drawable.menu_edit,`

R.drawable.menu_delete, R.drawable.menu_fullscreen},`13,` `0xFFFFFFFF);`

bodyAdapter[`2]=newTabMenu.MenuBodyAdapter(this,new` `String[] {` `"工具1",“工具2”,`

"工具3"`,“工具4”},newint[] { R.drawable.menu_copy,`

R.drawable.menu_cut, R.drawable.menu_normalmode,

R.drawable.menu_quit },`13,` `0xFFFFFFFF);`

tabMenu=`newTabMenu(this,`

new TitleClickEvent(),

new BodyClickEvent(),

titleAdapter,

0x55123456`,//TabMenu的背景颜色`

R.style.PopupAnimation);`//出现与消失的动画`

tabMenu.update();

tabMenu.SetTitleSelect(`0);`

tabMenu.SetBodyAdapter(bodyAdapter[`0]);`

}

class TitleClickEvent implements OnItemClickListener{

@Override

public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,

long arg3) {

selTitle=arg2;

tabMenu.SetTitleSelect(arg2);

tabMenu.SetBodyAdapter(bodyAdapter[arg2]);

}

}

class BodyClickEvent implements OnItemClickListener{

@Override

public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,

long arg3) {

tabMenu.SetBodySelect(arg2,Color.GRAY);

String str=`“第”+String.valueOf(selTitle)+“栏/n/r”`

+`“第”+String.valueOf(arg2)+“项”;`

Toast.makeText(testTabMenu.`this, str,` `500).show();`

}

}

@Override

/**

* 创建MENU

*/

public boolean onCreateOptionsMenu(Menu menu) {

menu.add(`“menu”);// 必须创建一项`

return super`.onCreateOptionsMenu(menu);`

}

@Override

/**

* 拦截MENU

*/

public boolean onMenuOpened(`intfeatureId, Menu menu) {`

if (tabMenu != null`) {`

if (tabMenu.isShowing())

tabMenu.dismiss();

else {

tabMenu.showAtLocation(findViewById(R.id.LinearLayout01),

Gravity.BOTTOM, 0`,0);`

}

}

return false`;// 返回为true 则显示系统menu`

}

}

这样,我们就基本实现了Android自定义Menu菜单的功能,谢谢阅读!