Android 横向带有吸附效果的横向拖动控件(效果同纵向下拉刷新ListView)

【Android】两种方式实现可拖拽的控件(带吸附效果) 实现的效果如下图所示,手指能拖拽悬浮球移动,并会根据距离自动吸附于屏幕边缘,其半边隐藏于屏幕外。 阅读详情

先上一张效果图



中间的横向拖动就是我们要做的效果。

一、实现思路

仔细观察不难发现,该拖动view与listview的下拉刷新的效果很类似,手指拖动的时候显示隐藏的view,手指放开自动回弹。只不过区别就是一个横向一个纵向
下拉刷新的实现思路如下:
自定义一个布局继承自LinearLayout,然后在这个布局中加入下拉头和ListView这两个子元素,并让这两个子元素纵向排列。初始化的时候,让下拉头向上偏移出屏幕,这样我们看到的就只有ListView了。然后对ListView的touch事件进行监听,如果当前ListView已经滚动到顶部并且手指还在向下拉的话,那就将下拉头显示出来,松手后进行刷新操作,并将下拉头隐藏。原理如图所示:

我们要实现的效果跟下拉刷新基本一样,只不过是方向是横向而已。如图

二、具体实现

首先我们要先自定义一个LinearLayout,然后在布局中加入隐藏头和剩余部分
布局文件如下:
        <com.boohee.myview.HorizontalDragLinearLayout
            android:id="@+id/main_hori_scroll_ll"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:baselineAligned="false"
            android:clickable="true"
            android:descendantFocusability="blocksDescendants"
            android:orientation="horizontal">

            <!--添加一层处理左右拖动时的移动-->
            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                >

              ...........<pre name="code" class="java"><span style="white-space:pre">		</span><!--此处添加 剩余显示的部分-->
</LinearLayout> </com.boohee.myview.HorizontalDragLinearLayout>
 自定义的LinearLayout,初始化部分:
    private Context context;
    //需要隐藏的view
    private TextView headerView;
    /**
     * 是否已加载过一次layout,这里onLayout中的初始化只需加载一次
     */
    private boolean loadOnce;
    /**
     * 需要隐藏View的布局参数
     */
    private MarginLayoutParams headerLayoutParams;

    /**
     * 隐藏view的宽度
     */
    private int hideHeaderWidth;
    private float xDown;
    /**
     * 每次move的x坐标
     */
    private float tmpXMove;

    private float mFocusX = 0.f;
    /**
     * 在被判定为滚动之前用户手指可以移动的最大值。
     */
    private int touchSlop;
    /**
     * 头部回滚的速度
     */
    public static final int SCROLL_SPEED = -10;

    public HorizontalDragLinearLayout(Context context) {
        this(context, null);
    }

    public HorizontalDragLinearLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HorizontalDragLinearLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setOrientation(HORIZONTAL);
        this.context = context;
        init();
    }

    private void init() {
        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

        headerView = new TextView(context);
        LinearLayout.LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        params.gravity = Gravity.CENTER_VERTICAL;
        headerView.setLayoutParams(params);
        headerView.setTextColor(Color.BLACK);
        headerView.setGravity(Gravity.CENTER);
        this.addView(headerView, 0);
    }

    public void setHeaderText(String string){
        if (headerView != null){
            headerView.setText(string);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (headerView != null && changed && !loadOnce){
            hideHeaderWidth = - headerView.getWidth();
            headerLayoutParams = (MarginLayoutParams) headerView.getLayoutParams();
            headerLayoutParams.leftMargin = hideHeaderWidth;
            headerView.setLayoutParams(headerLayoutParams);
            loadOnce = true;
        }
    }

初始化的时候动态添加了一个TextView,也就是我们需要隐藏的部分
在第一次onLayout布局的时候,我们根据隐藏头的宽度 调整该隐藏头的margin,使其隐藏。

然后我们需要进行拖动识别,重写onTouchEvent 
    @Override
    public boolean onTouchEvent(MotionEvent motionEvent) {
        //禁止父容器拦截事件
        getParent().requestDisallowInterceptTouchEvent(true);
        switch (motionEvent.getAction()){
            case MotionEvent.ACTION_DOWN:
                xDown = motionEvent.getRawX();
                return true;
            case MotionEvent.ACTION_MOVE:
                float xMove = motionEvent.getRawX();
                int distance = (int) (xMove - xDown);
                if (distance <= 0 && headerLayoutParams.leftMargin <= hideHeaderWidth) {
                    return false;
                }
                if (distance < touchSlop) {
                    return false;
                }
                //大于头部宽度不做处理
                if (distance >= -hideHeaderWidth){
                    return true;
                }
                headerLayoutParams.leftMargin = distance + hideHeaderWidth;
                headerView.setLayoutParams(headerLayoutParams);
                tmpXMove = xMove;
                return true;
            case MotionEvent.ACTION_UP:
                //松手时调用隐藏头部
                new HideHeaderTask().execute();
                break;
            default:
                break;
        }
        return true;
    }

由于外层是用的viewPager+fragment进行页面切换,所以默认情况下touch事件是被viewpager消费掉的。我们要组织父控件拦截事件
        getParent().requestDisallowInterceptTouchEvent(true);
其中涉及Android 的touch 分发,可以参考 鸿洋大大的这篇博客 点击打开链接
在move的时候得到移动的距离,然后对隐藏头设置margin,使其及该LinearLayout的其他子view跟随隐藏头一起向右移动,达到我们想要的效果

up的时候启动一个AsyncTask 动态改变隐藏头的margin,去恢复到最初始的状态,即隐藏头隐藏的状态。

    /**
     * 隐藏头部
     */
    class HideHeaderTask extends AsyncTask<Void, Integer, Integer> {

        @Override
        protected Integer doInBackground(Void... params) {
            int leftMargin = headerLayoutParams.leftMargin;
            while (true) {
                leftMargin = leftMargin + SCROLL_SPEED;
                if (leftMargin <= hideHeaderWidth) {
                    leftMargin = hideHeaderWidth;
                    break;
                }
                publishProgress(leftMargin);
                sleep(10);
            }
            return leftMargin;
        }

        @Override
        protected void onProgressUpdate(Integer... leftMargin) {
            headerLayoutParams.leftMargin = leftMargin[0];
            headerView.setLayoutParams(headerLayoutParams);
        }

        @Override
        protected void onPostExecute(Integer leftMargin) {
            headerLayoutParams.leftMargin = leftMargin;
            headerView.setLayoutParams(headerLayoutParams);
        }
    }

    private void sleep(int i) {
        try {
            Thread.sleep(i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

搞定。

另外 效果中带悬浮进度的progressBar 连接在 这里
Android 自定义View 实现自动吸附功能 1.简述 最近开发app过程中要实现拖动view后要可以自动吸附功能,所以需要自定义view来在onTouchEvent中来利用动画来实现此功能 2.功能代码部分 import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.util.... 阅读详情

相关推荐

Android滑动吸附悬停技术与实现

ViewPager 是 Android 开发中常用的组件,用于实现滑动页面切换的效果。它的核心是一个适配器模式,通过内部的Adapter来承载和管理多个页面视图。使用ViewPager时,开发者需要为其设置一个Adapter,Adapter会负责创建与ViewPager页面数量一致的视图(View)。关键API包括:: 设置页面适配器。: 设置ViewPager当前显示的页面。: 设置预加载的页面数量,以优化性能。ViewPager内部默认不支持滑动吸附。

weixin_29301059的博客 1052

悬浮View,可拖动,放手后自动吸附到屏幕边上。

自定义的悬浮View,内容可以放任意布局,可以随手指拖动,悬浮后会自动吸附到手机左、右屏幕边上,可以控制是否自动吸附。

超级大帅哥 1264

Android-用RecycleView实现的吸附效果支持单条数据

用RecycleView实现的吸附效果,支持单条数据

Android(自定义图标)可拖动并带有吸附边缘效果

很简单,只需要自定义一个View就可以。 布局: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" androi...

mintent的博客 2532

上汽CPMP开发流程与A、B、C、D样

也叫验收样件或设计样件,是根据A样试制结果优化后的样件,外观、功能达到设计要求,B样可以是手工样件或者模具件,B样件的全维度产品功能和尺寸参数已经固化下来,并需要和最终的量产产品保持一致。为批量样件或生产样件、展示样件,是在A/B的基础上完善结果,此时的产品状态已经完全定型,并能够满足客户和市场提出的各类需求。预试生产(Pre-Production)----------------------------------------------------------------------→D样。

weixin_43602865的博客 3717

android横向加载更多,Android开发ListView中下拉刷新上拉加载及带列的横向滚动实现方法...

ListView 控件可使用四种不同视图显示项目。通过此控件,可将项目组成带有或不带有列标头的列,并显示伴随的图标和文本。可使用 ListView 控件将称作 ListItem 对象的列表条目组织成下列四种不同的视图之一:1.大(标准)图标2.小图标3.列表4.报表 View 属性决定在列表中控件使用何种视图显示项目。还可用 LabelWrap 属性控制列表中与项目关联的标签是否可换行显示。另外,...

weixin_28946193的博客 496

Rocky Linux 9.0国内yum源一键替换指南(上海交大镜像站实测)

本文详细介绍了如何将Rocky Linux 9.0的yum源替换为上海交大镜像站,以解决国内用户访问官方源速度慢的问题。通过实测验证,上海交大镜像站提供高速下载和稳定更新,并提供了完整的替换步骤、常见问题解决方案及高级优化配置,帮助用户提升软件包下载效率。

weixin_29304985的博客 362

Android之AppBarLayout实现悬停吸附伸缩效果

前几天看到这样一个UI效果,然后自己也仿照实现了下: 看着挺酷的,也有很多App都用到了这个UI效果,比如开眼App和沪江开心词场就用到了. 所以下面就来简单实现一下这个UI效果吧. 组合三剑客 1.AppBarLayout 2.CoordinatorLayout 3.CollapsingToolbarLayout 实现上面的UI效果需要将这三剑客的组合起来用,下面先介绍下这三个控件: Ap...

weixin_33840661的博客 1093

【数据库】SQL Server 2008 R2 安装全流程详解与常见问题避坑指南

本文详细解析了SQL Server 2008 R2的完整安装流程与核心配置。从安装前的系统兼容性检查、.NET Framework依赖准备,到图文详解实例配置、混合身份验证模式设置等关键步骤,并提供了安装失败、服务无法启动等高频问题的排查与避坑指南,帮助用户顺利完成部署。

java5的博客 1242

5分钟搞定PaddleOCR PP-OCRv5环境搭建:从安装到第一个识别Demo

本文提供了一份详细的PaddleOCR PP-OCRv5环境搭建与快速入门指南。通过清晰的步骤,指导读者在5分钟内完成从创建Python虚拟环境、安装PaddlePaddle框架和PaddleOCR库,到编写并运行第一个OCR识别Demo的全过程,帮助开发者快速体验最新的PP-OCRv5模型的文字识别能力。

sprite的博客 1268

android 应用置顶到最前端_【五种方式实现Android吸顶效果 最全总结!】列表滑动到顶部 固定顶部栏效果...

如今许多app都会应用到的一种UI交互形式,列表滑动到顶部,固定顶部栏效果,我们也可以称作其为吸顶效果。比如微博 、各大浏览器的首页信息流模块、我的页面的设计等。微博评论的吸顶效果本文将循序渐进的通过多种方式实现吸顶效果。大家择优选取适合自己的实现方式。 实现效果如图:demo实现一、两个相同的顶部栏写两个一模一样的固定悬浮栏,在一开始把外层固定栏先隐藏,当内层固定栏滑动到外层固定位置时,把内层固...

weixin_39854730的博客 2453

体系结构学习-6-超标量处理器

 MIPS32-5段流水线采用了指令级并行方式(5个流水段同时运行5条指令)提升系统吞吐率,是一种标量处理器(CPI≥1CPI \ge 1CPI≥1),但是一个周期一条指令以及无法满足现代计算机需求了。 超标量处理器(Superscalar) 1、基本思想:增强指令集并行,让每个周期执行更多指令,实现 CPI<1CPI<1CPI<1 。(IPC=1/CPIIPC = 1...

qq_40891899的博客 1213

Android自定义View实现拖动吸附效果

1、既然要实现控件拖动,那么就离不开onTouchEvent()这个方法,需要监听里面的按下和滑动事件。 2、 要实现自动贴边,需要监听onTouchEvent()中手指离开屏幕事件。对于贴边的过程,我们用属性动画来解决。 3、事件的冲突问题也需要考虑,拖动、点击关系到了事件的拦截。

yihanss的博客 1198

快速入门:使用 SQL Server Management Studio (SSMS) 连接和查询 SQL Server 实例

开始使用 SQL Server Management Studio (SSMS) 连接到 SQL Server 实例并运行一些 Transact-SQL (T-SQL) 命令。本文介绍如何连接和查询实例SQL Server。有关 Azure SQL,请参阅连接。若要使用,请参阅连接和查询。若要详细了解如何SQL Server Management Studio,请参阅其他。......

m0_72938729的博客 5729

手把手教你学 Simulink (1.3):探索Simulink模块库的奇妙世界

Simulink模块库按照功能分为多个类别,每个类别包含专门用于特定任务的模块。% 打开Simulink库浏览器% 或者以编程方式获取库列表disp('可用的库列表:');end常用模块(Simulink):最基础和最常用的模块信号处理模块(DSP System Toolbox):专业信号处理工具通信模块(Communications Toolbox):通信系统设计控制系统模块(Control System Toolbox):控制系统设计与分析% 创建自定义模块库。

QQ_778132974的博客 384

Android -- RecyclerView实现顶部吸附效果

1,先来看一下今天实现的效果: 2,这次的效果是使用ItemDecoration来实践的,来看一看我们的实现吧   第一步:首先添加依赖,由于我们这些数据是请求网络的,所以一下我们添加网络框架依赖、RecyclerView、Glide依赖 apply plugin: 'com.android.application' apply plugin: 'com.neenbedankt.android...

weixin_33744141的博客 401

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

安卓用RecyclerView实现横向滑动列表

背景 通常我们遇到的是纵向滑动列表,但是也会有横向滑动列表.那横向的怎么做呢? 解决方案 起始很简单,绝大部分代码和纵向是一样的,只有一个设置不一样. 实现效果 关键代码 recyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false) 完整代码 1). MainActivity....

蓝不蓝编程 1万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Android控件——HorizontalScrollView使用(一)

1. HorizontalScrollView简单使用 Gallery(画廊)是一个锁定中心条目并且拥有水平滚动列表的视图,一般用来浏览图片,并且可以响应事件显示信息;Gallery还可以和ImageSwitcher组件结合使用来实现一个通过缩略图来浏览图片的效果; 但Gallery被谷歌废弃了,Google推荐使用ViewPager和HorizontalScrollView来实现Gallery的...

zhewen的博客 2万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

android水平滚动条,android 水平滚动 HorizontalScrollView

encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="fill_parent"android:layout_height="fill_parent">android:layout_h...

weixin_39739395的博客 194

一个流畅的拖动排序DragSortGridView,自动滚屏

先上效果流畅效果超越了网易新闻和UC浏览器的栏目收藏.gif图和实际效果有差距1.拖拽可以移动item,并且其他item会立即自动补位,快速拖拽也非常流畅 2.item太多时,拖拽到边缘时会自动滚屏. 3.可以自定义被拖拽的的View放大,添加阴影等效果 4.长按启动删除模式,需要自己实现item的删除按钮展示,自己管理删除模式的切换 5.可以放在ScrollView中拖动排序,需要Scro

虎躯一震的博客 8518

android拖拽排序,DragSortListView:可拖动排序的listview

DragSortListView是一个可以实现拖动排序的listview控件,是我看到的交互较为复杂的开源代码中不管是代码质量还是流畅性都最好的。虽然作者已经不再更新其版本,但是仍然非常值得我们去研究,尤其是那些本身需要这种效果的朋友。DragSortListView 简称DSLV,继承自listView,能实现拖动排序、滑动删除,主要用于这样的listview,音乐列表、收藏列表、清单列表等。他...

weixin_42305622的博客 1073

Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现 (附源码下载)

本文内容:1、横向ListView的所有实现思路; 2、其中一个最通用的思路HorizontalListView,并基于横向ListView开发一个简单的相册; 3、实现的横向ListView在点击、浏览时item背景会变色,并解决了listview里setSelected造成item的选择状态混乱的问题。

yanzi1225627的专栏 20万+

android 横向动态列表,Android横向ListView

在日常开发中经常会发现横向的ListView。下面讨论实现方案。1.动态的添加布局。RelativeLayout view = (RelativeLayout) LayoutInflater.from(this).inflate(R.layout.demo, null);ListView.addView(view);2.通过继承AdapterView(ListAdapter)自定义类实现部分关键代...

weixin_39670246的博客 1088

RecyclerView 的简单使用 -- (横向/纵向)列表、网格、瀑布流的实现

代码实现 Activity.java public class RecyclerViewActivity extends BaseActivity { private RecyclerView recyclerView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { ...

villen_t的博客 2万+
上一篇: Android自定义Viewgroup切换View带有吸附效果
下一篇: Android RecyclerView 的点击事件
w4lle
博客等级 码龄16年 49粉丝 60原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值