Android仿美團(tuán)淘寶實(shí)現(xiàn)多級(jí)下拉列表菜單功能
我們?cè)诔S玫碾娚袒蛘呗糜蜛PP中,例如美團(tuán),手機(jī)淘寶等等,都能夠看的到有那種下拉式的二級(jí)列表菜單。具體如圖所示:
上面兩張圖就是美團(tuán)的一個(gè)二級(jí)列表菜單的一個(gè)展示。我相信很多人都想開(kāi)發(fā)一個(gè)跟它一樣的功能放到自己的APP中。好,接下來(lái)我們就開(kāi)始動(dòng)手,解決它。
1.結(jié)構(gòu)分析
首先,我們給出這個(gè)下拉菜單需要的組建。我們用線框圖來(lái)分析。
1)如上圖所示,最外圍的是一個(gè)Activity,頂部包含了一個(gè)View的容器,這個(gè)容器主要是裝載ToggleButton來(lái)實(shí)現(xiàn)諸如美團(tuán)里面的“美食,全城,理我最近,刷選”這一行。這一行一點(diǎn)就會(huì)彈出對(duì)應(yīng)的下來(lái)菜單。
2)下拉菜單是如何實(shí)現(xiàn)的呢?,這里我們利用了PopupWindow來(lái)實(shí)現(xiàn)這一彈出式窗口。然后我們?cè)趶棾鍪酱翱诶锩嬖俣x我們的下來(lái)列表項(xiàng),是單列還是二級(jí)菜單,都是由里面來(lái)定。
3)不同的菜單,需要一級(jí)或者需要二級(jí),在這里根據(jù)我的需求而變動(dòng)。我們?cè)赑opupWindow上面加一個(gè)自定義的LeftView,或者是MiddleView,RightView。主要是一個(gè)ToggleButton,你彈出一個(gè)窗口,你就定制一個(gè)窗口。
4)視圖里面嵌入ListView,就形成了列表項(xiàng)。
好分析就到上面為止,接下來(lái)我們一步步的說(shuō)明實(shí)現(xiàn)。
2.項(xiàng)目結(jié)構(gòu)
本項(xiàng)目的項(xiàng)目結(jié)構(gòu)如圖所示:
1) Adapter。適配器,主要是為L(zhǎng)istView提供數(shù)據(jù)適配的。
2)MainActivity。主活動(dòng)頁(yè)面。
3)ExpandTabView。本項(xiàng)目的核心類(lèi),它包含ToggleButton容器和PopupWindow,是控制彈出窗口的核心類(lèi)。
4)ViewLeft,ViewMiddle,ViewRight。是彈出里面嵌套的類(lèi),實(shí)現(xiàn)不同的列表菜單。
3.MainActivity
承載所有元素??创a比看文字實(shí)在。
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 mViewArray = new ArrayList();
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 mTextArray = new ArrayList();
mTextArray.add("距離");
mTextArray.add("區(qū)域");
mTextArray.add("距離");
expandTabView.setValue(mTextArray, mViewArray);//將三個(gè)下拉列表設(shè)置進(jìn)去
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();
}
}
}
4 .ExpandTabView
最主要就是如何處理當(dāng)我們點(diǎn)擊這些ToggleButton的時(shí)候要彈出或者收起這些PopupWindow。
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;
/**
* 菜單控件頭部,封裝了下拉動(dòng)畫(huà),動(dòng)態(tài)生成頭部按鈕個(gè)數(shù)
*
* @author zengjinlong
*/
public class ExpandTabView extends LinearLayout implements OnDismissListener {
private static final String TAG = "ExpandTabView";
private ToggleButton selectedButton;
private ArrayList mTextArray = new ArrayList();
private ArrayList mViewArray = new ArrayList();
private ArrayList mToggleButton = new ArrayList();
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);
}
/**
* 根據(jù)選擇的位置設(shè)置tabitem顯示的值
*/
public void setTitle(String valueText, int position) {
if (position < mToggleButton.size()) {
mToggleButton.get(position).setText(valueText);
}
}
public void setTitle(String title){
}
/**
* 根據(jù)選擇的位置獲取tabitem顯示的值
*/
public String getTitle(int position) {
if (position < mToggleButton.size() && mToggleButton.get(position).getText() != null) {
return mToggleButton.get(position).getText().toString();
}
return "";
}
/**
* 設(shè)置tabitem的個(gè)數(shù)和初始值
* @param textArray 標(biāo)題數(shù)組
* @param viewArray 控件數(shù)組
*/
public void setValue(ArrayList textArray, ArrayList 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);
}
/**
* 如果菜單成展開(kāi)狀態(tài),則讓菜單收回去
*/
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;
/**
* 設(shè)置tabitem的點(diǎn)擊監(jiān)聽(tīng)事件
*/
public void setOnButtonClickListener(OnButtonClickListener l) {
mOnButtonClickListener = l;
}
/**
* 自定義tabitem點(diǎn)擊回調(diào)接口
*/
public interface OnButtonClickListener {
public void onClick(int selectPosition);
}
}
5.ViewLeft
其中的一個(gè)示例,其他兩個(gè)就不列舉了
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.效果圖

以上所述是小編給大家介紹的Android仿美團(tuán)淘寶實(shí)現(xiàn)多級(jí)下拉列表菜單功能,多條目的實(shí)例代碼,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Android實(shí)現(xiàn)聯(lián)動(dòng)下拉框 下拉列表spinner的實(shí)例代碼
- Android UI組件Spinner下拉列表詳解
- Android下拉列表選項(xiàng)框及指示箭頭動(dòng)畫(huà)
- Android自定義Spinner下拉列表(使用ArrayAdapter和自定義Adapter實(shí)現(xiàn))
- Android控件Spinner實(shí)現(xiàn)下拉列表及監(jiān)聽(tīng)功能
- Android仿微信實(shí)現(xiàn)下拉列表
- Android自定義單選多選下拉列表的實(shí)例代碼
- Android使用Spinner控件實(shí)現(xiàn)下拉列表的案例
- Android下拉列表spinner的實(shí)例代碼
- Android Studio實(shí)現(xiàn)下拉列表效果
相關(guān)文章
Android Fragment多層嵌套重影問(wèn)題的解決方法
這篇文章主要介紹了Android Fragment多層嵌套重影問(wèn)題的解決方法,從解決bug的思想,導(dǎo)致原因,原理解析等方面找出問(wèn)題所在原因,最終解決方法就可以簡(jiǎn)單了,對(duì)fragment 多層嵌套問(wèn)題感興趣的朋友一起通過(guò)本文學(xué)習(xí)吧2016-08-08
Android之Viewpager+Fragment實(shí)現(xiàn)懶加載示例
本篇文章主要介紹了Android之Viewpager+Fragment實(shí)現(xiàn)懶加載示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03
Android 性能優(yōu)化系列之bitmap圖片優(yōu)化
在日常開(kāi)發(fā)的APP,大部分時(shí)候需要想用戶展示圖片信息,圖片最終對(duì)應(yīng)Android中的Bitmap對(duì)象。而對(duì)于APP端來(lái)說(shuō)Bitmap又是一個(gè)比較麻煩的問(wèn)題,主要表現(xiàn)在Bitmap是非常占用內(nèi)存的對(duì)象,處理不當(dāng)將導(dǎo)致APP運(yùn)行卡頓甚至出現(xiàn)OOM2021-11-11
WebView設(shè)置WebViewClient的方法
這篇文章主要介紹了 WebView設(shè)置WebViewClient的方法的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-09-09
Android實(shí)現(xiàn)圖片自動(dòng)切換功能(實(shí)例代碼詳解)
這篇文章主要介紹了Android實(shí)現(xiàn)圖片自動(dòng)切換功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
Android通過(guò)JNI實(shí)現(xiàn)守護(hù)進(jìn)程
這篇文章主要為大家詳細(xì)介紹了Android通過(guò)JNI實(shí)現(xiàn)守護(hù)進(jìn)程的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-09-09
Mac中配置gradle環(huán)境及使用android studio打包jar包與arr包的方法
這篇文章主要給大家介紹了關(guān)于在Mac中配置gradle環(huán)境,以及使用android studio打包jar包與arr包的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01
Android開(kāi)發(fā)中通過(guò)手機(jī)號(hào)+短信驗(yàn)證碼登錄的實(shí)例代碼
最近在開(kāi)發(fā)一個(gè)android的項(xiàng)目,需要通過(guò)獲取手機(jī)驗(yàn)證碼來(lái)完成登錄功能,接下來(lái)通過(guò)實(shí)例代碼給大家分享手機(jī)號(hào)+短信驗(yàn)證碼登錄的實(shí)現(xiàn)方法,需要的的朋友參考下吧2017-05-05

