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

(0)

相关推荐

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

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

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

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

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

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

  • 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仿美团淘宝实现多级下拉列表菜单功能

    我们在常用的电商或者旅游APP中,例如美团,手机淘宝等等,都能够看的到有那种下拉式的二级列表菜单.具体如图所示: 上面两张图就是美团的一个二级列表菜单的一个展示.我相信很多人都想开发一个跟它一样的功能放到自己的APP中.好,接下来我们就开始动手,解决它. 1.结构分析 首先,我们给出这个下拉菜单需要的组建.我们用线框图来分析. 1)如上图所示,最外围的是一个Activity,顶部包含了一个View的容器,这个容器主要是装载ToggleButton来实现诸如美团里面的"美食,全城,理我最近,刷选&

  • Android仿京东淘宝自动无限循环轮播控件思路详解

    在App的开发中,很多的时候都需要实现类似京东淘宝一样的自动无限轮播的广告栏,所以就自己写了一个,下面是我自定义控件的思路和过程. 一.自定义控件属性 新建自定义控件SliderLayout继承于RelativeLayout,首先要考虑的就是自定义的控件需要扩展那些属性,把这些属性列出来.在这里是要实现类似于京东淘宝的无限轮播广告栏,那么首先想到的就是轮播的时长.轮播指示器的样式等等.我在这里列举了一些并且结合到了代码中. 1.扩展属性 (1)是否开启自动轮播的功能. (2)指示器的图形样式,一

  • Android中使用TextView实现高仿京东淘宝各种倒计时效果

    今天给大家带来的是仅仅使用一个TextView实现一个高仿京东.淘宝.唯品会等各种电商APP的活动倒计时.最近公司一直加班也没来得及时间去整理,今天难得休息想把这个分享给大家,只求共同学习,以及自己后续的复习.为什么会想到使用一个TextView来实现呢?因为最近公司在做一些优化的工作,其中就有一个倒计时样式,原来开发的这个控件的同事使用了多个TextView拼接在一起的,实现的代码冗余比较大,故此项目经理就说:小宏这个就交给你来优化了,并且还要保证有一定的扩展性,当时就懵逼了.不知道从何处开始

  • Android中实现淘宝购物车RecyclerView或LIstView的嵌套选择的逻辑

    使用了RecyclerView嵌套RecyclerView的方案. 购物车的第一个界面为RecyclerView,每个Item里面包含一个店铺.在Item中使用RecyclerView包含店铺和店铺的多个商品. 实现思路: 使用接口回调将第二个adapter的商品选择的监听事件回调给第一个adapter后再在第一个adapter中回调给MainActivity. 使用接口回调将第一个adapter的商品选择的监听事件回调给MainActivity. 在MainActivity中处理第一个adap

  • Android项目类似淘宝 电商 搜索功能,监听软键盘搜索事件,延迟自动搜索,以及时间排序的搜索历史记录的实现

    最近跳槽去新公司,接受的第一个任务是在 一个电商模块的搜索功能以及搜索历史记录的实现. 需求和淘宝等电商的功能大体差不多,最上面一个搜索框,下面显示搜索历史记录.在EditText里输入要搜索的关键字后,按软键盘的搜索按键/延迟xxxxms后自动搜索.然后将搜索的内容展示给用户/提示用户没有搜到相关信息. 历史记录是按时间排序的,最新的在前面,输入以前搜索过的关键字,例如牛仔裤(本来是第二条),会更新这条记录的时间,下次再看,牛仔裤的排列就在第一位了.并且有清除历史记录的功能. 整理需求,大致需

  • 原生JS实现仿淘宝网左侧商品分类菜单效果代码

    本文实例讲述了原生JS实现仿淘宝网左侧商品分类菜单效果代码.分享给大家供大家参考.具体如下: 这是一款原生JS实现的仿淘宝网左侧商品分类菜单效果代码,JavaScript技术实现,兼容各主流浏览器.自己再修改一下CSS菜单,它会变得更漂亮. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-f-taobao-pro-menu-style-codes/ 具体代码如下: <!DOCTYPE html> <head> <titl

  • Android仿QQ长按删除弹出框功能示例

    废话不说,先看一下效果图,如果大家感觉不错,请参考实现代码: 对于列表来说,如果想操作某个列表项,一般会采用长按弹出菜单的形式,默认的上下文菜单比较难看,而QQ的上下文菜单就人性化多了,整个菜单给用户一种气泡弹出的感觉,而且会显示在手指按下的位置,而技术实现我之前是使用popupWindow和RecyclerView实现的,上面一个RecyclerView,下面一个小箭头ImageView,但后来发现没有必要,而且可定制化也不高,还是使用多个TextView更好一点. 我封装了一下,只需要一个P

随机推荐