转载

Android自定义控件:下拉菜单的实现与优化

下拉菜单

美团首页类似的下拉弹出菜单工程中经常遇到的控件,不同工程中菜单条目的类型与数量也不一样 所以需要根据实际需要填充不同内容。先写个demo,一倍不时之需吧。  既然每个项目用到的菜单样式不同,此时我们必须根据实际情况填充,这样就需要将容器和内容分开。 

Android自定义控件:下拉菜单的实现与优化

容器

容器的画当然就使用popWindow了,我们需要在点击指定控件后弹出window,需要 

1.指定当前window的位置及大小

2.指定window出方式

3.如果要求其他部分变暗,我们必须指定变暗部分的高度

内容

内容需要被填充到容器中,根据不同的数据类型及需求,设置不同的页面填充。可以将其定义为**组合控件**或者一个**Holder**。 需要提供控件填充方法和数据刷新两个基本方法,同时还需要一个方法暴露一个View的引用,这样就可以将这个View填充到我们想添加的任何位置。 

BaseHolder

/**  * Created by Administrator on 2015/10/30 0030.  */ public abstract class BaseHolder<T> {      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;     } }

弹窗代码

假定我们现在按下一个按键,然后弹出popwindow,此时我们需要继承一个Button,复写Button的OnClick方法,从而实现点击按键在按键正下方弹出popwindow的效果。

public class PopMenuButton extends Button  implements View.OnClickListener {      private Context mCtx;     private PopupWindow mPopupWindow;     private LinearLayout mPopupWindowView;     //根布局设置为Button 弹出popwindow的位置可以以根布局为参照     private View mRootView;     private View mShodowView;     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();         //获取按键的位置         mRootView.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);             //y轴起始位置             int start = location[1] + this.getHeight() + 1;             //测量屏幕的高度             int screenHeight = ((Activity) mCtx).getWindowManager().getDefaultDisplay().getHeight();              //设置弹框的大小  弹框位置在按钮以下,占据所有屏幕             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);             //设置弹框的位置             mPopupWindow.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);     } }

二级菜单Holder

假设我们当前要弹出一个二级菜单,我们可以将逻辑封装到一个Holder中,最终让holder为我们提供页面,直接将页面贴到容器中。

/**  * Created by vonchenchen on 2015/10/30 0030.  */ public class DoubleListViewHolder extends BaseHolder<List<List<String>>> {      private List<List<String>> mData;      private ListView mLeftListView;     private ListView mRightListView;      private List<String> mLeftList;     private List<String> 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(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<List<String>> 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));              //防止多次测量             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;         }     }      /**      * ListView 中的 Holder      */     private class TextViewHolder extends BaseHolder<String>{          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);         }     } }

将内容添加到容器中

调用的时候分为以下四步。这样,显示,逻辑和数据就自然分离开来了。

//创建容器         PopMenuButton mPopMenuButton = (PopMenuButton) findViewById(R.id.btn_pop);         //创建Holder,提供内容         DoubleListViewHolder holder = new DoubleListViewHolder();          //将 内容 贴到 容器 中         mPopMenuButton.setContentView(holder.getView());         //用数据刷新容器的显示内容         holder.refreshView(mLists);

git: https://git.oschina.net/vonchenchen/pulldownmenu.git

原文  http://www.androidchina.net/3928.html
正文到此结束
Loading...