Android仿京东、天猫app的商品详情页的布局架构, 以及功能实现

前言

电商内app,重点在于详情页商品展示,用户不仅要看到图,可以看到各种描述,以及相关规格参数。

有需要做电商类app的童鞋可以看看, 首先先看看效果实现

  • 本项目使用的第三方框架:
    • 加载网络图片使用的 Fresco
    • 头部的商品图轮播 ConvenientBanner
    • 导航栏切换 PagerSlidingTabStrip

先看看效果实现

Android仿京东、天猫app的商品详情页的布局架构, 以及功能实现

由于代码量过多, 就不一一讲解只介绍几个核心的自定义控件)

不想看的童鞋可以下载apk或者在github上下载源码使用

  • github地址
  • apk下载
  • 最外层的布局文件
<?xml version="1.0" encoding="utf-8"?> 


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 


    xmlns:app="http://schemas.android.com/apk/res-auto" 


    xmlns:tools="http://schemas.android.com/tools" 


    android:layout_width="match_parent" 


    android:layout_height="match_parent" 


    android:orientation="vertical"> 


     <!-- 顶部标题 --> 


    <LinearLayout 


        android:id="@+id/ll_title_root" 


        android:layout_width="match_parent" 


        android:layout_height="wrap_content" 


        android:background="#ec0f38" 


        android:orientation="vertical"> 


 


        <LinearLayout 


            android:layout_width="match_parent" 


            android:layout_height="44dp" 


            android:orientation="horizontal"> 


 


            <LinearLayout 


                android:id="@+id/ll_back" 


                android:layout_width="wrap_content" 


                android:layout_height="match_parent" 


                android:paddingLeft="15dp"> 


 


                <ImageView 


                    android:id="@+id/iv_back" 


                    android:layout_width="22dp" 


                    android:layout_height="22dp" 


                    android:layout_gravity="center_vertical" 


                    android:src="@mipmap/address_come_back" /> 


            </LinearLayout> 


 


            <LinearLayout 


                android:layout_width="0dp" 


                android:layout_height="match_parent" 


                android:layout_weight="1" 


                android:gravity="center"> 


 


                <!-- 商品、详情、评价切换的控件 --> 


                <com.gxz.PagerSlidingTabStrip 


                    android:id="@+id/psts_tabs" 


                    android:layout_width="wrap_content" 


                    android:layout_height="32dp" 


                    android:layout_gravity="center" 


                    android:textColor="#ffffff" 


                    android:textSize="15sp" 


                    app:pstsDividerColor="@android:color/transparent" 


                    app:pstsDividerPaddingTopBottom="0dp" 


                    app:pstsIndicatorColor="#ffffff" 
  • ItemWebView是SlideDetailsLayout的子View (SlideDetailsLayout代码太多, 放到了最后)
    • 功能为显示商品简介的webview
    • 防止往上滑动时会直接滑动到第一个View
    • 实现滑动到WebView顶部时, 让父控件重新获得触摸事件
/** 


 * 商品详情页底部的webview 


 */ 


public class ItemWebView extends WebView { 


    public float oldY; 


    private int t; 


    private float oldX; 


 


    public ItemWebView(Context context) { 


        super(context); 


    } 


 


    public ItemWebView(Context context, AttributeSet attrs) { 


        super(context, attrs); 


    } 


 


    public ItemWebView(Context context, AttributeSet attrs, int defStyleAttr) { 


        super(context, attrs, defStyleAttr); 


    } 


 


 


    @Override 


    public boolean onTouchEvent(MotionEvent ev) { 


 


        switch (ev.getAction()) { 


            case MotionEvent.ACTION_MOVE: 


                float Y = ev.getY(); 


                float Ys = Y - oldY; 


                float X = ev.getX(); 


 


                //滑动到顶部让父控件重新获得触摸事件 


                if (Ys > 0 && t == 0) { 


                    getParent().getParent().requestDisallowInterceptTouchEvent(false); 


                } 


                break; 


 


            case MotionEvent.ACTION_DOWN: 


                getParent().getParent().requestDisallowInterceptTouchEvent(true); 


                oldY = ev.getY(); 


                oldX = ev.getX(); 


                break; 


 


            case MotionEvent.ACTION_UP: 


                getParent().getParent().requestDisallowInterceptTouchEvent(true); 


                break; 


 


            default: 


                break; 


        } 


        return super.onTouchEvent(ev); 


    } 


 


    @Override 


    protected void onScrollChanged(int l, int t, int oldl, int oldt) { 


        this.t = t; 


        super.onScrollChanged(l, t, oldl, oldt); 


    } 


 


} 
  • ItemListView 也是SlideDetailsLayout的子View
    • 和ItemWebView功能大致一样
/** 


 * 商品详情页底部的ListView 


 */ 


public class ItemListView extends ListView implements AbsListView.OnScrollListener { 


    private float oldX, oldY; 


    private int currentPosition; 


 


    public ItemListView(Context context) { 


        super(context); 


        setOnScrollListener(this); 


    } 


 


    public ItemListView(Context context, AttributeSet attrs) { 


        super(context, attrs); 


        setOnScrollListener(this); 


    } 


 


    public ItemListView(Context context, AttributeSet attrs, int defStyleAttr) { 


        super(context, attrs, defStyleAttr); 


        setOnScrollListener(this); 


    } 


 


 


    @Override 


    public boolean onTouchEvent(MotionEvent ev) { 


        switch (ev.getAction()) { 


            case MotionEvent.ACTION_MOVE: 


                float Y = ev.getY(); 


                float Ys = Y - oldY; 


                float X = ev.getX(); 


                int [] location = new int [2]; 


                getLocationInWindow(location); 


 


                //滑动到顶部让父控件重新获得触摸事件 


                if (Ys > 0 && currentPosition == 0) { 


                    getParent().getParent().requestDisallowInterceptTouchEvent(false); 


                } 


                break; 


 


            case MotionEvent.ACTION_DOWN: 


                getParent().getParent().requestDisallowInterceptTouchEvent(true); 


                oldY = ev.getY(); 


                oldX = ev.getX(); 


                break; 


 


            case MotionEvent.ACTION_UP: 


                getParent().getParent().requestDisallowInterceptTouchEvent(true); 


                break; 


 


            default: 


                break; 


        } 


        return super.onTouchEvent(ev); 


    } 


 


    @Override 


    public void onScrollStateChanged(AbsListView view, int scrollState) { 


        currentPosition = getFirstVisiblePosition(); 


    } 


 


    @Override 


    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 


 


    } 


} 
  • NoScrollViewPager为最外层的父布局
    • 当滑动到图文详情模块时, 能禁止掉ViewPager的滑动事件
/** 


 * 提供禁止滑动功能的自定义ViewPager 


 */ 


public class NoScrollViewPager extends ViewPager { 


    private boolean noScroll = false; 


 


    public NoScrollViewPager(Context context, AttributeSet attrs) { 


        super(context, attrs); 


    } 


 


 


    public NoScrollViewPager(Context context) { 


        super(context); 


    } 


 


    public void setNoScroll(boolean noScroll) { 


        this.noScroll = noScroll; 


    } 


 


    @Override 


    public void scrollTo(int x, int y) { 


        super.scrollTo(x, y); 


    } 


 


    @Override 


    public boolean onTouchEvent(MotionEvent arg0) { 


        if (noScroll) 


            return false; 


        else 


            return super.onTouchEvent(arg0); 


    } 


 


    @Override 


    public boolean onInterceptTouchEvent(MotionEvent arg0) { 


        if (noScroll) 


            return false; 


        else 


            return super.onInterceptTouchEvent(arg0); 


    } 


 


    @Override 


    public void setCurrentItem(int item, boolean smoothScroll) { 


        super.setCurrentItem(item, smoothScroll); 


    } 


 


    @Override 


    public void setCurrentItem(int item) { 


        super.setCurrentItem(item); 


    } 


 


} 

商品模块最外层的布局是一个自定义的ViewGroup名为SlideDetailsLayout

SlideDetailsLayout内容有两个View, mFrontView(第一个View)和mBehindView(第二个View)

有两种状态, 状态设置为close就显示第一个商品数据View, open状态就显示第二个图文详情View

相关推荐