仿美团分类菜单+自动弹出收起底部栏

先看应用中的效果图:

demo的效果图:

这里是使用了仿美团的分类列表加上SlideBottomLayout来实现底部名片的自动弹出跟收起功能的。

实现流程:

1.添加SlideBottomLayout依赖

//自定义底部上拉控件
    implementation 'com.github.qingmei2:SlideBottomLayout-Android:1.2.3'
//recyclerview
    implementation 'com.android.support:recyclerview-v7:27.1.1'

2.布局文件

(1)MainActivity的布局文件

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >


    <com.qingmei2.library.SlideBottomLayout
        android:id="@+id/sbl_bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:handler_height="35dp"
        android:layout_gravity="bottom"
        android:layout_marginLeft="-10dp"
        android:layout_marginRight="-10dp"
        android:visibility="gone"

        >



        <LinearLayout
            android:id="@+id/ll_sbl_bottom"
            android:layout_width="match_parent"
            android:layout_height="120dp"
            android:orientation="vertical"
            android:layout_gravity="center_horizontal"
            android:background="@mipmap/sbl_bottom_bg"
            >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="底部栏"
                android:textSize="14sp"
                android:textColor="@color/colorAccent"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="14dp"
                android:textStyle="bold"

                />

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="80dp"
                android:background="#FFFFFF"
                android:layout_marginTop="5dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp">

                <android.support.v4.view.ViewPager
                    android:id="@+id/recycle_home_entrance_vp"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>

                <LinearLayout
                    android:id="@+id/recycle_ll_dot"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true"
                    android:layout_marginBottom="8dp"
                    android:gravity="center"
                    android:orientation="horizontal" />
            </RelativeLayout>


        </LinearLayout>






    </com.qingmei2.library.SlideBottomLayout>

</FrameLayout>

(2)item_home_entrance的布局文件

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:paddingBottom="5dp">

        <ImageView
            android:id="@+id/entrance_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="2dp"
            android:scaleType="fitCenter" />

        <TextView
            android:id="@+id/entrance_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="2dp"
            android:singleLine="true"
            android:textColor="#80000000"
            android:textSize="12dp" />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>

(3)item_home_entrance_vp的布局文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

(4)dot 小圆点指示器的布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <!-- 小圆点View -->
    <View
        android:id="@+id/v_dot"
        android:layout_width="8dp"
        android:layout_height="8dp"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="2dp"
        android:background="@drawable/dot_normal"/>
</RelativeLayout>

(5)小圆点的正常态跟选中态的drawable文件

dot_normal:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <corners android:radius="8dp" />
    <solid android:color="#D4D3D3" />
</shape>

dot_selected:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/colorPrimary" />
    <corners android:radius="8dp" />
</shape>

3.MainActvivty

package zy.xda.dibumingpian;

import android.os.Handler;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.qingmei2.library.SlideBottomLayout;

import java.util.ArrayList;
import java.util.List;

import zy.xda.dibumingpian.adapter.EntranceAdapter;
import zy.xda.dibumingpian.model.ModelHomeEntrance;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    SlideBottomLayout sbl_bottom;
    boolean isShow;

    LinearLayout ll_sbl_bottom;
    ViewPager entranceViewPager;
    LinearLayout mLlDot;

    public static final int HOME_ENTRANCE_PAGE_SIZE = 3;//首页菜单单页显示数量
    private int pageCount;//总页数
    private int curIndex = 0;//当前显示的事第几页
    private List<ModelHomeEntrance> homeEntrances;
    private LayoutInflater inflater;
    EntranceAdapter entranceAdapter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        entranceViewPager = findViewById(R.id.recycle_home_entrance_vp);
        mLlDot = findViewById(R.id.recycle_ll_dot);
        ll_sbl_bottom = findViewById(R.id.ll_sbl_bottom);
        ll_sbl_bottom.setOnClickListener(this);
        sbl_bottom = findViewById(R.id.sbl_bottom);
        sbl_bottom.setVisibility(View.VISIBLE);
        sbl_bottom.show();
        showMingPian();

        initData();
        init();
    }



    public void showMingPian(){
        Handler handler = new Handler();
        Handler handler2 = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                sbl_bottom.show();
                isShow = true;
            }
        }, 1000);

        handler2.postDelayed(new Runnable() {
            @Override
            public void run() {
                sbl_bottom.hide();
                isShow = false;
            }
        }, 5000);

    }

    
    //假数据
    private void initData() {
        homeEntrances = new ArrayList<>();
        homeEntrances.add(new ModelHomeEntrance("美食", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("电影", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("酒店住宿", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("生活服务", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("KTV", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("旅游", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("学习培训", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("汽车服务", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("摄影写真", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("休闲娱乐", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("丽人", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("运动健身", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("大保健", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("团购", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("景点", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("全部分类", R.mipmap.ic_launcher));

        homeEntrances.add(new ModelHomeEntrance("美食", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("电影", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("酒店住宿", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("生活服务", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("KTV", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("旅游", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("学习培训", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("汽车服务", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("摄影写真", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("休闲娱乐", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("丽人", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("运动健身", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("大保健", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("团购", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("景点", R.mipmap.ic_launcher));
        homeEntrances.add(new ModelHomeEntrance("全部分类", R.mipmap.ic_launcher));
    }

    private void init() {
        //首页菜单分页
        inflater = LayoutInflater.from(this);
        //将RecyclerView放至ViewPager中:
        int pageSize = HOME_ENTRANCE_PAGE_SIZE;
        //一共的页数等于 总数/每页数量,并取整。
        pageCount = (int) Math.ceil(homeEntrances.size() * 1.0 / pageSize);
        List<View> viewList = new ArrayList<View>();
        for (int index = 0; index < pageCount; index++) {
            //每个页面都是inflate出一个新实例
            RecyclerView recyclerView = (RecyclerView) inflater.inflate(R.layout.item_home_entrance_vp, entranceViewPager, false);
            recyclerView.setLayoutManager(new GridLayoutManager(MainActivity.this, 3){
                @Override
                public boolean canScrollVertically() {
                    return false;
                }
            });
            entranceAdapter = new EntranceAdapter(MainActivity.this, homeEntrances, index, HOME_ENTRANCE_PAGE_SIZE);
            recyclerView.setAdapter(entranceAdapter);
            viewList.add(recyclerView);
            entranceAdapter.setOnItemClickListener(new EntranceAdapter.OnItemClick(){
                @Override
                public void onItemListener(int position){
                    Toast.makeText(MainActivity.this,homeEntrances.get(position).getName(),Toast.LENGTH_SHORT).show();
                }
            });

        }

        CagegoryViewPagerAdapter adapter = new CagegoryViewPagerAdapter(viewList);
        entranceViewPager.setAdapter(adapter);
        //设置小圆点
        setOvalLayout();
    }

    private void setOvalLayout() {
        for (int i = 0; i < pageCount; i++) {
            mLlDot.addView(inflater.inflate(R.layout.dot, null));
        }
        //默认显示第一页
        mLlDot.getChildAt(0).findViewById(R.id.v_dot).setBackgroundResource(R.drawable.dot_selected);
        entranceViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                //取消选中
                mLlDot.getChildAt(curIndex).findViewById(R.id.v_dot).setBackgroundResource(R.drawable.dot_normal);
                //选中
                mLlDot.getChildAt(position).findViewById(R.id.v_dot).setBackgroundResource(R.drawable.dot_selected);

                curIndex = position;

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.ll_sbl_bottom:
                if(isShow){
                    sbl_bottom.hide();
                    isShow = false;
                }else{
                    isShow = true;
                    sbl_bottom.show();
                }
                break;
        }

    }
}

4.仿美团分类菜单的Adapter

package zy.xda.dibumingpian.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;


import java.util.List;

import zy.xda.dibumingpian.R;
import zy.xda.dibumingpian.model.ModelHomeEntrance;

/**
 * Created by haoxuhong on 2019/1/14.
 *
 * @description:
 */
public class EntranceAdapter extends RecyclerView.Adapter<EntranceAdapter.EntranceViewHolder> {

    private List<ModelHomeEntrance> mDatas;

    /**
     * 页数下标,从0开始(通俗讲第几页)
     */
    private int mIndex;

    /**
     * 每页显示最大条目个数
     */
    private int mPageSize;

    private Context mContext;

    private final LayoutInflater mLayoutInflater;

    private List<ModelHomeEntrance> homeEntrances;

    public EntranceAdapter(Context context, List<ModelHomeEntrance> datas, int index, int pageSize) {
        this.mContext = context;
        this.homeEntrances = datas;
        mPageSize = pageSize;
        mDatas = datas;
        mIndex = index;
        mLayoutInflater = LayoutInflater.from(context);

    }

    @Override
    public EntranceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new EntranceViewHolder(mLayoutInflater.inflate(R.layout.item_home_entrance, null));
    }

    @Override
    public void onBindViewHolder(EntranceViewHolder holder, final int position) {
        /**
         * 在给View绑定显示的数据时,计算正确的position = position + mIndex * mPageSize,
         */
        final int pos = position + mIndex * mPageSize;
        holder.entranceNameTextView.setText(homeEntrances.get(pos).getName());
        holder.entranceIconImageView.setImageResource(homeEntrances.get(pos).getImage());
      

        if(mOnItemClick!=null){
            holder.itemView.setOnClickListener(new View.OnClickListener(){
                @Override
                public void onClick(View v){

                    mOnItemClick.onItemListener(pos);

                }
            });
        }

    }

    @Override
    public int getItemCount() {
        return mDatas.size() > (mIndex + 1) * mPageSize ? mPageSize : (mDatas.size() - mIndex * mPageSize);
    }

    @Override
    public long getItemId(int position) {
        return position + mIndex * mPageSize;
    }

    class EntranceViewHolder extends RecyclerView.ViewHolder {

        private TextView entranceNameTextView;
        private ImageView entranceIconImageView;

        public EntranceViewHolder(View itemView) {
            super(itemView);
            entranceIconImageView = (ImageView) itemView.findViewById(R.id.entrance_image);
            entranceNameTextView = (TextView) itemView.findViewById(R.id.entrance_name);
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (int) ((float) mContext.getResources().getDisplayMetrics().widthPixels / 4.0f));
            itemView.setLayoutParams(layoutParams);
        }
    }

    public OnItemClick mOnItemClick;

    public void setOnItemClickListener(OnItemClick onItemClick){
        this.mOnItemClick = onItemClick;
    }

    public interface OnItemClick{
        void onItemListener(int position);
    }

}

5.指示器小圆点的Adapter

package zy.xda.dibumingpian;


import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;

import java.util.List;

/**
 * Created by haoxuhong on 2019/1/14.
 *
 * @description: 首页分类ViewPager适配器
 */
class CagegoryViewPagerAdapter extends PagerAdapter {

    private List<View> mViewList;
    public CagegoryViewPagerAdapter(List<View> mViewList) {
        this.mViewList = mViewList;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(mViewList.get(position));
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        container.addView(mViewList.get(position));
        return (mViewList.get(position));
    }

    @Override
    public int getCount() {
        if (mViewList == null)
            return 0;
        return mViewList.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }
}

6.菜单的model类:

package zy.xda.dibumingpian.model;


/**
 * Created by haoxuhong on 2019/1/14.
 *
 * @description: 菜单项实体类
 */
public class ModelHomeEntrance {
	private String name = "";
	private int image;
	
	public ModelHomeEntrance(String name, int image) {
		this.image = image;
		this.name = name;
	}
	
	
	public int getImage() {
		return image;
	}
	
	public String getName() {
		return name;
	}
}

代码完成,demo效果图:

demo源码:https://download.csdn.net/download/qq_38306233/12685220

 

加个自动滑动的viewpager:



import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import java.util.List;

public class ScrollerViewpager extends ViewPager {

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 100002)
                setCurrentItem(getCurrentItem() + 1);
        }
    };

    //滚动的页面
    private List<View> views;

    //滚动的页面数量
    private int count;

    //自动滚动信号
    private final int SCROLL = 100002;

    //创建一个滚动线程
    private Thread thread;

    //间隔时间
    private int SPACE;

    //目前线程状态
    private boolean NORMAL = true;

    public ScrollerViewpager(@NonNull Context context) {
        super(context);
    }

    public ScrollerViewpager(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * 功能:初始化
     * @param views 视图组
     * @param space 间隔时间
     * @param listener 监听事件
     */
    public void init(List<View> views, final int space, final OnViewpagerChangeListener listener){
        this.views = views;
        this.count = views.size();
        this.SPACE = space;

        setAdapter(new MyAdapter());
        setCurrentItem(Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % views.size());

        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        NORMAL = true;
                        Thread.sleep(SPACE * 1000);
                        handler.sendEmptyMessage(SCROLL);
                    } catch (InterruptedException e) {
                        try {
                            NORMAL = false;
                            Thread.sleep(Integer.MAX_VALUE);
                        } catch (InterruptedException e1) { }
                    }
                }
            }
        });
        thread.start();

        addOnPageChangeListener(new OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                listener.onChange(position % count);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                if ((!NORMAL && state != 1) || (NORMAL && state == 1)){
                    thread.interrupt();
                }
            }
        });
    }

    public class MyAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return Integer.MAX_VALUE;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            int temp = position % count;
            View view = views.get(temp);
            if (view.getParent() == container) {
                container.removeView(view);
            }
            container.addView(view);
            return view;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
        }

        @Override
        public float getPageWidth(int position) {
//            return 0.9f;  设置显示控件的90%宽度
            return 1.0f;
        }
    }
}

使用:使用ScrollerViewpager替换原来的Viewpager,并在 init()方法中初始化ScrollerViewPager:

    entranceViewPager.init(viewList, 5, new OnViewpagerChangeListener() {
            @Override
            public void onChange(int currentPage) {

            }
        });

        /**
         * 通过反射来修改 ViewPager的mScroller属性
         * 修改viewpager的滑动速度
         */
        try {
            Class clazz=Class.forName("android.support.v4.view.ViewPager");
            Field f=clazz.getDeclaredField("mScroller");
            FixedSpeedScroller fixedSpeedScroller=new FixedSpeedScroller(getActivity(),new LinearOutSlowInInterpolator());
            fixedSpeedScroller.setmDuration(1200);//设置滑动速度 1.2s划完
            f.setAccessible(true);
            f.set(klineViewPager,fixedSpeedScroller);
        } catch (Exception e) {
            e.printStackTrace();
        }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值