Android custom control: Implementation and optimization of the drop-down menu
Drop-down menu
Widgets that are frequently encountered in the drop-down menu project similar to those on the home page of Meituan. The types and quantities of menu entries are different in different projects. Therefore, you need to fill in different contents as needed. First, write a demo, which is a time-consuming one. Since the menu styles used by each project are different, we must fill them according to the actual situation so that the container and content need to be separated.
Container
Of course, popWindow is used for container painting. We need to pop up the window after clicking the specified control.
1. Specify the position and size of the current window
2. Specify the window output mode
3. If other parts are required to be dimmed, we must specify the height of the dimmed part.
Content
The content needs to be filled in the container, and different page fills should be set according to different data types and needs. You can define it as ** combined control ** or a ** Holder **. You need to provide two basic methods: the control filling method and the data refreshing method. At the same time, you also need a method to expose a reference to the View so that you can fill the View to any location we want to add.
BaseHolder
/** * Created by Administrator on 2015/10/30 0030. */public abstract class BaseHolder
{ private View mView; public abstract View initView(); public abstract void refreshView(T info); public BaseHolder(){ mView = initView(); mView.setTag(this); } public View getView(){ return mView; }}
Pop-up code
Assume that we press the next Button and popwindow pops up. At this time, we need to inherit a Button,
Rewrite the OnClick method of the Button to bring up the popwindow at the bottom of the Button.
Public class PopMenuButton extends Button implements View. onClickListener {private Context mCtx; private PopupWindow mPopupWindow; private LinearLayout mPopupWindowView; // you can set the root layout to the position of the pop-up popwindow in the Button. You can refer to the private View mRootView in the root layout; private LinearLayout mContentView; private int [] mLocation = new int [2]; private int mStartY; private int mScreenHeight; public PopMenuButton (Context context, AttributeSet attrs) {super (context, attrs); mCtx = context; mRootView = this;} public PopMenuButton (Context context) {super (context); mCtx = context; mRootView = this;} @ Override protected void onFinishInflate () {super. onFinishInflate (); initPopWindow ();} public void setContentView (View view) {LinearLayout. layoutParams params = new LinearLayout. layoutParams (LinearLayout. layoutParams. WRAP_CONTENT, LinearLayout. layoutParams. WRAP_CONTENT); mContentView. addView (view, params);} private void initView () {mPopupWindowView = (LinearLayout) View. inflate (mCtx, R. layout. popmenu_layout, null); mContentView = (LinearLayout) mPopupWindowView. findViewById (R. id. rl_content); mShodowView = mPopupWindowView. findViewById (R. id. rl_shodow); mShodowView. setOnClickListener (new OnClickListener () {@ Override public void onClick (View v) {mPopupWindow. dismiss () ;}}); setOnClickListener (this);} private void initPopWindow () {initView (); // obtain the mRootView position of the key. getLocationOnScreen (mLocation); mStartY = mLocation [1] + mRootView. getHeight () ;}@ Override public void onClick (View v) {if (mPopupWindow = null) {// initPopWindow (); int [] location = new int [2]; this. getLocationOnScreen (location); // start position of the Y axis int start = location [1] + this. getHeight () + 1; // int screenHeight = (Activity) mCtx ). getWindowManager (). getdefadisplay display (). getHeight (); // set the size of the bullet box. The position of the bullet box is below the button, occupying all screen mPopupWindow = new PopupWindow (mPopupWindowView, ViewGroup. layoutParams. MATCH_PARENT, screenHeight-start, false); // mPopupWindow = new PopupWindow (mPopupWindowView, ViewGroup. layoutParams. MATCH_PARENT, ViewGroup. layoutParams. MATCH_PARENT, false); mPopupWindow. setBackgroundDrawable (new ColorDrawable (0xb0000000); // mPopupWindow. setAnimationStyle (R. style. animationFade); mPopupWindow. setAnimationStyle (R. style. popupAnimation); mPopupWindow. setFocusable (true); mPopupWindow. setOutsideTouchable (true);} if (mPopupWindow. isShowing () {mPopupWindow. dismiss ();} else {int [] location1 = new int [2]; this. getLocationOnScreen (location1); // you can specify the position of the pop-up window. showAtLocation (mRootView, Gravity. NO_GRAVITY, 0, location1 [1] + this. getHeight () + 1) ;}} private int dip2px (Context context, float dpValue) {final float scale = context. getResources (). getDisplayMetrics (). density; return (int) (dpValue * scale );}}
Level 2 menu Holder
Suppose we want to bring up a level-2 menu, we can encapsulate the logic into a Holder, and finally let the holder provide us with the page, directly paste the page into the container.
/*** Created by vonchenchen on 2015/10/30 0030. */public class DoubleListViewHolder extends BaseHolder
>>{ Private List
> MData; private ListView mLeftListView; private ListView mRightListView; private List
MLeftList; private List
MRightList; private TextListAdapter mLeftAdapter; private TextRightListAdapter mRightAdapter; private View mViewClickRecorder = null; private boolean mFirstMesure = true; @ Override public View initView () {View view = View. inflate (MyApplication. getContext (), R. layout. doublelistview_layout, null); mLeftListView = (ListView) view. findViewById (R. id. ll_left); mRightListView = (ListView) view. findViewById (R. id. ll_right); mLeftListView. setOnItemClickListener (new AdapterView. onItemClickListener () {@ Override public void onItemClick (AdapterView
Parent, View view, int position, long id) {// if you click an entry, change the color of the clicked entry if (mViewClickRecorder! = View) {view. setBackgroundColor (MyApplication. getContext (). getResources (). getColor (R. color. normal_selected_color); if (mViewClickRecorder! = Null) {mViewClickRecorder. setBackgroundColor (MyApplication. getContext (). getResources (). getColor (R. color. normal_unselected_color);} mViewClickRecorder = view;} mRightList = mData. get (position + 1); mRightAdapter = new TextRightListAdapter (mRightList); mRightListView. setAdapter (mRightAdapter) ;}}); return view ;}@ Override public void refreshView (List
> Info) {this. mData = info; mLeftList = info. get (0); mLeftAdapter = new TextListAdapter (mLeftList); mRightList = info. get (1); mRightAdapter = new TextRightListAdapter (mRightList); mLeftListView. setAdapter (mLeftAdapter); mRightListView. setAdapter (mRightAdapter);} class TextListAdapter extends MyAdapter {public TextListAdapter (List list) {super (list) ;}@ Override public View getView (final int position, View convertView, ViewGroup parent) {TextViewHolder holder = null; if (convertView = null) {holder = new TextViewHolder () ;}else {holder = (TextViewHolder) convertView. getTag ();} convertView = holder. getView (); holder. refreshView (String) getItem (position); // prevents multiple measurements if (position = 0 & mFirstMesure) {mFirstMesure = false; convertView. setBackgroundColor (MyApplication. getContext (). getResources (). getColor (R. color. normal_selected_color); mViewClickRecorder = convertView;} return convertView;} class TextRightListAdapter extends MyAdapter {public TextRightListAdapter (List list) {super (list );} @ Override public View getView (final int position, View convertView, ViewGroup parent) {TextViewHolder holder = null; if (convertView = null) {holder = new TextViewHolder ();} else {holder = (TextViewHolder) convertView. getTag ();} convertView = holder. getView (); holder. refreshView (String) getItem (position); return convertView ;}}/ *** Holder */private class TextViewHolder extends BaseHolder in ListView
{Private TextView mTextView; @ Override public View initView () {View view = View. inflate (MyApplication. getContext (), R. layout. simpletext_item, null); mTextView = (TextView) view. findViewById (R. id. TV _text); return view;} @ Override public void refreshView (String info) {mTextView. setText (info );}}}
Add content to container
The following four steps are involved in the call process. In this way, the logic and data are naturally separated.
// Create PopMenuButton mPopMenuButton = (PopMenuButton) findViewById (R. id. btn_pop); // create a Holder and provide the content DoubleListViewHolder holder = new DoubleListViewHolder (); // paste the content to mPopMenuButton in the container. setContentView (holder. getView (); // use data to refresh the display content of the container holder. refreshView (mLists );