微信6.0的ActionBar比较简洁只有一个搜索框和一个溢出(overflow)菜单。这个溢出菜单可以看到不是默认的,而是一个“+”号图标。
并且溢出菜单中点击,里面的隐藏菜单图标可以显示出来。(系统默认是不显示的)
文章主要分三部分:
一.主要介绍:如何高仿微信6.0ActionBar;
1.溢出菜单不显示
2.自定义溢出菜单的图标样式
3.隐藏图标的显示。
二.取巧的方法;
三.用PopupWindow实现自定义溢出(overflow)菜单;
一.如何高仿微信6.0ActionBar
错误提示:第一次做时,犯了个错误,就是当我们创建MainActivity时,要让它去继承FragmentActivity,否则ActionBar就会出现异常情况!!!
1.在模拟器中,大家可以发现overflow是显示不出来的,我们可以通过反射的原理从新配置参数。然后再onCreate()方法中调用此方法。
private void setOverflowButtonAlways()
{
try
{
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKey = ViewConfiguration.class
.getDeclaredField("sHasPermanentMenuKey");
menuKey.setAccessible(true);
menuKey.setBoolean(config, false);
} catch (Exception e)
{
e.printStackTrace();
}
}
如果,想要在ActonBar中的图标不显示,在onCreate()方法中,配置如下:
getActionBar().setDisplayShowHomeEnabled(false);
2.自定义溢出菜单的图标样式
如果你的API在14+.那么是在你的values-14中的styles.xml中配置如下:
3.隐藏图标的显示。
@Override
public boolean onMenuOpened(int featureId, Menu menu)
{
if (featureId == Window.FEATURE_ACTION_BAR && menu != null)
{
if (menu.getClass().getSimpleName().equals("MenuBuilder"))
{
try
{
Method m = menu.getClass().getDeclaredMethod(
"setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
} catch (Exception e)
{
e.printStackTrace();
}
}
}
return super.onMenuOpened(featureId, menu);
}
最后:再把Menu下的main.xml文件补全:
二.取巧的方法:
这部分,再讲一下,取巧的方法:
我发现虽然溢出菜单中的图标不显示,但是如果将隐藏图标放到alway菜单(“+”号)下面,图标是显示的。
如图:
补充:上图是点击“+”号效果。
所以可以,不使用溢出菜单,直接将“+”设置为:android:showAsAction="always"
-
三.用PopupWindow实现自定义溢出(overflow)菜单;
如图:
首先,看下main.xml配置:
监听ID为action_overflow的Action,创建popupWindow弹出自己的overflow
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (id) {
case R.id.action_overflow:
opUpMyOverflow();// 弹出自定义overflow
break;
}
return super.onOptionsItemSelected(item);
}
下面介绍popUpMyOverflow()方法,就是通过它弹出了我们的overflow:
private void opUpMyOverflow() {
/**
* 定位PopupWindow,让它恰好显示在Action Bar的下方。 通过设置Gravity,确定PopupWindow的大致位置。
* 首先获得状态栏的高度,再获取Action bar的高度,这两者相加设置y方向的offset样PopupWindow就显示在action
* bar的下方了。 通过dp计算出px,就可以在不同密度屏幕统一X方向的offset.但是要注意不要让背景阴影大于所设置的offset,
* 否则阴影的宽度为offset.
*/
// 获取状态栏高度
Rect frame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
// 状态栏高度:frame.top
int yOffset = frame.top + getActionBar().getHeight();// 减去阴影宽度,适配UI.
int xOffset = Dp2Px(this, 5f); // 设置x方向offset为5dp
View parentView = getLayoutInflater().inflate(R.layout.activity_main,
null);
View popView = getLayoutInflater().inflate(
R.layout.action_overflow_popwindow, null);
final PopupWindow popWind = new PopupWindow(popView,
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true);// popView即popupWindow的布局,ture设置focusAble.
ll_one = (LinearLayout) popView.findViewById(R.id.ll_one);
ll_two = (LinearLayout) popView.findViewById(R.id.ll_two);
ll_one.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "添加", 0).show();
popWind.dismiss();
}
});
ll_two.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "群聊", 0).show();
popWind.dismiss();
}
});
// 必须设置BackgroundDrawable后setOutsideTouchable(true)才会有效。这里在XML中定义背景,所以这里设置为null;
popWind.setBackgroundDrawable(new BitmapDrawable(getResources(),
(Bitmap) null));
popWind.setOutsideTouchable(true); // 点击外部关闭。
popWind.setAnimationStyle(android.R.style.Animation_Dialog); // 设置一个动画。
// 设置Gravity,让它显示在右上角。
popWind.showAtLocation(parentView, Gravity.RIGHT | Gravity.TOP,
xOffset, yOffset);
}
在android中,为了适配不同屏幕密度和尺寸,android用了Dp单位,但是在Java代码中多是接受px单位的尺寸,所以这里要转换一下。 public int Dp2Px(Context context, float dp) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
最后,贴出自定义overflow的布局文件就是R.layout.action_overflow_popwindow