2

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

 2 years ago
source link: http://www.androidchina.net/3928.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Android自定义控件:下拉菜单的实现与优化 – Android开发中文站
你的位置:Android开发中文站 > Android开发 > 开发进阶 > Android自定义控件:下拉菜单的实现与优化
美团首页类似的下拉弹出菜单工程中经常遇到的控件,不同工程中菜单条目的类型与数量也不一样
所以需要根据实际需要填充不同内容。先写个demo,一倍不时之需吧。

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

这里写图片描述

容器的画当然就使用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

转载请注明:Android开发中文站 » Android自定义控件:下拉菜单的实现与优化


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK