Android仿美团淘宝实现多级下拉列表菜单功能

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

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

1.结构分析

首先,我们给出这个下拉菜单需要的组建。我们用线框图来分析。

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

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

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

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

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

2.项目结构

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

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

2)MainActivity。主活动页面。

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

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

3.MainActivity

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

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("区域");
    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();
    }
  }
} 

4 .ExpandTabView

最主要就是如何处理当我们点击这些ToggleButton的时候要弹出或者收起这些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;
/**
 * 菜单控件头部,封装了下拉动画,动态生成头部按钮个数
 *
 * @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);
  }
  /**
   * 根据选择的位置设置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 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);
  }
  /**
   * 如果菜单成展开状态,则让菜单收回去
   */
  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);
  }
} 

5.ViewLeft

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

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仿美团淘宝实现多级下拉列表菜单功能,多条目的实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

时间: 2017-01-11

Android仿美团下拉菜单(商品选购)实例代码

美团电商应用平台大家使用非常频繁,下面小编通过本文给大家介绍电商应用平台中常用的选择类别下拉列表的实现.先给大家展示下效果图: 一.下拉列表的实现 其实实现方法有很多,这时实现的也没有什么技术含量,只是总结下自己在项目中的做法,也提供一个思路. 首先是列表的数据,一般数据都是从后台读过来,这里因为没有后台,所以写死在客户端: private void initMenuData() { menuData = new ArrayList<map<string, string=""

Android模仿美团顶部的滑动菜单实例代码

前言 本文主要给大家介绍了关于Android模仿美团顶部滑动菜单的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 先来看下效果图: 实现方法 这是通过 ViewPager 和 GridView 相结合做出来的效果,每一个 ViewPager 页面都是一个 GridView,底部的每个滑动指示圆点都是从布局文件中 inflate 出来的 首先需要一个代表每个活动主题的 JavaBean /** * Created by CZY on 2017/6/23. */ publ

Android仿美团分类下拉菜单实例代码

本文实例为大家分享了Android仿美团下拉菜单的实现代码,分类进行选择,供大家参考,具体内容如下 效果图 操作平台 AS2.0 第三方框架:butterknife build.gradle dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.4.0' compile

Android编程实现仿美团或淘宝的多级分类菜单效果示例【附demo源码下载】

本文实例讲述了Android编程实现仿美团或淘宝的多级分类菜单效果.分享给大家供大家参考,具体如下: 这里要实现的是诸如美团/淘宝/百度糯米 多级分类菜单效果.当分类数量非常多时可以考虑采用两级分类,而诸如美团这种表现方式是一个不错的选择. 首先上效果图:   主要代码: 1. PopupWindow初始化过程: popupWindow = new PopupWindow(this); View view = LayoutInflater.from(this).inflate(R.layout.

Android开发之自定义view实现通讯录列表A~Z字母提示效果【附demo源码下载】

本文实例讲述了Android开发之自定义view实现通讯录列表A~Z字母提示效果.分享给大家供大家参考,具体如下: 开发工具:eclipse 运行环境:htc G9 android2.3.3 话不多说,先看效果图 其实左右边的A~Z是一个自定义的View,它直接覆盖在ListView上. MyLetterListView: public class MyLetterListView extends View { OnTouchingLetterChangedListener onTouching

Android编程实现仿QQ发表说说,上传照片及弹出框效果【附demo源码下载】

本文实例讲述了Android编程实现仿QQ发表说说,上传照片及弹出框效果.分享给大家供大家参考,具体如下: 代码很简单,主要就是几个动画而已,图标什么的就随便找了几个,效果图:   动画说明: 1.点击右上角按钮,菜单从顶部下拉弹出,同时背景变暗; 2.再次点击右上角按钮,点击返回键,或者点击空白区域(也就是变暗的部分),菜单向上收回; 3.点击菜单上的按钮响应事件,同时菜单收回(效果同2) 重要说明:动画结束后必须clearAnimation,否则隐藏状态的view依然能响应点击事件 主体代码

Android编程实现仿易信精美弹出框效果【附demo源码下载】

本文实例讲述了Android编程实现仿易信精美弹出框效果.分享给大家供大家参考,具体如下: 截图: 动画效果介绍: 1.点击ActionBar上"+"按钮,菜单从上方弹出(带反弹效果): 2.再次点击"+".点击空白区域或者点击返回键,菜单向上方收起: 3.点击弹出框上的按钮时,该按钮放大,其它按钮缩小,菜单整体渐变退出. 主体代码: 1.Activity. /** * 仿易信动画弹出框 */ public class MainActivity extends Ac

Android仿zaker用手向上推动的特效开发【推动门效果】(附demo源码下载)

本文实例讲述了Android仿zaker用手向上推动的特效开发.分享给大家供大家参考,具体如下: 最近在商店下载了zaker ,闲暇时拿来看看新闻!发现每次打开软件进入主界面时有个界面,需要你把它往上滑到一定距离才能进入到主界面.每次进入软件时它的背景可能不一样,在往上拨的时候你会看见主界面,好似向上推的门一样!打开它你就可以看到外面的世界.与窗帘有点不同的是在你没有拉开足够距离时,它会俏皮的关闭自己不让你看到外面的美景. 说这么多想像起来挺模糊的,那让我们看看实际效果图,我现在打开zaker截

Android编程实现带有图标的ListView并带有长按菜单效果示例

本文实例讲述了Android编程实现带有图标的ListView并带有长按菜单效果.分享给大家供大家参考,具体如下: MainActivity.Java package com.zxl; import java.util.ArrayList; import java.util.List; import org.w3c.dom.ls.LSException; import android.app.Activity; import android.os.Bundle; import android.v

Android编程实现仿优酷圆盘旋转菜单效果的方法详解【附demo源码下载】

本文实例讲述了Android编程实现仿优酷圆盘旋转菜单效果的方法.分享给大家供大家参考,具体如下: 目前,用户对安卓应用程序的UI设计要求越来越高,因此,掌握一些新颖的设计很有必要. 比如菜单,传统的菜单已经不能满足用户的需求. 其中优酷中圆盘旋转菜单的实现就比较优秀,这里我提供下我的思路及实现,仅供参考. 该菜单共分里外三层导航菜单.可以依次从外向里关闭三层菜单,也可以反向打开,并且伴有圆盘旋转的动画效果 首先,看下效果: 以下是具体的代码及解释: 1. 菜单布局文件: 大家看到主要有三个Ra

Android编程实现TextView垂直自动滚动功能【附demo源码下载】

本文实例讲述了Android编程实现TextView垂直自动滚动功能.分享给大家供大家参考,具体如下: 在做android 应用的开发的时候,横向滚动或者要做出跑马灯的效果很简单,textview本身的属性就支持,只要设置准确就会滚动,开发起来比较简单,但是textview 不支持垂直滚动,那么垂直滚动就需要自己来实现了,很多网友提供的垂直滚 动方案都是千篇一律,使用ScrollView来进行滚动,但是都不完美,做起来有些别扭.有一位网友给出的歌词的滚动思路明确,能从根本上解决问题,因此我实现的

Android编程实现录音及保存播放功能的方法【附demo源码下载】

本文实例讲述了Android编程实现录音及保存播放功能的方法.分享给大家供大家参考,具体如下: 在android中进行录音相对来说是比较简单的,使用系统提供的MediaRecorder类进行录音并保存,然后调用MediaPlayer进行播放.以下为xml配置文件代码: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas

原生JavaScript实现精美的淘宝轮播图效果示例【附demo源码下载】

本文实例讲述了原生JavaScript实现的淘宝轮播图效果.分享给大家供大家参考,具体如下: 轮播图是我们学习原生js的必经之路 它包含很多基本知识的运用,像this的使用,DOM的操作,还有setInterval的使用和清除,浮动与定位等等,很好的考察了我们的基础知识牢不牢固, 话不多说,直接上图 HTML代码如下: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF