扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
汉堡菜单,其实就是三条横杠,Google Material Design中一般用来做侧边栏开关,微软的UWP也是同样的做法。
成都创新互联一直通过网站建设和网站营销帮助企业获得更多客户资源。 以"深度挖掘,量身打造,注重实效"的一站式服务,以成都网站制作、成都网站建设、移动互联产品、网络营销推广服务为核心业务。十年网站制作的经验,使用新网站建设技术,全新开发出的标准网站,不但价格便宜而且实用、灵活,特别适合中小公司网站制作。网站管理系统简单易用,维护方便,您可以完全操作网站资料,是中小公司快速网站建设的选择。
将画布中心移动到控件中心,先绘制中间那一条横线,再计算上面和下面的横线的位置,如果不计算,也可以使用Canvas.translate(),移动2次画布中心去画。
一共两种实现方式:
方式一:java代码实现
@Override
public boolean onCreateOptionsMenu(Menu menu) {
/**
* 参数1:组的id
* 参数2:菜单的id
* 参数3:排列的顺序
* 参数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左侧推出导航菜单可以让Activity继承PopupWindow类来实现的弹出窗体,布局可以根据自己定义设计。弹出效果主要使用了translate和alpha样式实现。具体的做法是下列代码:
第一步:设计弹出窗口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
第二步:创建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();
}
});
//设置按钮监听
btn_pick_photo.setOnClickListener(itemsOnClick);
btn_take_photo.setOnClickListener(itemsOnClick);
//设置SelectPicPopupWindow的View
this.setContentView(mMenuView);
//设置SelectPicPopupWindow弹出窗体的宽
this.setWidth(LayoutParams.FILL_PARENT);
//设置SelectPicPopupWindow弹出窗体的高
this.setHeight(LayoutParams.WRAP_CONTENT);
//设置SelectPicPopupWindow弹出窗体可点击
this.setFocusable(true);
//设置SelectPicPopupWindow弹出窗体动画效果
this.setAnimationStyle(R.style.AnimBottom);
//实例化一个ColorDrawable颜色为半透明
ColorDrawable dw = new ColorDrawable(0xb0000000);
//设置SelectPicPopupWindow弹出窗体的背景
this.setBackgroundDrawable(dw);
//mMenuView添加OnTouchListener监听判断获取触屏位置如果在选择框外面则销毁弹出框
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类实现测试:
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);
//把文字控件添加监听,点击弹出自定义窗口
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); //设置layout在PopupWindow中显示的位置
}
});
}
//为弹出窗口实现监听类
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;
}
}
};
}
上述的代码实现了从底部弹出,也可以根据PopupWindow类设置从左下部弹出。
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等),可以设置偏移或无偏移
点击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
这样就可以实现Menu的高度定制。
2、构建菜单项
代码参考buildMenuItems(),对mAdapter遍历获取子View,添加点击事件,调用addView()添加到ViewGroup,这个时候系统就会调用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我赋值为半径的三分之二,当然你可以更改成你满意的长度。
然后要计算(x,y)的坐标,通过坐标项象来计算:
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
计算到这来,你可能已经发现了问题,如果用(x,y)坐标来表示菜单项的left 和 top位置,那么你会发现整个item相对于父控件是向右下偏移了。为了解决偏移问题,我采用了item控件的中心点来表示菜单项的left 和 top位置。
x = x - item的宽度/ 2;
y = y - item的高度 / 2;12
最后调用layout()方法,确定item的位置。
5、手势旋转
上面已经完成了静态的Menu,那么怎么才能通过滑动阴影部分使Menu旋转起来呢?
需要重写onTouchEvent()方法,并把返回值改为true。处理手势按下(ACTION_DOWN),抬起(ACTION_UP)的状态。
首先我们要判断手指按下是否在阴影局域内。注意手指按下是指尖局域与屏幕接触,并不是一点,所以有误差。
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的坐标,和抬起x的坐标,来判断用户是向左滑,还是右滑。
if (x1 - x 0) {
isLeft = false;
} else {
isLeft = true;
}12345
最后通过handler来改变每次运动的角度,使Menu很自然的旋转了起来:
if (isLeft) { //向左转动
offsetRotation -= ANGLE;
} else { //向右转动
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,地址,再一次感谢大家的关注。
android 中让菜单menu显示在左上角,可以使用popupwindow技术,也就是悬浮菜单,设置默认的位置为左上角,如下代码:
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()方法的四个参数,依次是:
*
* 1、组别,如果不分组的话就写Menu.NONE,
*
* 2、Id,这个很重要,Android根据这个Id来确定不同的菜单
*
* 3、顺序,那个菜单现在在前面由这个参数的大小决定
*
* 4、文本,菜单的显示文本
*/
menu.add(Menu.NONE, Menu.FIRST + 1, 1, getResource(R.string.edit_text)).setIcon(
R.drawable.ic_edit);
// setIcon()方法为菜单设置图标,这里使用的是系统自带的图标,同学们留意一下,以
// android.R开头的资源是系统提供的,我们自己提供的资源是以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;
}
/**菜单打开时调用*/
@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 则显示系统menu
// return false;
}
/**menu菜单关闭时调用*/
@Override
public void onOptionsMenuClosed(Menu menu) {
// TODO Auto-generated method stub
super.onOptionsMenuClosed(menu);
showToast("menu菜单关闭");
}
@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,设置该view的宽度/高度
popupWindow = new PopupWindow(mPopupWindowView,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
popupWindow.setFocusable(true);
popupWindow.setOutsideTouchable(true);
// 这个是为了点击“返回Back”也能使其消失,并且并不会影响你的背景;使用该方法点击窗体之外,才可关闭窗体
popupWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.bitmap_book_read_chapterlist_repeat));
//Background不能设置为null,dismiss会失效
// popupWindow.setBackgroundDrawable(null);
//设置渐入、渐出动画效果
// popupWindow.setAnimationStyle(R.style.popupwindow);
popupWindow.update();
//popupWindow调用dismiss时触发,设置了setOutsideTouchable(true),点击view之外/按键back的地方也会触发
popupWindow.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss() {
// TODO Auto-generated method stub
// showToast("关闭popupwindow");
}
});
}
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流