Android开发之多级下拉列表菜单实现(仿美团,淘宝等)

我们在常用的电商或者旅游APP中,例如美团,手机淘宝等等,都能够看的到有那种下拉式的二级列表菜单。具体如图所示:

\


\

上面两张图就是美团的一个二级列表菜单的一个展示。我相信很多人都想开发一个跟它一样的功能放到自己的APP中。好,接下来我们就开始动手,解决它。


<喎�"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPGgyPjGjrL3hubm31s72PC9oMj4KPHA+ytfPyKOsztLDx7j4s/bV4rj2z8LAtLLLtaXQ6NKqtcTX6b2ooaPO0sPH08PP37/yzbzAtLfWzvahozwvcD4KPHA+PGltZyBzcmM9"http://www.2cto.com/uploadfile/Collfiles/20140923/2014092309051719.jpg" width="600" alt="\">

1)如上图所示,最外围的是一个Activity,顶部包含了一个View的容器,这个容器主要是装载ToggleButton来实现诸如美团里面的“美食,全城,理我最近,刷选”这一行。这一行一点就会弹出对应的下来菜单。

2)下拉菜单是如何实现的呢?,这里我们利用了PopupWindow来实现这一弹出式窗口。然后我们在弹出式窗口里面再定义我们的下来列表项,是单列还是二级菜单,都是由里面来定。

3)不同的菜单,需要一级或者需要二级,在这里根据我的需求而变动。我们在PopupWindow上面加一个自定义的LeftView,或者是MiddleView,RightView。主要是一个ToggleButton,你弹出一个窗口,你就定制一个窗口。

3)视图里面嵌入ListView,就形成了列表项。

好分析就到上面为止,接下来我们一步步的说明实现。

2,项目结构

本项目的项目结构如图所示:

1) Adapter。适配器,主要是为ListView提供数据适配的。

2)MainActivity。主活动页面。

3)ExpandTabView。本项目的核心类,它包含ToggleButton容器和PopupWindow,是控制弹出窗口的核心类。

4)ViewLeft,ViewMiddle,ViewRight。是弹出里面嵌套的类,实现不同的列表菜单。


\



3,MainActivity

承载所有元素。看代码比看文字实在。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package com.example.expandtabview;
 
 
import java.util.ArrayList;
 
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
 
import com.example.view.ExpandTabView;
import com.example.view.ViewLeft;
import com.example.view.ViewMiddle;
import com.example.view.ViewRight;
 
public class MainActivity extends Activity {
     private static final String TAG = "MainActivity" ;
     private ExpandTabView expandTabView;
     private ArrayList<view> mViewArray = new ArrayList<view>();
     private ViewLeft viewLeft;
     private ViewMiddle viewMiddle;
     private ViewRight viewRight;
     
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         initView();
         initVaule();
         initListener();
         
     }
 
     private void initView() {
         Log.d(TAG, "initView" );
         expandTabView = (ExpandTabView) findViewById(R.id.expandtab_view);
         viewLeft = new ViewLeft( this );
         viewMiddle = new ViewMiddle( this );
         viewRight = new ViewRight( this );
         
     }
 
     private void initVaule() {
         Log.d(TAG, "initValue" );
         mViewArray.add(viewLeft);
         mViewArray.add(viewMiddle);
         mViewArray.add(viewRight);
         ArrayList<string> mTextArray = new ArrayList<string>();
         mTextArray.add( "距离" );
         mTextArray.add( "区域" );
         mTextArray.add( "距离" );
         expandTabView.setValue(mTextArray, mViewArray); //将三个下拉列表设置进去
         expandTabView.setTitle(viewLeft.getShowText(), 0 );
         expandTabView.setTitle(viewMiddle.getShowText(), 1 );
         expandTabView.setTitle(viewRight.getShowText(), 2 );
         
     }
 
     private void initListener() {
         Log.d(TAG, "initListener" );
         viewLeft.setOnSelectListener( new ViewLeft.OnSelectListener() {
 
             @Override
             public void getValue(String distance, String showText) {
                 Log.d( "ViewLeft" , "OnSelectListener, getValue" );
                 onRefresh(viewLeft, showText);
             }
         });
         
         viewMiddle.setOnSelectListener( new ViewMiddle.OnSelectListener() {
             
             @Override
             public void getValue(String showText) {
                 Log.d( "ViewMiddle" , "OnSelectListener, getValue" );
                 onRefresh(viewMiddle,showText);
                 
             }
         });
         
         viewRight.setOnSelectListener( new ViewRight.OnSelectListener() {
 
             @Override
             public void getValue(String distance, String showText) {
                 Log.d( "ViewRight" , "OnSelectListener, getValue" );
                 onRefresh(viewRight, showText);
             }
         });
         
     }
     
     private void onRefresh(View view, String showText) {
         Log.d(TAG, "onRefresh,view:" +view+ ",showText:" +showText);
         expandTabView.onPressBack();
         int position = getPositon(view);
         if (position >= 0 && !expandTabView.getTitle(position).equals(showText)) {
             expandTabView.setTitle(showText, position);
         }
         Toast.makeText(MainActivity. this , showText, Toast.LENGTH_SHORT).show();
 
     }
     
     private int getPositon(View tView) {
         Log.d(TAG, "getPosition" );
         for ( int i = 0 ; i < mViewArray.size(); i++) {
             if (mViewArray.get(i) == tView) {
                 return i;
             }
         }
         return - 1 ;
     }
     
     @Override
     public void onBackPressed() {
         
         if (!expandTabView.onPressBack()) {
             finish();
         }
         
     }
 
}</string></string></view></view>

4 ,ExpandTabView

最主要就是如何处理当我们点击这些ToggleButton的时候要弹出或者收起这些PopupWindow。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
package com.example.view;
 
import java.util.ArrayList;
 
import com.example.expandtabview.R;
 
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.PopupWindow.OnDismissListener;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.ToggleButton;
 
/**
  * 菜单控件头部,封装了下拉动画,动态生成头部按钮个数
  *
  * @author zengjinlong
  */
 
public class ExpandTabView extends LinearLayout implements OnDismissListener {
     private static final String TAG = "ExpandTabView" ;
     private ToggleButton selectedButton;
     private ArrayList<string> mTextArray = new ArrayList<string>();
     private ArrayList<relativelayout> mViewArray = new ArrayList<relativelayout>();
     private ArrayList<togglebutton> mToggleButton = new ArrayList<togglebutton>();
     private Context mContext;
     private final int SMALL = 0 ;
     private int displayWidth;
     private int displayHeight;
     private PopupWindow popupWindow;
     private int selectPosition;
 
     public ExpandTabView(Context context) {
         super (context);
         init(context);
     }
 
     public ExpandTabView(Context context, AttributeSet attrs) {
         super (context, attrs);
         init(context);
     }
 
     /**
      * 根据选择的位置设置tabitem显示的值
      */
     public void setTitle(String valueText, int position) {
         if (position < mToggleButton.size()) {
             mToggleButton.get(position).setText(valueText);
         }
     }
 
     public void setTitle(String title){
         
     }
     /**
      * 根据选择的位置获取tabitem显示的值
      */
     public String getTitle( int position) {
         if (position < mToggleButton.size() && mToggleButton.get(position).getText() != null ) {
             return mToggleButton.get(position).getText().toString();
         }
         return "" ;
     }
 
     /**
      * 设置tabitem的个数和初始值
      * @param textArray 标题数组
      * @param viewArray 控件数组
      */
     public void setValue(ArrayList<string> textArray, ArrayList<view> viewArray) {
         if (mContext == null ) {
             return ;
         }
         LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         Log.d(TAG, "setValue" );
         mTextArray = textArray;
         for ( int i = 0 ; i < viewArray.size(); i++) {
             final RelativeLayout r = new RelativeLayout(mContext);
             int maxHeight = ( int ) (displayHeight * 0.7 );
             RelativeLayout.LayoutParams rl = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, maxHeight);
             rl.leftMargin = 10 ;
             rl.rightMargin = 10 ;
             r.addView(viewArray.get(i), rl);
             mViewArray.add(r);
             r.setTag(SMALL);
             ToggleButton tButton = (ToggleButton) inflater.inflate(R.layout.toggle_button, this , false );
             addView(tButton);
             View line = new TextView(mContext);
             line.setBackgroundResource(R.drawable.choosebar_line);
             if (i < viewArray.size() - 1 ) {
                 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( 2 , LinearLayout.LayoutParams.MATCH_PARENT);
                 addView(line, lp);
             }
             mToggleButton.add(tButton);
             tButton.setTag(i);
             tButton.setText(mTextArray.get(i));
 
             r.setOnClickListener( new OnClickListener() {
                 @Override
                 public void onClick(View v) {
                     Log.d( "RelativeLayout" , "view:" +v);
                     onPressBack();
                 }
             });
 
             r.setBackgroundColor(mContext.getResources().getColor(R.color.popup_main_background));
             tButton.setOnClickListener( new OnClickListener() {
                 @Override
                 public void onClick(View view) {
                     Log.d( "tButton" , "setOnClickListener(l)" );
                     // initPopupWindow();
                     ToggleButton tButton = (ToggleButton) view;
 
                     if (selectedButton != null && selectedButton != tButton) {
                         selectedButton.setChecked( false );
                     }
                     selectedButton = tButton;
                     selectPosition = (Integer) selectedButton.getTag();
                     startAnimation();
                     if (mOnButtonClickListener != null && tButton.isChecked()) {
                         mOnButtonClickListener.onClick(selectPosition);
                     }
                 }
             });
         } // for..
     }
 
     private void startAnimation() {
         Log.d(TAG, "startAnimation" );
         if (popupWindow == null ) {
             Log.d(TAG, "startAnimation(),new popupWindow now" );
             popupWindow = new PopupWindow(mViewArray.get(selectPosition), displayWidth, displayHeight);
             popupWindow.setAnimationStyle(R.style.PopupWindowAnimation);
             popupWindow.setFocusable( false );
             popupWindow.setOutsideTouchable( true );
         }
         Log.d(TAG, "startAnimation(),selectedButton:" +selectedButton+ ",isChecked:" +selectedButton.isChecked()+
                 ",popupWindow.isShowing:" +popupWindow.isShowing());
         if (selectedButton.isChecked()) {
             
             if (!popupWindow.isShowing()) {
                 showPopup(selectPosition);
             } else {
                 popupWindow.setOnDismissListener( this );
                 popupWindow.dismiss();
                 hideView();
             }
         } else {
             if (popupWindow.isShowing()) {
                 popupWindow.dismiss();
                 hideView();
             }
         }
     }
 
     private void showPopup( int position) {
         View tView = mViewArray.get(selectPosition).getChildAt( 0 );
         if (tView instanceof ViewBaseAction) {
             ViewBaseAction f = (ViewBaseAction) tView;
             f.show();
         }
         if (popupWindow.getContentView() != mViewArray.get(position)) {
             popupWindow.setContentView(mViewArray.get(position));
         }
         popupWindow.showAsDropDown( this , 0 , 0 );
     }
 
     /**
      * 如果菜单成展开状态,则让菜单收回去
      */
     public boolean onPressBack() {
         Log.d(TAG, "onPressBack" );
         if (popupWindow != null && popupWindow.isShowing()) {
             popupWindow.dismiss();
             hideView();
             if (selectedButton != null ) {
                 selectedButton.setChecked( false );
             }
             return true ;
         } else {
             return false ;
         }
 
     }
 
     private void hideView() {
         Log.d(TAG, "hide()" );
         View tView = mViewArray.get(selectPosition).getChildAt( 0 );
         if (tView instanceof ViewBaseAction) {
             ViewBaseAction f = (ViewBaseAction) tView;
             f.hide();
         }
     }
 
     private void init(Context context) {
         mContext = context;
         displayWidth = ((Activity) mContext).getWindowManager().getDefaultDisplay().getWidth();
         displayHeight = ((Activity) mContext).getWindowManager().getDefaultDisplay().getHeight();
         setOrientation(LinearLayout.HORIZONTAL);
     }
 
     @Override
     public void onDismiss() {
         Log.d(TAG, "onDismiss,selectPosition:" +selectPosition);
         showPopup(selectPosition);
         popupWindow.setOnDismissListener( null );
     }
 
     private OnButtonClickListener mOnButtonClickListener;
 
     /**
      * 设置tabitem的点击监听事件
      */
     public void setOnButtonClickListener(OnButtonClickListener l) {
         mOnButtonClickListener = l;
     }
 
     /**
      * 自定义tabitem点击回调接口
      */
     public interface OnButtonClickListener {
         public void onClick( int selectPosition);
     }
 
}
</view></string></togglebutton></togglebutton></relativelayout></relativelayout></string></string>


5,ViewLeft

其中的一个示例,其他两个就不列举了

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package com.example.view;
 
 
import com.example.adapter.TextAdapter;
import com.example.expandtabview.R;
 
 
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Toast;
 
 
 
 
public class ViewLeft extends RelativeLayout implements ViewBaseAction{
     private static final String TAG = "ViewLeft" ;
     private ListView mListView;
     private final String[] items = new String[] { "item1" , "item2" , "item3" , "item4" , "item5" , "item6" }; //显示字段
     private final String[] itemsVaule = new String[] { "1" , "2" , "3" , "4" , "5" , "6" }; //隐藏id
     private OnSelectListener mOnSelectListener;
     private TextAdapter adapter;
     private String mDistance;
     private String showText = "item1" ;
     private Context mContext;
 
 
     public String getShowText() {
         return showText;
     }
 
 
     public ViewLeft(Context context) {
         super (context);
         init(context);
     }
 
 
     public ViewLeft(Context context, AttributeSet attrs, int defStyle) {
         super (context, attrs, defStyle);
         init(context);
     }
 
 
     public ViewLeft(Context context, AttributeSet attrs) {
         super (context, attrs);
         init(context);
     }
 
 
     private void init(Context context) {
         mContext = context;
         LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         inflater.inflate(R.layout.view_distance, this , true );
         setBackgroundDrawable(getResources().getDrawable(R.drawable.choosearea_bg_mid));
         mListView = (ListView) findViewById(R.id.listView);
         adapter = new TextAdapter(context, items, R.drawable.choose_item_right, R.drawable.choose_eara_item_selector);
         adapter.setTextSize( 17 );
         if (mDistance != null ) {
             for ( int i = 0 ; i < itemsVaule.length; i++) {
                 if (itemsVaule[i].equals(mDistance)) {
                     adapter.setSelectedPositionNoNotify(i);
                     showText = items[i];
                     break ;
                 }
             }
         }
         mListView.setAdapter(adapter);
         adapter.setOnItemClickListener( new TextAdapter.OnItemClickListener() {
 
 
             @Override
             public void onItemClick(View view, int position) {
 
 
                 if (mOnSelectListener != null ) {
                     showText = items[position];
                     mOnSelectListener.getValue(itemsVaule[position], items[position]);
                 }
             }
         });
     }
 
 
     public void setOnSelectListener(OnSelectListener onSelectListener) {
         mOnSelectListener = onSelectListener;
     }
 
 
     public interface OnSelectListener {
         public void getValue(String distance, String showText);
     }
 
 
     @Override
     public void hide() {
         
     }
 
 
     @Override
     public void show() {
         
     }
 
 
}

6,效果图

\

\

\


好,今天就到这里。。希望有用。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值