當Action Bar的Action放不下時,系統會將其收集在overflow中。
用hierarchyviewer查看系統自己生成的Overflow,發現它本身就是popupWindow。
所以我們也可以用popUpWindow來寫自己的overflow實現更多功能,做出像微信一樣的效果。
第一次寫,廢話有點多,還望多包涵。
效果(GIF演示在文章底部):
最右邊的Action(那個三點菜單)是自己添加的Action,使用了android開發包里的圖標ic_action_overflow.png,可到官網下載。
首先在Item中添加Action,為了演示,添加了一個Submenu
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:context="com.example.popupwindowoverflow.MainActivity" > <item android:id="@+id/action_new" android:orderInCategory="1" android:title="SubMenu" android:icon="@drawable/ic_action_new" app:showAsAction="always"> <menu> <item android:id="@+id/submenu1" android:title="Accept" android:titleCondensed="Accept" android:icon="@drawable/ic_action_accept" /> <item android:id="@+id/submenu2" android:title="Cancel" android:titleCondensed="Cancel" android:icon="@drawable/ic_action_cancel" /> <item android:id="@+id/submenu3" android:title="Unread" android:titleCondensed="Unread" android:icon="@drawable/ic_action_unread" /> </menu> </item> <item android:id="@+id/action_overflow" android:orderInCategory="2" android:title="PopupWindow" android:icon="@drawable/ic_action_overflow" app:showAsAction="always"/> </menu>
監聽ID為action_overflow的Action,創建popupWindow彈出自己的overflow。
1 public boolean onOptionsItemSelected(MenuItem item) { 2 // Handle action bar item clicks here. The action bar will 3 // automatically handle clicks on the Home/Up button, so long 4 // as you specify a parent activity in AndroidManifest.xml. 5 int id = item.getItemId(); 6 switch (id) { 7 case R.id.action_overflow: 8 popUpMyOverflow();//彈出自定義overflow 9 return true; 10 } 11 return super.onOptionsItemSelected(item); 12 }
下面介紹popUpMyOverflow()方法,就是通過它彈出了我們的overflow,自定義overflow的布局文件就是R.layout.action_overflow_popwindow,這里就不貼出來啦。
1 public void popUpMyOverflow() { 2 /** 3 * 定位PopupWindow,讓它恰好顯示在Action Bar的下方。 通過設置Gravity,確定PopupWindow的大致位置。 4 * 首先獲得狀態欄的高度,再獲取Action bar的高度,這兩者相加設置y方向的offset樣PopupWindow就顯示在action 5 * bar的下方了。 通過dp計算出px,就可以在不同密度屏幕統一X方向的offset.但是要注意不要讓背景陰影大於所設置的offset, 6 * 否則陰影的寬度為offset. 7 */ 8 // 獲取狀態欄高度 9 Rect frame = new Rect(); 10 getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); 11 // 狀態欄高度:frame.top 12 int xOffset = frame.top+getActionBar().getHeight()-25;//減去陰影寬度,適配UI. 13 int yOffset = Dp2Px(this, 5f); //設置x方向offset為5dp 14 View parentView = getLayoutInflater().inflate(R.layout.activity_main, 15 null); 16 View popView = getLayoutInflater().inflate( 17 R.layout.action_overflow_popwindow, null); 18 PopupWindow popWind = new PopupWindow(popView, 19 LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true);//popView即popupWindow的布局,ture設置focusAble. 20 21 //必須設置BackgroundDrawable后setOutsideTouchable(true)才會有效。這里在XML中定義背景,所以這里設置為null; 22 popWind.setBackgroundDrawable(new BitmapDrawable(getResources(), 23 (Bitmap) null)); 24 popWind.setOutsideTouchable(true); //點擊外部關閉。 25 popWind.setAnimationStyle(android.R.style.Animation_Dialog); //設置一個動畫。 26 //設置Gravity,讓它顯示在右上角。 27 popWind.showAtLocation(parentView, Gravity.RIGHT | Gravity.TOP, 28 yOffset, xOffset); 29 }
在android中,為了適配不同屏幕密度和尺寸,android用了Dp單位,但是在Java代碼中多是接受px單位的尺寸,所以這里要轉換一下。
Dp轉換Px的方法。
1 public int Dp2Px(Context context, float dp) { 2 final float scale = context.getResources().getDisplayMetrics().density; 3 return (int) (dp * scale + 0.5f); 4 }
好的,現在我們有了所有要顯示自定義Overflow的東西了!運行你的app吧。
最終效果: