逛豆瓣的时候看到了这样的控件,觉得挺有趣,遂模仿之

先看看原版的效果

再看看模仿的效果



分析

控件结构分析

由于*ScrollView只能有一个child view,所以整个child view的结构如图,这里我选择的是LinearLayout作为最外层的布局,content为展示的可滑动的内容,“更多”滑到最右边继续滑时出现的部分,先通过margin把“更多”隐藏

还有“更多”出现时的波纹效果,这个效果是通过贝塞尔曲线实现的,这里的实现比较简单,只取一个控制点,y坐标的数值为height的一半,x坐标随滑动距离变化

关键代码

控件的滑动效果由child view(下称wrapView)和content view(下称contentView)配合产生

  1. 当滑动到最左边并继续滑动的时候,wrapView的scrollX变化,产生第1个gif图效果
  2. 当滑动到最右边并继续滑动的时候,wrapView的scrollX先变化,当滑出到一定距离的时候,contentView的scrollX变化,产生第3个gif图效果
  3. 其他情况不处理滑动,交由HorizontalScrollView处理

详细参考以下代码

public boolean (MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = ev.getRawX();
break;
case MotionEvent.ACTION_MOVE:
float mDeltaX = (ev.getRawX() - mLastX);
mLastX = ev.getRawX();
mDeltaX = mDeltaX * RATIO;
if (mDeltaX > 0) {
if (!canScrollHorizontally(-1) || mWrapView.getScrollX() > 0) {
//contentView的scrollX > 0,contentView scroll,使scrollX变化
if (mContentView.getScrollX() > 0) {
mContentView.scrollBy((int) -mDeltaX, 0);
mMsg.setText(mStringDragged);
} else {
//wrapView的scrollX > 0,wrapView scroll,使scrollX变化
mWrapView.scrollBy((int) -mDeltaX, 0);
mMsg.setText(mStringDragging);
//贝塞尔曲线控制点变化
mControlPoint.x = (int) (mRect.right - mWrapView.getScrollX() * RIPPLE_RATIO);
mControlPoint.y = mRect.bottom / 2;
invalidate();
}
}
} else {
//不能右滑或者外层布局的scrollX < 0
if (!canScrollHorizontally(1) || mWrapView.getScrollX() < 0) {
if (!canScrollHorizontally(1)) {
getDrawingRect(mRect);
}
//wrapView的scrollX >= 产生"更多"动作的距离,contentView scroll,使scrollX变化
if (mWrapView.getScrollX() >= mOffset) {
mContentView.scrollBy((int) -mDeltaX, 0);
mMsg.setText(mStringDragged);
} else {
//wrapView的scrollX < 0,wrapView scroll,使scrollX变化
mWrapView.scrollBy((int) -mDeltaX, 0);
mMsg.setText(mStringDragging);
//贝塞尔曲线控制点变化
mControlPoint.x = (int) (mRect.right - mWrapView.getScrollX() * RIPPLE_RATIO);
mControlPoint.y = mRect.bottom / 2;
invalidate();
}
return true;
}
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
checkAction();
if (mWrapView.getScrollX() < 0) {
mScroller.startScroll(mWrapView.getScrollX(), 0, 0 - mWrapView.getScrollX(), 0,
(0 - mWrapView.getScrollX()) * 5);
} else if (mContentView.getScrollX() > 0) {
mScroller.startScroll(mContentView.getScrollX() + mWrapView.getScrollX(), 0,
0 - mContentView.getScrollX() - mWrapView.getScrollX(), 0,
(mContentView.getScrollX() + mWrapView.getScrollX()) * 6);
} else {
mScroller.startScroll(mWrapView.getScrollX(), 0, 0 - mWrapView.getScrollX(), 0,
mWrapView.getScrollX() * 5);
}
invalidate();
break;
}
return super.onTouchEvent(ev);
}

松手后复原的滑动效果使用Scroller完成,读者可参考相关文档和文章

源码和demo

github:horizontal-elasticity-scrollview

欢迎交流


仿豆瓣首页弹性滑动控件|Axlchen's blog的更多相关文章

  1. 基于Bootstrap仿淘宝分页控件实现

    .header { cursor: pointer } p { margin: 3px 6px } th { background: lightblue; width: 20% } table { t ...

  2. Android开发技巧——定制仿微信图片裁剪控件

    拍照--裁剪,或者是选择图片--裁剪,是我们设置头像或上传图片时经常需要的一组操作.上篇讲了Camera的使用,这篇讲一下我对图片裁剪的实现. 背景 下面的需求都来自产品. 裁剪图片要像微信那样,拖动 ...

  3. 仿IOS7日期选择控件(新)

    前面也写过好几篇仿IOS日期控件的文章,不过基本上都是基于Wheelview修改而来,大致实现了滑轮选择选项的效果,其实和ios7及以上的效果还是相差甚远,而本文中所展现的这个控件虽也是从网上而来(呵 ...

  4. Android-PickerView【仿iOS的PickerView控件,并封装了时间选择和选项选择这两种选择器】使用

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 本文主要演示Android-PickerView的选项选择器.时间选择器的简单运用.由于每一个版本略有不用,所以实际使用方式以git ...

  5. android 开发进阶 自定义控件-仿ios自动清除控件

    先上图: 开发中经常需要自定义view控件或者组合控件,某些控件可能需要一些额外的配置.比如自定义一个标题栏,你可能需要根据不同尺寸的手机定制不同长度的标题栏,或者更常见的你需要配置标题栏的背景,这时 ...

  6. 【Qt】仿QQ表情选择控件

         表情选择控件在聊天应用中常常要用到,做起来尽管不复杂可是非常繁琐.特别是有些图标须要按顺序排列.每次重做必定是非常费时.所以我将聊天表情选择控件封装成一个独立的类QFaceSelectWid ...

  7. JCameraView 仿微信拍照Android控件(点击拍照,长按录小视频)

    JCameraView 控件介绍 这是一个模仿微信拍照的Android开源控件,主要的功能有如下: 点击拍照. 前后摄像头的切换. 长按录视频(视频长度为10秒内). 长按录视频的时候,手指上滑可以放 ...

  8. qml: 自定义按钮-- 仿QML自带控件;

    import QtQuick 2.0 Rectangle { id: btn; width:; height:; radius:; border.color: "#A3A3A3"; ...

  9. jquery仿jquery mobile的select控件效果

    不说废话.直接上代码 //仿jQuery mobile Select控件 //使用方法box为容器id,_id指控件id,selectvalue为选中值,Value为当前值 function Sele ...

随机推荐

  1. HDU - 1754 线段树

    #include <algorithm> #include <iostream> #include<sstream> #include<cstring> ...

  2. jenkins-master-slave节点配置总结

    一.jenkins分布式简单介绍 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能 二.jenk ...

  3. 吴裕雄--天生自然 PYTHON3开发学习:面向对象

    class MyClass: """一个简单的类实例""" i = 12345 def f(self): return 'hello wor ...

  4. DFS---迷宫问题

    #include<iostream> #include<string> #include<cstring> using namespace std;//dfs in ...

  5. 传统方式接口测试返回值json验证

    1.返回值 2.验证方式: public void check200_N(Object obj, int ret_num) throws UnsupportedEncodingException, E ...

  6. python中的变量引用小结

    python的变量都可以看成是内存中某个对象的引用.(变量指向该内存地址存储的值) 1.python中的可更改对象和不可更改对象 python中的对象可以分为可更改(mutable)对象与不可更改(i ...

  7. Centos7.5 firewalld防火墙配置

    CentOS 7.0默认使用的是firewall作为防火墙 1.查看firewall服务状态 systemctl status firewalld 2.查看firewall的状态 firewall-c ...

  8. TreeviewEditor软件的安装和使用

    TreeviewEditor是用VB6开发的一款Windows桌面程序,用户可以快速搭建树形结构,可以导出为Word文档. 支持节点的复制粘贴.节点的拖放. 下载地址:TreeviewEditor.r ...

  9. elementUI的select全选

    elementUI中的el-select全选 <template> <el-select class="handle-select" size="min ...

  10. Django学习之模板层

    三板斧 render,HttpResponse,redirectrender返回一个HTML页面,并且还能够给该页面传数据render内部原理: from django.template import ...