11package de .dlyt .yanndroid .oneui .view ;
22
3+ import android .annotation .SuppressLint ;
4+ import android .app .Activity ;
35import android .content .Context ;
6+ import android .content .ContextWrapper ;
47import android .util .TypedValue ;
8+ import android .view .KeyEvent ;
59import android .view .LayoutInflater ;
10+ import android .view .Menu ;
11+ import android .view .MenuInflater ;
12+ import android .view .MenuItem ;
13+ import android .view .MotionEvent ;
614import android .view .View ;
715import android .view .ViewGroup ;
816import android .widget .AdapterView ;
917import android .widget .ArrayAdapter ;
1018import android .widget .LinearLayout ;
11- import android .widget .ListAdapter ;
1219import android .widget .PopupWindow ;
1320import android .widget .TextView ;
1421
22+ import androidx .annotation .MenuRes ;
23+ import androidx .appcompat .app .AppCompatActivity ;
24+ import androidx .appcompat .view .SupportMenuInflater ;
25+ import androidx .appcompat .view .menu .MenuBuilder ;
26+
27+ import java .text .NumberFormat ;
1528import java .util .ArrayList ;
29+ import java .util .HashMap ;
30+ import java .util .Locale ;
1631
1732import de .dlyt .yanndroid .oneui .R ;
1833import de .dlyt .yanndroid .oneui .sesl .utils .ReflectUtils ;
@@ -22,50 +37,102 @@ public class PopupMenu {
2237
2338 private Context context ;
2439 private View anchor ;
40+ private NumberFormat numberFormat = NumberFormat .getInstance (Locale .getDefault ());
41+ public static final int N_BADGE = -1 ;
42+ private OnMenuItemClickListener onMenuItemClickListener = item -> {
43+ };
2544
45+ private Menu menu ;
2646 private PopupWindow popupWindow ;
27- private PopupListView listView ;
2847 private PopupMenuAdapter popupMenuAdapter ;
48+ private HashMap <MenuItem , Integer > overflowBadges = new HashMap <>();
2949
3050 public PopupMenu (View anchor ) {
3151 this .context = anchor .getContext ();
3252 this .anchor = anchor ;
3353 }
3454
35- public void inflate (ArrayList <String > menu ) {
55+ public interface OnMenuItemClickListener {
56+ void onMenuItemClick (MenuItem item );
57+ }
58+
59+ public void setOnMenuItemClickListener (OnMenuItemClickListener listener ) {
60+ onMenuItemClickListener = listener ;
61+ }
62+
63+ public Menu getMenu () {
64+ return menu ;
65+ }
66+
67+ @ SuppressLint ("RestrictedApi" )
68+ public void inflate (@ MenuRes int menuRes ){
69+ menu = new MenuBuilder (context );
70+ MenuInflater menuInflater = new SupportMenuInflater (context );
71+ menuInflater .inflate (menuRes , menu );
72+
73+ ArrayList <MenuItem > menuItems = new ArrayList <>();
74+
75+ for (int i = 0 ; i < menu .size (); i ++) {
76+ MenuItem item = menu .getItem (i );
77+ overflowBadges .put (item , 0 );
78+ menuItems .add (item );
79+ }
80+
81+ if (menuItems .isEmpty ()) return ;
82+
3683 if (popupWindow != null ) {
3784 if (popupWindow .isShowing ()) {
3885 popupWindow .dismiss ();
3986 }
4087 popupWindow = null ;
4188 }
42-
43- listView = new PopupListView (context );
44- popupMenuAdapter = new PopupMenuAdapter (menu );
89+ PopupListView listView = new PopupListView (context );
90+ popupMenuAdapter = new PopupMenuAdapter (getActivity (), menuItems );
4591 listView .setAdapter (popupMenuAdapter );
4692 listView .setMaxHeight (context .getResources ().getDimensionPixelSize (R .dimen .sesl_menu_popup_max_height ));
4793 listView .setDivider (null );
48- listView .setSelector (R .drawable .sesl_list_selector );
94+ listView .setSelector (context .getResources ().getDrawable (R .drawable .sesl_list_selector , context .getTheme ()));
95+ listView .setOnItemClickListener (new AdapterView .OnItemClickListener () {
96+ @ Override
97+ public void onItemClick (AdapterView <?> parent , View view , int position , long id ) {
98+ onMenuItemClickListener .onMenuItemClick ((MenuItem ) popupMenuAdapter .getItem (position ));
99+ }
100+ });
49101
50102 listView .measure (ViewGroup .LayoutParams .WRAP_CONTENT , ViewGroup .LayoutParams .WRAP_CONTENT );
51- int height = listView .getMeasuredHeight () + context .getResources ().getDimensionPixelSize (R .dimen .sesl_popup_menu_item_bottom_padding ) -5 ;
103+ int height = listView .getMeasuredHeight () + context .getResources ().getDimensionPixelSize (R .dimen .sesl_popup_menu_item_bottom_padding ) - 5 ;
52104
53105 popupWindow = new PopupWindow (listView );
54106 popupWindow .setWidth (getPopupMenuWidth ());
55107 popupWindow .setHeight (height );
56- //popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
57108 popupWindow .setAnimationStyle (R .style .MenuPopupAnimStyle );
58- popupWindow .setBackgroundDrawable (context .getDrawable (R .drawable .sesl_menu_popup_background ));
109+ popupWindow .setBackgroundDrawable (context .getResources (). getDrawable (R .drawable .sesl_menu_popup_background , context . getTheme () ));
59110 popupWindow .setOutsideTouchable (true );
60111 popupWindow .setElevation (TypedValue .applyDimension (TypedValue .COMPLEX_UNIT_DIP , (float ) 12 , context .getResources ().getDisplayMetrics ()));
61112 popupWindow .setFocusable (true );
62113 if (popupWindow .isClippingEnabled ()) {
63114 popupWindow .setClippingEnabled (false );
64115 }
65- }
66-
67- public void setOnMenuItemClickListener (AdapterView .OnItemClickListener listener ) {
68- listView .setOnItemClickListener (listener );
116+ popupWindow .getContentView ().setOnKeyListener (new View .OnKeyListener () {
117+ @ Override
118+ public boolean onKey (View view , int i , KeyEvent keyEvent ) {
119+ if (keyEvent .getKeyCode () != KeyEvent .KEYCODE_MENU || keyEvent .getAction () != KeyEvent .ACTION_UP || !popupWindow .isShowing ()) {
120+ return false ;
121+ }
122+ popupWindow .dismiss ();
123+ return true ;
124+ }
125+ });
126+ popupWindow .setTouchInterceptor (new View .OnTouchListener () {
127+ @ Override
128+ public boolean onTouch (View view , MotionEvent motionEvent ) {
129+ if (motionEvent .getAction () != MotionEvent .ACTION_OUTSIDE ) {
130+ return false ;
131+ }
132+ popupWindow .dismiss ();
133+ return true ;
134+ }
135+ });
69136 }
70137
71138 public void show () {
@@ -81,71 +148,99 @@ public void dismiss() {
81148 popupWindow .dismiss ();
82149 }
83150
84- private int getPopupMenuWidth () {
85- int makeMeasureSpec = View .MeasureSpec .makeMeasureSpec (0 , View .MeasureSpec .UNSPECIFIED );
86- View view = null ;
87- ViewGroup viewGroup = null ;
88- int measuredWidth = 0 ;
151+ public boolean isShowing (){
152+ return popupWindow .isShowing ();
153+ }
89154
90- int i = 0 ;
91- int count = popupMenuAdapter .getCount ();
92155
93- while (i < count ) {
94- ViewGroup linearLayout ;
95- int itemViewType = popupMenuAdapter .getItemViewType (i );
156+ public void setMenuItemBadge (MenuItem item , Integer badge ) {
157+ overflowBadges .put (item , badge );
158+ popupMenuAdapter .notifyDataSetChanged ();
159+ popupWindow .setWidth (getPopupMenuWidth ());
160+ if (popupWindow .isShowing ()) popupWindow .dismiss ();
161+ }
96162
97- if (itemViewType != 0 )
98- view = null ;
163+ public Integer getOverflowMenuBadge (MenuItem item ) {
164+ return overflowBadges .get (item );
165+ }
99166
100- if (viewGroup == null )
101- linearLayout = new LinearLayout (context );
102- else
103- linearLayout = viewGroup ;
167+ private int getPopupMenuWidth () {
168+ int makeMeasureSpec = View .MeasureSpec .makeMeasureSpec (0 , View .MeasureSpec .UNSPECIFIED );
169+ int popupWidth = 0 ;
104170
105- view = popupMenuAdapter .getView (i , view , linearLayout );
171+ for (int i = 0 ; i < popupMenuAdapter .getCount (); i ++) {
172+ View view = popupMenuAdapter .getView (i , null , new LinearLayout (context ));
106173 view .measure (makeMeasureSpec , makeMeasureSpec );
107- measuredWidth = view .getMeasuredWidth ();
108- if (measuredWidth <= 0 ) {
109- measuredWidth = 0 ;
174+ int measuredWidth = view .getMeasuredWidth ();
175+ if (measuredWidth > popupWidth ) {
176+ popupWidth = measuredWidth ;
177+ }
178+ }
179+ return popupWidth ;
180+ }
181+
182+ private AppCompatActivity getActivity () {
183+ while (context instanceof ContextWrapper ) {
184+ if (context instanceof AppCompatActivity ) {
185+ return (AppCompatActivity ) context ;
110186 }
111- i ++;
112- viewGroup = linearLayout ;
187+ context = ((ContextWrapper ) context ).getBaseContext ();
113188 }
114- return measuredWidth ;
189+ return null ;
115190 }
116191
192+
117193 private class PopupMenuAdapter extends ArrayAdapter {
118- ArrayList <String > itemTitle ;
194+ Activity activity ;
195+ ArrayList <MenuItem > overflowItems ;
119196
120- public PopupMenuAdapter (ArrayList <String > itemTitle ) {
121- super (context , 0 );
122- this .itemTitle = itemTitle ;
197+ public PopupMenuAdapter (Activity instance , ArrayList <MenuItem > overflowItems ) {
198+ super (instance , 0 );
199+ this .activity = instance ;
200+ this .overflowItems = overflowItems ;
123201 }
124202
125203 @ Override
126204 public int getCount () {
127- return itemTitle .size ();
205+ return overflowItems .size ();
128206 }
129207
130208 @ Override
131209 public Object getItem (int position ) {
132- return itemTitle .get (position );
210+ return overflowItems .get (position );
133211 }
134212
135213 @ Override
136214 public View getView (int index , View view , ViewGroup parent ) {
137- final TextView titleText ;
138-
139- if (view == null ) {
140- view = ((LayoutInflater ) context .getSystemService (Context .LAYOUT_INFLATER_SERVICE )).inflate (R .layout .menu_popup_item_layout , parent , false );
141- titleText = view .findViewById (R .id .more_menu_popup_title_text );
142- view .setTag (titleText );
215+ TextView titleText ;
216+ TextView badgeIcon ;
217+
218+ view = ((LayoutInflater ) activity .getSystemService (Context .LAYOUT_INFLATER_SERVICE )).inflate (R .layout .menu_popup_item_layout , parent , false );
219+ titleText = view .findViewById (R .id .more_menu_popup_title_text );
220+ titleText .setText (overflowItems .get (index ).getTitle ());
221+
222+ badgeIcon = view .findViewById (R .id .more_menu_popup_badge );
223+ Integer badgeCount = overflowBadges .get (overflowItems .get (index ));
224+
225+ if (badgeCount > 0 ) {
226+ int count = badgeCount ;
227+ if (count > 99 ) {
228+ count = 99 ;
229+ }
230+ String countString = numberFormat .format ((long ) count );
231+ badgeIcon .setText (countString );
232+ int width = (int ) (context .getResources ().getDimension (R .dimen .sesl_badge_default_width ) + (float ) countString .length () * context .getResources ().getDimension (R .dimen .sesl_badge_additional_width ));
233+ LinearLayout .LayoutParams lp = (LinearLayout .LayoutParams ) badgeIcon .getLayoutParams ();
234+ lp .width = width ;
235+ badgeIcon .setLayoutParams (lp );
236+ badgeIcon .setVisibility (View .VISIBLE );
237+ } else if (badgeCount == N_BADGE ) {
238+ badgeIcon .setText ("N" );
239+ badgeIcon .setVisibility (View .VISIBLE );
143240 } else {
144- titleText = ( TextView ) view . getTag ( );
241+ badgeIcon . setVisibility ( View . GONE );
145242 }
146243
147- titleText .setText (itemTitle .get (index ));
148-
149244 return view ;
150245 }
151246 }
0 commit comments