漢堡菜單,其實就是三條橫杠,Google Material Design中一般用來做側(cè)邊欄開關(guān),微軟的UWP也是同樣的做法。
成都創(chuàng)新互聯(lián)一直通過網(wǎng)站建設(shè)和網(wǎng)站營銷幫助企業(yè)獲得更多客戶資源。 以"深度挖掘,量身打造,注重實效"的一站式服務(wù),以成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、移動互聯(lián)產(chǎn)品、網(wǎng)絡(luò)營銷推廣服務(wù)為核心業(yè)務(wù)。十年網(wǎng)站制作的經(jīng)驗,使用新網(wǎng)站建設(shè)技術(shù),全新開發(fā)出的標(biāo)準(zhǔn)網(wǎng)站,不但價格便宜而且實用、靈活,特別適合中小公司網(wǎng)站制作。網(wǎng)站管理系統(tǒng)簡單易用,維護方便,您可以完全操作網(wǎng)站資料,是中小公司快速網(wǎng)站建設(shè)的選擇。
將畫布中心移動到控件中心,先繪制中間那一條橫線,再計算上面和下面的橫線的位置,如果不計算,也可以使用Canvas.translate(),移動2次畫布中心去畫。
一共兩種實現(xiàn)方式:
方式一:java代碼實現(xiàn)
@Override
public boolean onCreateOptionsMenu(Menu menu) {
/**
* 參數(shù)1:組的id
* 參數(shù)2:菜單的id
* 參數(shù)3:排列的順序
* 參數(shù)4:顯示菜單的文本
*/
menu.add(0, 0, 0, "你好");
menu.add(1, 1, 1, "不好");
return super.onCreateOptionsMenu(menu);
}
/**菜單的點擊事件*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case 0:
Toast.makeText(this, "你選擇你好", Toast.LENGTH_LONG).show();
break;
case 1:
Toast.makeText(this, "你選擇不好", Toast.LENGTH_LONG).show();
break;
}
}
方式二:xml形式的菜單
步驟一:在res/menu目錄下新建xml文件
menu xmlns:android=""
xmlns:tools=""
tools:context="com.lifei.menu.MainActivity"
item
android:id="@+id/delete_menu_item"
android:orderInCategory="20"
android:title="@string/deletemunu"/
item
android:id="@+id/add_menu_item"
android:orderInCategory="19"
android:title="@string/addmunu"
menu
item
android:id="@+id/add_user_item"
android:orderInCategory="30"
android:title="@string/adduser"/
item
android:id="@+id/add_phone_item"
android:orderInCategory="31"
android:showAsAction="never"
android:title="@string/addhpone"/
/menu
/item
/menu
步驟二:在activity中
@Override
public boolean onCreateOptionsMenu(Menu menu) {
/**xml形式的menu菜單*/
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
點擊事件與方式一是一樣的
? Android左側(cè)推出導(dǎo)航菜單可以讓Activity繼承PopupWindow類來實現(xiàn)的彈出窗體,布局可以根據(jù)自己定義設(shè)計。彈出效果主要使用了translate和alpha樣式實現(xiàn)。具體的做法是下列代碼:
第一步:設(shè)計彈出窗口xml:
Xml代碼??
?xml?version="1.0"?encoding="utf-8"???
RelativeLayout???
xmlns:android=""??
android:layout_width="fill_parent"??
android:layout_height="wrap_content"??
android:gravity="center_horizontal"??
android:orientation="vertical"??
LinearLayout???
android:id="@+id/pop_layout"??
android:layout_width="fill_parent"??
android:layout_height="wrap_content"??
android:gravity="center_horizontal"??
android:orientation="vertical"??
android:layout_alignParentBottom="true"??
android:background="@drawable/btn_style_alert_dialog_background"??
Button??
android:id="@+id/btn_take_photo"??
android:layout_marginLeft="20dip"??
android:layout_marginRight="20dip"??
android:layout_marginTop="20dip"??
android:layout_width="fill_parent"??
android:layout_height="wrap_content"??
android:text="拍照"??
android:background="@drawable/btn_style_alert_dialog_button"??
android:textStyle="bold"??
/??
Button??
android:id="@+id/btn_pick_photo"??
android:layout_marginLeft="20dip"??
android:layout_marginRight="20dip"??
android:layout_marginTop="5dip"???
android:layout_width="fill_parent"??
android:layout_height="wrap_content"??
android:text="從相冊選擇"??
android:background="@drawable/btn_style_alert_dialog_button"??
android:textStyle="bold"??
/??
Button??
android:id="@+id/btn_cancel"??
android:layout_marginLeft="20dip"??
android:layout_marginRight="20dip"??
android:layout_marginTop="15dip"???
android:layout_marginBottom="15dip"??
android:layout_width="fill_parent"??
android:layout_height="wrap_content"??
android:text="取消"??
android:background="@drawable/btn_style_alert_dialog_cancel"??
android:textColor="#ffffff"??
android:textStyle="bold"??
/??
/LinearLayout??
/RelativeLayout??
第二步:創(chuàng)建SelectPicPopupWindow類繼承PopupWindow:
Java代碼??
import?android.app.Activity;??
import?android.content.Context;??
import?android.graphics.drawable.ColorDrawable;??
import?android.view.LayoutInflater;??
import?android.view.MotionEvent;??
import?android.view.View;??
import?android.view.View.OnClickListener;??
import?android.view.View.OnTouchListener;??
import?android.view.ViewGroup.LayoutParams;??
import?android.widget.Button;??
import?android.widget.PopupWindow;??
public?class?SelectPicPopupWindow?extends?PopupWindow?{??
private?Button?btn_take_photo,?btn_pick_photo,?btn_cancel;??
private?View?mMenuView;??
public?SelectPicPopupWindow(Activity?context,OnClickListener?itemsOnClick)?{??
super(context);??
LayoutInflater?inflater?=?(LayoutInflater)?context??
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);??
mMenuView?=?inflater.inflate(R.layout.alert_dialog,?null);??
btn_take_photo?=?(Button)?mMenuView.findViewById(R.id.btn_take_photo);??
btn_pick_photo?=?(Button)?mMenuView.findViewById(R.id.btn_pick_photo);??
btn_cancel?=?(Button)?mMenuView.findViewById(R.id.btn_cancel);??
//取消按鈕??
btn_cancel.setOnClickListener(new?OnClickListener()?{??
public?void?onClick(View?v)?{??
//銷毀彈出框??
dismiss();??
}??
});??
//設(shè)置按鈕監(jiān)聽??
btn_pick_photo.setOnClickListener(itemsOnClick);??
btn_take_photo.setOnClickListener(itemsOnClick);??
//設(shè)置SelectPicPopupWindow的View??
this.setContentView(mMenuView);??
//設(shè)置SelectPicPopupWindow彈出窗體的寬??
this.setWidth(LayoutParams.FILL_PARENT);??
//設(shè)置SelectPicPopupWindow彈出窗體的高??
this.setHeight(LayoutParams.WRAP_CONTENT);??
//設(shè)置SelectPicPopupWindow彈出窗體可點擊??
this.setFocusable(true);??
//設(shè)置SelectPicPopupWindow彈出窗體動畫效果??
this.setAnimationStyle(R.style.AnimBottom);??
//實例化一個ColorDrawable顏色為半透明??
ColorDrawable?dw?=?new?ColorDrawable(0xb0000000);??
//設(shè)置SelectPicPopupWindow彈出窗體的背景??
this.setBackgroundDrawable(dw);??
//mMenuView添加OnTouchListener監(jiān)聽判斷獲取觸屏位置如果在選擇框外面則銷毀彈出框??
mMenuView.setOnTouchListener(new?OnTouchListener()?{??
public?boolean?onTouch(View?v,?MotionEvent?event)?{??
int?height?=?mMenuView.findViewById(R.id.pop_layout).getTop();??
int?y=(int)?event.getY();??
if(event.getAction()==MotionEvent.ACTION_UP){??
if(yheight){??
dismiss();??
}??
}?????????????????
return?true;??
}??
});??
}??
}??
第三步:編寫MainActivity類實現(xiàn)測試:
Java代碼??
import?android.app.Activity;??
import?android.os.Bundle;??
import?android.view.Gravity;??
import?android.view.View;??
import?android.view.View.OnClickListener;??
import?android.widget.TextView;??
public?class?MainActivity?extends?Activity?{??
//自定義的彈出框類??
SelectPicPopupWindow?menuWindow;??
@Override??
public?void?onCreate(Bundle?savedInstanceState)?{??
super.onCreate(savedInstanceState);??
setContentView(R.layout.activity_main);??
TextView?tv?=?(TextView)?this.findViewById(R.id.text);??
//把文字控件添加監(jiān)聽,點擊彈出自定義窗口??
tv.setOnClickListener(new?OnClickListener()?{?????????????
public?void?onClick(View?v)?{??
//實例化SelectPicPopupWindow??
menuWindow?=?new?SelectPicPopupWindow(MainActivity.this,?itemsOnClick);??
//顯示窗口??
menuWindow.showAtLocation(MainActivity.this.findViewById(R.id.main),?Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL,?0,?0);?//設(shè)置layout在PopupWindow中顯示的位置??
}??
});??
}??
//為彈出窗口實現(xiàn)監(jiān)聽類??
private?OnClickListener??itemsOnClick?=?new?OnClickListener(){??
public?void?onClick(View?v)?{??
menuWindow.dismiss();??
switch?(v.getId())?{??
case?R.id.btn_take_photo:??
break;??
case?R.id.btn_pick_photo:?????????????????
break;??
default:??
break;??
}??
}??
};??
}
? 上述的代碼實現(xiàn)了從底部彈出,也可以根據(jù)PopupWindow類設(shè)置從左下部彈出。
Android的對話框有兩種:PopupWindow和AlertDialog。它們的不同點在于:
AlertDialog的位置固定,而PopupWindow的位置可以隨意
AlertDialog是非阻塞線程的,而PopupWindow是阻塞線程的
PopupWindow的位置按照有無偏移分,可以分為偏移和無偏移兩種;按照參照物的不同,可以分為相對于某個控件(Anchor錨)和相對于父控件。具體如下
showAsDropDown(View anchor):相對某個控件的位置(正左下方),無偏移
showAsDropDown(View anchor, int xoff, int yoff):相對某個控件的位置,有偏移
showAtLocation(View parent, int gravity, int x, int y):相對于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以設(shè)置偏移或無偏移
點擊button彈出對話框菜單
import?android.app.Activity;
import?android.app.AlertDialog;
import?android.content.DialogInterface;
import?android.os.Bundle;
import?android.view.View;
import?android.view.View.OnClickListener;
import?android.widget.Button;
publicclass?choice?extends?Activity?{
private?Button?button;
/**?Called?when?the?activity?is?first?created.?*/
@Override
publicvoid?onCreate(Bundle?savedInstanceState)?{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button=(Button)findViewById(R.id.button1);
button.setOnClickListener(new?OnClickListener(){
@Override
publicvoid?onClick(View?arg0)?{
new?AlertDialog.Builder(choice.this)
.setTitle("choice")
.setItems(R.array.str_body,?new?DialogInterface.OnClickListener()?{
@Override
publicvoid?onClick(DialogInterface?arg0,?int?arg1)?{
//?TODO?Auto-generated?method?stub
String[]?aryshop=getResources().getStringArray(R.array.str_body);
new?AlertDialog.Builder(choice.this)
.setMessage(aryshop[arg1])
.setNegativeButton("ok",?new?DialogInterface.OnClickListener()?{
@Override
publicvoid?onClick(DialogInterface?arg0,?int?arg1)?{
//?TODO?Auto-generated?method?stub
}
}).show();
}
}).show();
//?TODO?Auto-generated?method?stub
}});
}
}
菜單項
?xmlversion="1.0"encoding="utf-8"?
resources
stringname="hello"Hello?World,?choice!/string
stringname="app_name"ChoiceMenu/string
stringname="strtitle"按我選擇:/string
stringname="str"你選擇的是:/string
arrayname="str_body"
item選項1/item
item選項2/item
item選項3/item
item選項4/item
item選項5/item
item選項6/item
/array
/resources
1、通用模式
上圖是圖片加文字,如果我想換成按鈕呢,或者我只需要圖片。這里就需要定制。怎么辦呢,我采用了適配模式,大家都還記得 ListView的用法,我這里也借鑒了一下:
public void setAdapter(ListAdapter mAdapter) { ? ? ? ?this.mAdapter = mAdapter;
}123
這樣就可以實現(xiàn)Menu的高度定制。
2、構(gòu)建菜單項
代碼參考buildMenuItems(),對mAdapter遍歷獲取子View,添加點擊事件,調(diào)用addView()添加到ViewGroup,這個時候系統(tǒng)就會調(diào)用onMeasure()對子View計算大小。
3、計算item大小
代碼參考measureMyself()和measureChildViews(),確定每個item的尺寸大小。
4、item布局
首先計算item(x,y)距離圓心的長度,我畫了一個草圖:
int x = (int) Math.round(Math.sin(Math.toRadians(a)) * temp); int y = (int) Math.round(Math.cos(Math.toRadians(a)) * temp);12
temp我賦值為半徑的三分之二,當(dāng)然你可以更改成你滿意的長度。
然后要計算(x,y)的坐標(biāo),通過坐標(biāo)項象來計算:
if (x = 0 y = 0) { ?//第二項象
x = mRadius - Math.abs(x);
y = mRadius - y;
} else if (x = 0 y = 0) {//第三項象
y = mRadius + Math.abs(y);
x = mRadius - Math.abs(x);
} else if (x = 0 y = 0) {//第四項象
y = mRadius + Math.abs(y);
x = mRadius + x;
} else if (x = 0 y = 0) {//第一項象
x = mRadius + x;
y = mRadius - Math.abs(y);
}12345678910111213
計算到這來,你可能已經(jīng)發(fā)現(xiàn)了問題,如果用(x,y)坐標(biāo)來表示菜單項的left 和 top位置,那么你會發(fā)現(xiàn)整個item相對于父控件是向右下偏移了。為了解決偏移問題,我采用了item控件的中心點來表示菜單項的left 和 top位置。
x = x - item的寬度/ 2;
y = y - item的高度 / 2;12
最后調(diào)用layout()方法,確定item的位置。
5、手勢旋轉(zhuǎn)
上面已經(jīng)完成了靜態(tài)的Menu,那么怎么才能通過滑動陰影部分使Menu旋轉(zhuǎn)起來呢?
需要重寫onTouchEvent()方法,并把返回值改為true。處理手勢按下(ACTION_DOWN),抬起(ACTION_UP)的狀態(tài)。
首先我們要判斷手指按下是否在陰影局域內(nèi)。注意手指按下是指尖局域與屏幕接觸,并不是一點,所以有誤差。
x = event.getX();
y = event.getY();if ((x - 圓心x) * (x - 圓心x) + (y - 圓心y) * (y - 圓心y) (圓心x+ 誤差) * (圓心y+ 誤差)) {
isRange = true;
}12345
然后我們要計算運動的速度,我剛開始的想法是用重力加速度,非常感謝我同事小賈,他給了我更好的意見:速度=距離/時間。
ACTION_DOWN:
lastTouchTime = System.currentTimeMillis();1
ACTION_UP:
long timeStamp = System.currentTimeMillis() - lastTouchTime;float distance = (float) Math.sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)); float speed = distance / timeStamp;123
然后我們通過對比手指按下的x的坐標(biāo),和抬起x的坐標(biāo),來判斷用戶是向左滑,還是右滑。
if (x1 - x 0) {
isLeft = false;
} else {
isLeft = true;
}12345
最后通過handler來改變每次運動的角度,使Menu很自然的旋轉(zhuǎn)了起來:
if (isLeft) { ? ? ? ? ? ? ? ? ? ? ? ?//向左轉(zhuǎn)動
offsetRotation -= ANGLE;
} else { ? ? ? ? ? ? ? ? ? ? ? ?//向右轉(zhuǎn)動
offsetRotation += ANGLE;
} ? ? ? ? ? ? ? ? ? ?//速度衰減
speed -= SPEED_ATTENUATION;
invalidate();//重繪
handler.sendEmptyMessageDelayed(EMPTY_MESSAGE, 50);1234567891011
使用
1、xml布局
com.github.ws.viewdemo.widget.CircleMenuLayout
android:id="@+id/cm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f0f0f0"
/com.github.ws.viewdemo.widget.CircleMenuLayout1234567
2、class文件
circleMenuLayout.setAdapter(new MyAdapter());
circleMenuLayout.setOnItemClickListener(new CircleMenuLayout.OnItemClickListener() {
@Override ? ? ? ? ? ?public void onItemClickListener(View v, int position) {
Toast.makeText(MainActivity.this, mList.get(position).text + "", Toast.LENGTH_SHORT).show();
}
});12345678
源碼我已上傳到github,地址,再一次感謝大家的關(guān)注。
android 中讓菜單menu顯示在左上角,可以使用popupwindow技術(shù),也就是懸浮菜單,設(shè)置默認(rèn)的位置為左上角,如下代碼:
package?com.example.menutype;
import?android.app.ActionBar.LayoutParams;
import?android.app.Activity;
import?android.content.Context;
import?android.os.Bundle;
import?android.view.Gravity;
import?android.view.LayoutInflater;
import?android.view.Menu;
import?android.view.MenuItem;
import?android.view.View;
import?android.view.View.OnClickListener;
import?android.widget.Button;
import?android.widget.PopupWindow;
import?android.widget.PopupWindow.OnDismissListener;
import?android.widget.TextView;
import?android.widget.Toast;
/**
*?
*?@author?tr
*?@time?2014-3-10
*?@description?自定義菜單,下拉菜單樣式,添加動畫效果,重寫onMenuOpened()方法,自定義"menu"按鍵彈出菜單
*/
public?class?MainActivity?extends?Activity?implements?OnClickListener{
private?static?Toast?mToast;
private?static?Context?mContext;
private?PopupWindow?popupWindow?;
private?Button?btn_popupwindow;
private?View?mPopupWindowView;
@Override
protected?void?onCreate(Bundle?savedInstanceState)?{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext?=?this;
btn_popupwindow?=?(Button)?findViewById(R.id.btn_popupwindow);
btn_popupwindow.setOnClickListener(this);
initPopupWindow();
}
@Override
public?boolean?onCreateOptionsMenu(Menu?menu)?{
/**actionBar上更多按鈕*/
getMenuInflater().inflate(R.menu.main,?menu);
/**點擊menu,彈出菜單*/
/*
*?
*?add()方法的四個參數(shù),依次是:
*?
*?1、組別,如果不分組的話就寫Menu.NONE,
*?
*?2、Id,這個很重要,Android根據(jù)這個Id來確定不同的菜單
*?
*?3、順序,那個菜單現(xiàn)在在前面由這個參數(shù)的大小決定
*?
*?4、文本,菜單的顯示文本
*/
menu.add(Menu.NONE,?Menu.FIRST?+?1,?1,?getResource(R.string.edit_text)).setIcon(
R.drawable.ic_edit);
//?setIcon()方法為菜單設(shè)置圖標(biāo),這里使用的是系統(tǒng)自帶的圖標(biāo),同學(xué)們留意一下,以
//?android.R開頭的資源是系統(tǒng)提供的,我們自己提供的資源是以R開頭的
menu.add(Menu.NONE,?Menu.FIRST?+?2,?2,?getResource(R.string.file)).setIcon(
R.drawable.ic_menu_file);
menu.add(Menu.NONE,?Menu.FIRST?+?3,?3,?getResource(R.string.about)).setIcon(
R.drawable.ic_menu_about);
return?true;
}
/**菜單打開時調(diào)用*/
@Override
public?boolean?onMenuOpened(int?featureId,?Menu?menu)?{
//?TODO?Auto-generated?method?stub
showToast("menu菜單打開:"+featureId);
//點擊"menu"按鈕打開
if(featureId?==?0){
showPopupWindow();
}
return?super.onMenuOpened(featureId,?menu);//?返回為true?則顯示系統(tǒng)menu
// return?false;
}
/**menu菜單關(guān)閉時調(diào)用*/
@Override
public?void?onOptionsMenuClosed(Menu?menu)?{
//?TODO?Auto-generated?method?stub
super.onOptionsMenuClosed(menu);
showToast("menu菜單關(guān)閉");
}
@Override
public?boolean?onOptionsItemSelected(MenuItem?item)?{
//?TODO?Auto-generated?method?stub
switch(item.getItemId()){
case?Menu.FIRST?+?1:
case?R.id.action_edit:
showToast(getResource(R.string.edit_text));
break;
case?Menu.FIRST?+?2:
case?R.id.action_file:
showToast(getResource(R.string.file));
break;
case?R.id.action_favorite:
showToast(getResource(R.string.favorite));
break;
case?R.id.action_share:
showToast(getResource(R.string.share));
break;
case?Menu.FIRST?+?3:
case?R.id.action_about:
showToast(getResource(R.string.about));
break;
}
return?super.onOptionsItemSelected(item);
}
@Override
public?void?onClick(View?v)?{
switch(v.getId()){
case?R.id.btn_popupwindow:
showPopupWindow();
break;
case?R.id.textview_about:
showToast(getResource(R.string.about));
popupWindow.dismiss();
break;
case?R.id.textview_edit:
showToast(getResource(R.string.edit_text));
popupWindow.dismiss();
break;
case?R.id.textview_file:
showToast(getResource(R.string.file));
popupWindow.dismiss();
break;
}
}
/**顯示popupwindow*/
private?void?showPopupWindow(){
if(!popupWindow.isShowing()){
popupWindow.showAsDropDown(btn_popupwindow,?btn_popupwindow.getLayoutParams().width/2,?0);
}else{
popupWindow.dismiss();
}
}
/**
*?初始化popupwindow
*/
private?void?initPopupWindow(){
initPopupWindowView();
//初始化popupwindow,綁定顯示view,設(shè)置該view的寬度/高度
popupWindow?=?new?PopupWindow(mPopupWindowView,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
popupWindow.setFocusable(true);
popupWindow.setOutsideTouchable(true);
//?這個是為了點擊“返回Back”也能使其消失,并且并不會影響你的背景;使用該方法點擊窗體之外,才可關(guān)閉窗體
popupWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.bitmap_book_read_chapterlist_repeat));
//Background不能設(shè)置為null,dismiss會失效
// popupWindow.setBackgroundDrawable(null);
//設(shè)置漸入、漸出動畫效果
// popupWindow.setAnimationStyle(R.style.popupwindow);
popupWindow.update();
//popupWindow調(diào)用dismiss時觸發(fā),設(shè)置了setOutsideTouchable(true),點擊view之外/按鍵back的地方也會觸發(fā)
popupWindow.setOnDismissListener(new?OnDismissListener()?{
@Override
public?void?onDismiss()?{
//?TODO?Auto-generated?method?stub
// showToast("關(guān)閉popupwindow");
}
});
}