android 仿淘宝、京东商品详情页 向上拖动查看图文详情控件

一、淘宝商品详情页效果

先看一下淘宝详情页的效果




我们的效果



二、实现思路


使用两个scrollView,两个scrollView 竖直排列,通过自定义viewGroup来控制两个scrollView的竖直排列,以及滑动事件的处理。如下图




三、具体实现


1、继承viewGroup自定义布局View 重写onMeasure()和onLayout方法,在onLayout方法中完成对两个子ScrollView的竖直排列布局,代码如下:
布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.baoyunlong.view.pulluptoloadmore.MainActivity"><com.baoyunlong.view.pulluptoloadmore.PullUpToLoadMoreandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><com.baoyunlong.view.pulluptoloadmore.MyScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:fillViewport="true"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ImageViewandroid:scaleType="fitXY"android:src="@drawable/a1"android:layout_width="match_parent"android:layout_height="180dp" /><TextViewandroid:text="这里是标题"android:textSize="18dp"android:layout_marginRight="10dp"android:layout_marginLeft="10dp"android:layout_marginTop="10dp"android:layout_width="match_parent"android:layout_height="wrap_content" /><TextViewandroid:layout_marginTop="10dp"android:text="子标题"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:textSize="18dp"android:layout_width="match_parent"android:layout_height="wrap_content" />..............<LinearLayoutandroid:layout_height="0dp"android:layout_weight="1"android:gravity="bottom"android:layout_width="match_parent"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:height="50dp"android:background="#b11"android:gravity="center"android:text="继续拖动查看图文详情"android:textColor="#000" /></LinearLayout></LinearLayout></com.baoyunlong.view.pulluptoloadmore.MyScrollView><com.baoyunlong.view.pulluptoloadmore.MyScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:fillViewport="true"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/a1" /><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/a3" />.........</LinearLayout></com.baoyunlong.view.pulluptoloadmore.MyScrollView></com.baoyunlong.view.pulluptoloadmore.PullUpToLoadMore></RelativeLayout>
代码:
public class PullUpToLoadMore extends ViewGroup {public PullUpToLoadMore(Context context) {super(context);}public PullUpToLoadMore(Context context, AttributeSet attrs) {super(context, attrs);}public PullUpToLoadMore(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);measureChildren(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int childCount = getChildCount();int childTop = t;for (int i = 0; i < childCount; i++) {View child = getChildAt(i);child.layout(l, childTop, r, childTop + child.getMeasuredHeight());childTop += child.getMeasuredHeight();}}
}
2、处理滑动事件 
规则如下 :
(1)、当处于第一屏时 第一个ScrollView已经滑动到底部并且滑动方向是往上滑动,这个时候滑动事件应该交给父view处理也就是拦截事件让onInterceptTouchEvent返回true.然后父view通过scrollBy()方法滚动,显示出第二个scrollView。
      (2)、当处于第二屏时 第二个ScrollView已经滑动到顶部并且滑动方向是往下滑动,这个时候滑动事件交给父view处理,根据滑动事件显示出第一个ScrollView。
      (3)、当手指离开屏幕时,根据滑动速度来决定是回弹到第一个ScrollView还是第二个ScrollView,通过VelocityTracker来获取滑动速度。
3、一些细节的处理
(1)、如果仔细看观察淘宝的实现效果你会发现,当你滑动到刚刚看到 “继续拖动,查看图文详情”的时候,手指抬起,然后再按下重新向上拖动你会发现,第二页并不会划出来,而是停留在了“继续拖动,查看图文详情”的底部,京东的效果也是一样。这样用户体验不太好,我们来优化一下。其实通过查看ScrollView的源码可以看出来,这是因为ScrollView类的onTouchEvent方法的默认实现,调用了parent.requestDisallowInterceptTouchEvent(true)方法 阻止了我们拦截事件,导致我们父view的onInterceptTouchEvent方法无法执行,也就拦截不到事件,拦截不到事件我们的onTouchEvent就无法执行,onTouchEvent无法执行,我们写在onTouchEvent里面的滚动逻辑就执行不到了,导致了上面我们看到的划不动的效果。解决方法就是,我们需要重写dispatchTouchEvent()方法,防止子view干扰我们,这样我们滑动的时候就可以一气呵成了。代码如下:
@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {//防止子View禁止父view拦截事件this.requestDisallowInterceptTouchEvent(false);return super.dispatchTouchEvent(ev);}
      (2)、监听ScrollView滑动事件的问题
ScrollView没有提供滚动事件的监听方法,也就没法判断是否滚动到了顶部,或者底部,这里我们继承ScrollView 自己实现滚动事件监听。
/*** Created by baoyunlong on 16/6/8.*/
public class MyScrollView extends ScrollView {private static String TAG=MyScrollView.class.getName();public void setScrollListener(ScrollListener scrollListener) {this.mScrollListener = scrollListener;}private ScrollListener mScrollListener;public MyScrollView(Context context) {super(context);}public MyScrollView(Context context, AttributeSet attrs) {super(context, attrs);}public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overridepublic boolean onTouchEvent(MotionEvent ev) {switch (ev.getAction()){case MotionEvent.ACTION_MOVE:if(mScrollListener!=null){int contentHeight=getChildAt(0).getHeight();int scrollHeight=getHeight();int scrollY=getScrollY();mScrollListener.onScroll(scrollY);if(scrollY+scrollHeight>=contentHeight||contentHeight<=scrollHeight){mScrollListener.onScrollToBottom();}else {mScrollListener.notBottom();}if(scrollY==0){mScrollListener.onScrollToTop();}}break;}boolean result=super.onTouchEvent(ev);requestDisallowInterceptTouchEvent(false);return result;}public interface ScrollListener{void onScrollToBottom();void onScrollToTop();void onScroll(int scrollY);void notBottom();}
4、完整代码如下
/*** Created by baoyunlong on 16/6/8.*/
public class PullUpToLoadMore extends ViewGroup {public static String TAG = PullUpToLoadMore.class.getName();MyScrollView topScrollView, bottomScrollView;VelocityTracker velocityTracker = VelocityTracker.obtain();Scroller scroller = new Scroller(getContext());int currPosition = 0;int position1Y;int lastY;public int scaledTouchSlop;//最小滑动距离int speed = 200;boolean isIntercept;public boolean bottomScrollVIewIsInTop = false;public boolean topScrollViewIsBottom = false;public PullUpToLoadMore(Context context) {super(context);init();}public PullUpToLoadMore(Context context, AttributeSet attrs) {super(context, attrs);init();}public PullUpToLoadMore(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {post(new Runnable() {@Overridepublic void run() {topScrollView = (MyScrollView) getChildAt(0);bottomScrollView = (MyScrollView) getChildAt(1);topScrollView.setScrollListener(new MyScrollView.ScrollListener() {@Overridepublic void onScrollToBottom() {topScrollViewIsBottom = true;}@Overridepublic void onScrollToTop() {}@Overridepublic void onScroll(int scrollY) {}@Overridepublic void notBottom() {topScrollViewIsBottom = false;}});bottomScrollView.setScrollListener(new MyScrollView.ScrollListener() {@Overridepublic void onScrollToBottom() {}@Overridepublic void onScrollToTop() {}@Overridepublic void onScroll(int scrollY) {if (scrollY == 0) {bottomScrollVIewIsInTop = true;} else {bottomScrollVIewIsInTop = false;}}@Overridepublic void notBottom() {}});position1Y = topScrollView.getBottom();scaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();}});}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {//防止子View禁止父view拦截事件this.requestDisallowInterceptTouchEvent(false);return super.dispatchTouchEvent(ev);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {int y = (int) ev.getY();switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:lastY = y;break;case MotionEvent.ACTION_MOVE://判断是否已经滚动到了底部if (topScrollViewIsBottom) {int dy = lastY - y;//判断是否是向上滑动和是否在第一屏if (dy > 0 && currPosition == 0) {if (dy >= scaledTouchSlop) {isIntercept = true;//拦截事件lastY=y;}}}if (bottomScrollVIewIsInTop) {int dy = lastY - y;//判断是否是向下滑动和是否在第二屏if (dy < 0 && currPosition == 1) {if (Math.abs(dy) >= scaledTouchSlop) {isIntercept = true;}}}break;}return isIntercept;}@Overridepublic boolean onTouchEvent(MotionEvent event) {int y = (int) event.getY();velocityTracker.addMovement(event);switch (event.getAction()) {case MotionEvent.ACTION_MOVE:int dy = lastY - y;if (getScrollY() + dy < 0) {dy = getScrollY() + dy + Math.abs(getScrollY() + dy);}if (getScrollY() + dy + getHeight() > bottomScrollView.getBottom()) {dy = dy - (getScrollY() + dy - (bottomScrollView.getBottom() - getHeight()));}scrollBy(0, dy);break;case MotionEvent.ACTION_UP:isIntercept = false;velocityTracker.computeCurrentVelocity(1000);float yVelocity = velocityTracker.getYVelocity();if (currPosition == 0) {if (yVelocity < 0 && yVelocity < -speed) {smoothScroll(position1Y);currPosition = 1;} else {smoothScroll(0);}} else {if (yVelocity > 0 && yVelocity > speed) {smoothScroll(0);currPosition = 0;} else {smoothScroll(position1Y);}}break;}lastY = y;return true;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);measureChildren(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int childCount = getChildCount();int childTop = t;for (int i = 0; i < childCount; i++) {View child = getChildAt(i);child.layout(l, childTop, r, childTop + child.getMeasuredHeight());childTop += child.getMeasuredHeight();}}//通过Scroller实现弹性滑动private void smoothScroll(int tartY) {int dy = tartY - getScrollY();scroller.startScroll(getScrollX(), getScrollY(), 0, dy);invalidate();}@Overridepublic void computeScroll() {if (scroller.computeScrollOffset()) {scrollTo(scroller.getCurrX(), scroller.getCurrY());postInvalidate();}}
}


四、源码

github地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/61744.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML之淘宝界面案例

特殊符号 <<br/> <!--<小于号--> ><br/> <!-->大于号--> &amp;<br/> <!--&与--> &reg;<br /> <!--已注册商标--> ©<br /> <!--©版权标记--> &trade;<br /> <!--…

Android开发之仿淘宝商品详情页

看到有人在问如何实现淘宝商品详情页效果&#xff0c;手痒了就撸了一个&#xff0c;献上效果图 大致梳理一下思路&#xff0c;这里不提供源码 状态栏透明使用开源库StatusBarCompat&#xff0c;为了兼容手机4.4 dependencies {compile (com.github.niorgai:StatusBarCompa…

淘宝获得详情页详细教程

请求参数 请求参数&#xff1a;num_iid681459303535&is_promotion1 参数说明&#xff1a;num_iid:淘宝商品ID is_promotion:是否获取取促销价 API接口工具 { "item": { "num_iid": "681459303535", "title&qu…

淘宝商品详情页api

采集淘宝商品列表和商品详情遇到滑块验证码的解决方法&#xff08;带SKU和商品描述&#xff0c;可高并发&#xff09;&#xff0c;主要是解决了高频情况下的阿里系滑块和必须要N多小号才能解决的反扒问题&#xff0c;以后都可以使用本方法了。 大家都知道&#xff0c;淘宝的反爬…

用计算机玩王者荣耀,王者荣耀你们用电脑玩王者荣耀顺手吗? - 游戏发言 - 酷酷跑手机游戏...

我感觉有一点不顺手&#xff0c;那我也是一个职业&#xff0c;专门玩撸啊撸的玩家&#xff0c;但是呢&#xff0c;我就觉得王者荣耀这款游戏不应该搬上电脑这个平面上。王者荣耀是手游它搬上电脑给了诸多英雄&#xff0c;造成不便。比如其中的李白&#xff0c;难道你在李白释放…

王者荣耀太空人名字怎么弄 王者荣耀太空人名字设置方法

在玩王者荣耀游戏时很多人都会遇到一些有趣的名字&#xff0c;比如空白名、彩色名&#xff0c;甚至是会动的名字&#xff0c;而最近王者荣耀就出现了会动的太空人名字&#xff0c;那么&#xff0c;王者荣耀太空人名字怎么弄?下面来看看王者荣耀太空人名字设置方法吧。 王者荣…

苹果微信王者荣耀哪个服务器人多,王者荣耀:QQ区和微信区哪个玩家多?看完会明白...

原标题&#xff1a;王者荣耀&#xff1a;QQ区和微信区哪个玩家多&#xff1f;看完会明白 导读&#xff1a;王者荣耀&#xff1a;QQ区和微信区哪个玩家多&#xff1f;看完会明白 文|刺激小宇哥 阅读到这篇文章的各位趣友大家好&#xff01;游戏无时无刻的丰富着我们的生活&#…

服务器匹配原理,王者荣耀实现原理学习笔记

原作来自腾讯游戏学院 以下是原文部分节选 一、服务器架构 “房间模式” 房间类玩法和MMORPG有很大不同: 1.广播单元的不确定性 2.广播数量很小 3.需要匹配一台房间服务器让少数人进入同一个服务器 这一类游戏最重要的是其“游戏大厅”的承载量,每个“游戏房间”受逻辑所限,…

微信不同服务器能匹配吗,王者荣耀:玩家匹配到自己,体验服微信区和QQ区是互通的?...

原标题&#xff1a;王者荣耀&#xff1a;玩家匹配到自己&#xff0c;体验服微信区和QQ区是互通的&#xff1f; 不少玩家希望官方能够将微信和QQ区的数据打通&#xff0c;但官方的回复是技术无法做到&#xff0c;玩家们也只能因此作罢。近日有游戏博主称&#xff0c;自己王者荣耀…

如何一小时登上微信头脑王者王者段位

废话不多说&#xff0c;直接切入正题。 准备 连接于同一无线网络下的电脑一台、手机一部。 打开下面的网址&#xff0c;下载我们要用的到文件。 https://gitee.com/BroChicken/brain //【GitHub太高级了玩不来&#xff0c;就用了Gitee&#xff08;码云&#xff09;】 点击附件…

训练AI 玩王者荣耀,这算不算开挂?!(附源码)

用自己训练的AI玩王者荣耀 基于深度学习框架pytorch编写&#xff08;resnet101GPT&#xff09;&#xff0c;目前只是验证演示&#xff0c;因为训练数据少以及还没有进入强化学习阶段所以水平不高。 本源码模型主要用了SamLynnEvans Transformer 的源码的解码部分。以及pytorc…

数据分析软件解读王者荣耀一年的“王者”成绩单

玩手游的孩子应该都听过“王者农药”&#xff08;王者荣耀&#xff09;&#xff0c;小编也觉得此游戏&#xff0c;有毒&#xff0c;导致见面第一句话变成了&#xff0c;组团开黑啊&#xff01; 这档游戏有多火&#xff1f;看Power-BI 数据分析软件分析出的数据你就知道了。有人…

我和AI打了六局王者荣耀,心态崩了

十三 发自 凹非寺量子位 报道 | 公众号 QbitAI 今天&#xff0c;我和AI绝悟打了6局王者荣耀&#xff0c;心态有点崩。 没赢过&#xff1f;不&#xff0c;比分3:3打平&#xff0c;还拿过MVP。 那怎么就崩溃了&#xff1f;听我慢慢道来。 PVP对战手游王者荣耀在五一节期间上线了一…

王者荣耀安卓微信有什么服务器,王者荣耀:QQ和微信区哪个好?看排行榜就知道,别不懂清楚转区...

大家都知道&#xff0c;王者荣耀同时拥有安卓和IOS两大区服&#xff0c;它们的每日在线人数都是极其庞大的&#xff0c;而一直以来&#xff0c;关于QQ区和微信区谁强谁弱一直都是玩家们争辩的主要话题。有网友断言&#xff1a;QQ区本来就强&#xff0c;职业选手多&#xff0c;微…

王者荣耀战力查询微信小程序源码下载支持安卓苹果微信Q等多区查询

这是一款战力查询的微信小程序源码 源码内自带了接口 目前支持了微信,Q,苹果,安卓全区都可以查询 ,而且搭建安装简单 使用微信开发者工具打开源码然后设置一下合法域名上传审核即可 该小程序还有战区修改教程等等,具体功能等你来挖掘 另外该小程序无需服务器和域名,让你无…

微信小程序:王者荣耀战力查询微信小程序源码下载支持安卓苹果微信QQ等多区查询

这是一款战力查询的微信小程序源码 源码内自带了接口 目前支持了微信,QQ,苹果,安卓全区都可以查询 支持流量主收益,而且搭建安装简单 使用微信开发者工具打开源码然后设置一下合法域名上传审核即可 该小程序还有战区修改教程等等,具体功能等你来挖掘 另外该小程序无需服务…

王者荣耀改名神器助手微信小程序

这是一个强大的改名神器,强大的生成功能 输入您想要制作的名字可以一键生成N个重复名供您选择 这样就不用担心有些重复名被别人使用了导致无法使用 另外还有英雄昵称,提供多种昵称分类自动生成 比如情侣名字,英雄名字等等(到时候大家看小编演示图即可了解) 支持一键生成N个…

王者荣耀微信一区的服务器没了,为什么王者荣耀微信区和QQ区玩起来像两个游戏?...

我真是被微信区的大叔大妈坑到没脾气……而且有一说一&#xff0c;微信区不仅智商不在线的人很多&#xff0c;还有很多很迷惑的人&#xff0c;根本看不懂他在玩什么也看不懂他想干什么&#xff0c;像人机一般。qq区的人虽然浪&#xff0c;但是傻逼和迷惑的人不多&#xff0c;基…

20+顶尖高校同时开打《王者荣耀》!实际上是一场科研battle,你能信?

金磊 假装发自 王者峡谷量子位 报道 | 公众号 QbitAI 不是吧&#xff0c;不是吧。 一群学霸聚集在一起&#xff0c;竟然是为了打《王者荣耀》&#xff1f;&#xff01; 而且还是来自清北、中科院、浙大等20余所顶级学府的那种。 但毕竟是一帮学霸们的“聚会”&#xff0c;果然连…

王者荣耀战力在线查询小程序源码

介绍&#xff1a; 支持打包成APP版本支持QQ微信双端小程序 支持微信QQ安卓IOS战力查询 网盘下载地址&#xff1a; http://kekewl.cc/fg0D7sq2e5M0 图片&#xff1a;