前言
电商内app,重点在于详情页商品展示,用户不仅要看到图,可以看到各种描述,以及相关规格参数。
有需要做电商类app的童鞋可以看看, 首先先看看效果实现
本项目使用的第三方框架:
加载网络图片使用的 Fresco
头部的商品图轮播 ConvenientBanner
导航栏切换 PagerSlidingTabStrip
先看看效果实现
由于代码量过多, 就不一一讲解只介绍几个核心的自定义控件)
不想看的童鞋可以下载apk或者在github上下载源码使用
github地址
apk下载
最外层的布局文件
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">
android:id="@+id/ll_title_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ec0f38"
android:orientation="vertical">
android:layout_width="match_parent"
android:layout_height="44dp"
android:orientation="horizontal">
android:id="@+id/ll_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="15dp">
android:id="@+id/iv_back"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_gravity="center_vertical"
android:src="@mipmap/address_come_back"/>
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
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
*/
publicclass ItemWebView extends WebView {
publicfloatoldY;
private intt;
private floatoldX;
publicItemWebView(Context context) {
super(context);
}
publicItemWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
publicItemWebView(Context context, AttributeSet attrs,intdefStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
publicboolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
caseMotionEvent.ACTION_MOVE:
floatY = ev.getY();
floatYs = Y - oldY;
floatX = ev.getX();
//滑动到顶部让父控件重新获得触摸事件
if (Ys > 0 && t == 0) {
getParent().getParent().requestDisallowInterceptTouchEvent(false);
}
break;
caseMotionEvent.ACTION_DOWN:
getParent().getParent().requestDisallowInterceptTouchEvent(true);
oldY = ev.getY();
oldX = ev.getX();
break;
caseMotionEvent.ACTION_UP:
getParent().getParent().requestDisallowInterceptTouchEvent(true);
break;
default:
break;
}
returnsuper.onTouchEvent(ev);
}
@Override
protected void onScrollChanged(intl,intt,intoldl,intoldt) {
this.t = t;
super.onScrollChanged(l, t, oldl, oldt);
}
}
ItemListView 也是SlideDetailsLayout的子View
和ItemWebView功能大致一样
/**
* 商品详情页底部的ListView
*/
publicclass ItemListView extends ListView implements AbsListView.OnScrollListener {
private floatoldX, oldY;
private intcurrentPosition;
publicItemListView(Context context) {
super(context);
setOnScrollListener(this);
}
publicItemListView(Context context, AttributeSet attrs) {
super(context, attrs);
setOnScrollListener(this);
}
publicItemListView(Context context, AttributeSet attrs,intdefStyleAttr) {
super(context, attrs, defStyleAttr);
setOnScrollListener(this);
}
@Override
publicboolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
caseMotionEvent.ACTION_MOVE:
floatY = ev.getY();
floatYs = Y - oldY;
floatX = ev.getX();
int[] location = newint[2];
getLocationInWindow(location);
//滑动到顶部让父控件重新获得触摸事件
if (Ys > 0 && currentPosition == 0) {
getParent().getParent().requestDisallowInterceptTouchEvent(false);
}
break;
caseMotionEvent.ACTION_DOWN:
getParent().getParent().requestDisallowInterceptTouchEvent(true);
oldY = ev.getY();
oldX = ev.getX();
break;
caseMotionEvent.ACTION_UP:
getParent().getParent().requestDisallowInterceptTouchEvent(true);
break;
default:
break;
}
returnsuper.onTouchEvent(ev);
}
@Override
publicvoid onScrollStateChanged(AbsListViewview,intscrollState) {
currentPosition = getFirstVisiblePosition();
}
@Override
publicvoid onScroll(AbsListViewview,intfirstVisibleItem,intvisibleItemCount,inttotalItemCount) {
}
}
NoScrollViewPager为最外层的父布局
当滑动到图文详情模块时, 能禁止掉ViewPager的滑动事件
/**
* 提供禁止滑动功能的自定义ViewPager
*/
publicclass NoScrollViewPager extends ViewPager {
private boolean noScroll = false;
publicNoScrollViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
publicNoScrollViewPager(Context context) {
super(context);
}
publicvoid setNoScroll(boolean noScroll) {
this.noScroll = noScroll;
}
@Override
publicvoid scrollTo(intx,inty) {
super.scrollTo(x, y);
}
@Override
publicboolean onTouchEvent(MotionEvent arg0) {
if (noScroll)
returnfalse;
else
returnsuper.onTouchEvent(arg0);
}
@Override
publicboolean onInterceptTouchEvent(MotionEvent arg0) {
if (noScroll)
returnfalse;
else
returnsuper.onInterceptTouchEvent(arg0);
}
@Override
publicvoid setCurrentItem(intitem, boolean smoothScroll) {
super.setCurrentItem(item, smoothScroll);
}
@Override
publicvoid setCurrentItem(intitem) {
super.setCurrentItem(item);
}
}
商品模块最外层的布局是一个自定义的ViewGroup名为SlideDetailsLayout
SlideDetailsLayout内容有两个View, mFrontView(***个View)和mBehindView(第二个View)
有两种状态, 状态设置为close就显示***个商品数据View, open状态就显示第二个图文详情View
@SuppressWarnings("unused")
publicclass SlideDetailsLayout extends ViewGroup {
/**
* Callback forpanelOPEN-CLOSEstatus changed.
*/
publicinterface OnSlideDetailsListener {
/**
* Called afterstatus changed.
*
* @param status {@link Status}
*/
void onStatucChanged(Status status);
}
publicenum Status {
/** Panel isclosed */
CLOSE,
/** Panel isopened */
OPEN;
publicstaticStatus valueOf(intstats) {
if (0 == stats) {
returnCLOSE;
} elseif (1 == stats) {
returnOPEN;
} else{
returnCLOSE;
}
}
}
private staticfinalfloatDEFAULT_PERCENT = 0.2f;
private staticfinalintDEFAULT_DURATION = 300;
private ViewmFrontView;
private ViewmBehindView;
private floatmTouchSlop;
private floatmInitMotionY;
private floatmInitMotionX;
private ViewmTarget;
private floatmSlideOffset;
private Status mStatus = Status.CLOSE;
private boolean isFirstShowBehindView = true;
private floatmPercent = DEFAULT_PERCENT;
private long mDuration = DEFAULT_DURATION;
private intmDefaultPanel = 0;
private OnSlideDetailsListener mOnSlideDetailsListener;
publicSlideDetailsLayout(Context context) {
this(context, null);
}
publicSlideDetailsLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
publicSlideDetailsLayout(Context context, AttributeSet attrs,intdefStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlideDetailsLayout, defStyleAttr, 0);
mPercent = a.getFloat(R.styleable.SlideDetailsLayout_percent, DEFAULT_PERCENT);
mDuration = a.getInt(R.styleable.SlideDetailsLayout_duration, DEFAULT_DURATION);
mDefaultPanel = a.getInt(R.styleable.SlideDetailsLayout_default_panel, 0);
这个商品详情页的架构也是本人在已上线的项目中使用
【编辑推荐】
【责任编辑:枯木 TEL:(010)68476606】
点赞 0