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

下拉菜单

美团首页类似的下拉弹出菜单工程中经常遇到的控件,不同工程中菜单条目的类型与数量也不一样

所以需要根据实际需要填充不同内容。先写个demo,一倍不时之需吧。

既然每个项目用到的菜单样式不同,此时我们必须根据实际情况填充,这样就需要将容器和内容分开。

223196_0.png

容器

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

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

2.指定window出方式

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

内容

内容需要被填充到容器中,根据不同的数据类型及需求,设置不同的页面填充。可以将其定义为**组合控件**或者一个**Holder**。

需要提供控件填充方法和数据刷新两个基本方法,同时还需要一个方法暴露一个View的引用,这样就可以将这个View填充到我们想添加的任何位置。

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;

}

}

弹窗代码

假定我们现在按下一个按键,然后弹出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>> {

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(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));

//防止多次测量

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{

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);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值