Android仿微信列表滑动删除之可滑动控件(一)

这次是列表滑动删除的第三波,仿微信的列表滑动删除。先上个效果图:

前面的文章里面说过开源框架SwipeListView的实现原理是每个列表item中包含上下两层view,普通状态下上层的view覆盖着下层的view,当用户滑开上层的view,下层的view就显示出来了。但是仔细观察微信列表的item,很明显并非这个实现方案,微信的item应该一个单层view,只不过这个item超出了所在的ListView的宽度,在用户滑动item的时候,item超出屏幕的view则会显示在屏幕之上,这种滑动实现也很不错。

既然推测出微信的实现原理,现在就要寻找具体的实现方案了,我最开始想的比较简单,以为写一个横向线性布局LinearLayout,让其包含两个子布局,左边的子布局宽度设置为填充父布局的宽度,以为另一个子布局就自然而然的会超出父布局的显示范围,但是具体测试的时候,发现就算左边的子布局设置为填充父布局的宽度,但实际显示的时候还是两个子布局被包含在父布局的显示范围内,右边的子布局无法做到超出父布局的显示范围。

纠结了一段时间,偶然情况下想起了ScrollView还有一种类型是HorizontalScrollView,,这个android提供的HorizontalScrollView可以做到其子view超出它的显示范围,那我可以直接使用HorizontalScrollView来实现这个item,我决定自定义一个控件,继承自HorizontalScrollView,在代码里面直接添加两个子布局,并让左边的布局宽度填充这个控件的自身宽度,以便让右边的布局超出控件的显示范围,不过很不辛,HorizontalScrollView比较傲娇,很难驾驭,奇葩bug层出不穷,譬如左边的子布局渲染出来了,但是右边的子布局愣是没初始化,更别说滑动了,弄的焦头烂额,最后实在没办法,只得暂时放下。

最后则是想到了使用一个自定义的ViewGroup来实现这个item。现在很多app在第一次启动的时候,会出现一个介绍性的导航界面,用户一页一页的滑动,看完导航的介绍之后再正式进入app,现在这种导航介绍应该大多数是用ViewPager实现的,ViewPager可以做到两个滑动的子页同时显示在屏幕范围内,具有很好的体验效果。但是ViewPager是在之后的support.v4里面引入的,最初并没有,那一开始这种导航介绍使用什么方案实现的呢?当然就是自定义的ViewGroup了,其实supprot.v4.ViewPager本身就是一个自定义的ViewGroup。关于使用自定义的ViewGroup实现导航介绍,csdn上有个大牛有专门写过一个文章介绍了,这里就不详细说了。

本篇的要讲的是如何使用自定义的ViewGroup实现item的子view可以超出父布局的显示范围这样的效果。

写一个SwipeItemView,继承自ViewGroup,构造方法里面,传入左边布局的引用id和右边布局的引用id,初始化左子布局和右子布局,并将它们添加到SwipeItemView中作为子view,代码如下:

private void init(Context context, AttributeSet attrs) {
    mScroller = new Scroller(context);

    ......

    if(mPrimaryViewID == -1)
      throw new RuntimeException(
          "Illegal attribute 'primaryView', make sure you have set it");

    mPrimaryView = LayoutInflater.from(getContext()).inflate(
        mPrimaryViewID, null);
    mPrimaryView.setClickable(false);
    addView(mPrimaryView, 0);
    if(mSlidingViewID != -1) {
      mSlidingView = LayoutInflater.from(getContext()).inflate(
          mSlidingViewID, null);
      mSlidingView.setClickable(false);
      addView(mSlidingView, 1);
    }
  }

接下来需要重写VIewGroup的onMeasure()方法,用来测量这个SwipeItemView及其子view的宽高,其中先获取转入的heightMeasureSpec中包含的heightSize,当heightSize的值和heightMeasureSpec相同的时候,是测量整个SwipeItemView的宽高,这是我们不做额外的处理,当heightSize不等于的传入的heightMeasureSpec的时候,是用于测量SwipeItemView它包含的子view的宽高,这里我们做一下额外的处理,主要是针对超出SwipeItemView显示范围的右边的mSlidingView,我想要它的宽只是包裹其内容就行,不想它的宽和屏幕范围等宽,所以构造一个这样的参数MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),具体代码如下:

@Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);

    if(heightSize != heightMeasureSpec) {
      mPrimaryView.measure(MeasureSpec.makeMeasureSpec(widthSize, widthMode),
          MeasureSpec.makeMeasureSpec(heightSize, heightMode));

      if(mSlidingView != null) {
        mSlidingView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
            MeasureSpec.makeMeasureSpec(heightSize, heightMode));
      }

    } else {
      mPrimaryView.measure(widthMeasureSpec, heightMeasureSpec);
      if(mSlidingView != null)
        mSlidingView.measure(widthMeasureSpec, heightMeasureSpec);
    }
  }

然后是重写ViewGroup的onLayout()方法,用来放置子view在SwipeItemView中的具体位置,主要就是让右边的mSlidingView排列在左边的mPrimaryView的右边,具体代码如下:

@Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    mPrimaryView.layout(l, t, r, b);
    if(mSlidingView != null)
      mSlidingView.layout(r, t, r + mSlidingView.getMeasuredWidth(), b);
  }  

好了,具体的SwipeItemView的初始化完成了,接下来需要做什么工作呢,看一下上面的构造方法,有没有看到mScroller = new Scroller(context)这行代码,我们需要使用这个mScroller来做这个SwipeItemView滑动的动画效果。我们知道ViewGroup中提供了scrollBy()和scrollTo()两个方法用来移动这个ViewGroup视图内容的位置,其中scrollBy()移动参数指定的距离,scrollTo()方法移动到参数指定的位置。但是scrollBy()还好,如果每次都是移动一小段距离的话,给用户的感觉就是一段连续的动画效果了,但是scrollTo()则是瞬间移动,中间没有任何动画效果,会让人感觉到非常突兀,这样我们就需要用到mScroller这个对象了。

Scroller是android提供的用来实现我们需要的移动动画效果的。Scroller本身并非去执行移动的动画的,感觉上Scroller更多是作为一个指挥者,当我们调用它的Scroller.startScroll()方法的时候,这个方法我们需要传入移动初始的位置、移动的距离以及花费的时间,简单理解的话,我们假设指定的时间是10s,那第3s的时候,ViewGroup视图内容应该移动到什么位置,第7s,应该移动到哪个位置,而且这个时刻Scroller计算出来的位置可以通过Scroller.getCurrX()和Scroller.getCurrY()获取到,这个过程,Scroller会回调ViewGroup中的computeScroll()方法,在这个回调方法中,我们调用scrollTo()执行具体的移动操作。而我们实现的这个scrollToWithAnimation()方法就是提供给后面的SwipeListView用来移动某个item并且使其移动过程带有动画效果的方法。代码如下:

 @Override
  public void computeScroll() {
    if(mScroller.computeScrollOffset()) {
      scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
    }
  }

  /**
   * just like scrollTo(), but with animation :D
   * */
  public void scrollToWithAnimation(int scrollX, int scrollY) {
    mScroller.abortAnimation();
    mScroller.startScroll(getScrollX(), getScrollY(),
        scrollX - getScrollX(), getScrollY() - scrollY, 300);
  }

接下来需要实现一个自定义的ListView,暂且命名为SwipeListView。下一篇继续。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android仿微信滑动弹出编辑、删除菜单效果、增加下拉刷新功能

    如何为不同的list item呈现不同的菜单,本文实例就为大家介绍了Android仿微信或QQ滑动弹出编辑.删除菜单效果.增加下拉刷新等功能的实现,分享给大家供大家参考,具体内容如下 效果图: 1. 下载开源项目,并将其中的liberary导入到自己的项目中: 2. 使用SwipeMenuListView代替ListView,在页面中布局: <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipeRefresh

  • Android高仿微信对话列表滑动删除效果

    前言 用过微信的都知道,微信对话列表滑动删除效果是很不错的,这个效果我们也可以有.思路其实很简单,弄个ListView,然后里面的每个item做成一个可以滑动的自定义控件即可.由于ListView是上下滑动而item是左右滑动,因此会有滑动冲突,也许你需要了解下android中点击事件的派发流程,请参考Android源码分析-点击事件派发机制.我的解决思路是这样的:重写ListView的onInterceptTouchEvent方法,在move的时候做判断,如果是左右滑动就返回false,否则返

  • Android 高仿微信朋友圈动态支持双击手势放大并滑动查看图片效果

    最近参与了开发一款旅行APP,其中包含实时聊天和动态评论功能,终于耗时几个月几个伙伴完成了,今天就小结一下至于实时聊天功能如果用户不多的情况可以scoket实现,如果用户万级就可以采用开源的smack + opnefile实现,也可以用mina开源+XMMP,至于怎么搭建和实现,估计目前github上一搜一大把,至于即时通讯怕误人子弟,暂且不做介绍,现就把实现的一个微信朋友圈的小功能介绍一下. 先上效果图: 一拿到主流的UI需求,大致分析下,需要我ListView嵌套Gridview,而grid

  • Android仿微信右滑返回功能的实例代码

    先上效果图,如下: 先分析一下功能的主要技术点,右滑即手势判断,当滑到一直距离时才执行返回,并且手指按下的位置是在屏幕的最左边(这个也是有一定范围的),  这些可以实现onTouchEvent来实现. 接着就是返回时,有滑动效果,很显然这个是Acitivty切换动画实现的.好啦,分析完了就开干.下面上代码: @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case Mot

  • Android仿微信列表滑动删除 如何实现滑动列表SwipeListView

    接上一篇,本篇主要讲如何实现滑动列表SwipeListView. 上篇完成了滑动控件SwipeItemView,这个控件是一个自定义的ViewGroup,作为列表的一个item,为列表提供一些方法让这个SwipeItemView能滑动其视图内容,同时滑动过程中会有顺滑的动画效果.而本篇讲的SwipeListView则是这个列表的具体实现了.当然啦,这个SwipeListView继承自ListView,为了实现我们需要的功能,重点就是重写ListView的onTouchEvent()以及onInt

  • Android实现仿微信tab高亮icon粘着手的滑动效果

    微信的主页分为3个tab,被选中的tab的tabwidget下面会有一个高亮的长条icon,而当切换tab页面的时候,这个icon不是等到tab切换完成后再出现在当前被选中的tab的tabwidget的下面,而是会随着viewpager滑动页面的动作也进行滑动,从前一个tabwidget滑到当前被选中的tabwidget,像viewpager一样有一种粘着你的手的效果,体验很赞.上个图: 本篇分析如何实现这个效果. 首先基本知识是,实现不同tab页之间可以滑动切换需要用到TabPageIndic

  • Android实现微信首页左右滑动切换效果

    大家看到微信首页切换效果有没有觉得很炫,滑动切换,点击底部bar瞬间切换,滑动切换渐变效果,线上效果图: 之前也在博客上看到别人的实现,再次基础上,我做了些优化.首先说下实现原理,大神略过,o(╯□╰)o 页面上看到的三个页面是三个Fragment, 左右滑动使用viewpager,相信大家也都是这么再用,那么底部用的是什么技术呢,底部渐变其实就是重写了ImageView,以及在左右滑动时,改变了TextView的颜色值,是不是很简单...下面我们一步一步的来: 1.自定义ImageView:

  • Android仿微信列表滑动删除之可滑动控件(一)

    这次是列表滑动删除的第三波,仿微信的列表滑动删除.先上个效果图: 前面的文章里面说过开源框架SwipeListView的实现原理是每个列表item中包含上下两层view,普通状态下上层的view覆盖着下层的view,当用户滑开上层的view,下层的view就显示出来了.但是仔细观察微信列表的item,很明显并非这个实现方案,微信的item应该一个单层view,只不过这个item超出了所在的ListView的宽度,在用户滑动item的时候,item超出屏幕的view则会显示在屏幕之上,这种滑动实现

  • Android仿微信滑动退出Activity

    效果图: 原理: 原理一句话就能描述清楚.重写Activity的dispatchTouchEvent,滑动的时候拿到Activity栈中栈顶Activity的上一个Acticity的ContentView添加到栈顶Activity的DecorView中,滑动的过程中做视图平移,滑动结束之后把前面拿过来用的ContentView归还给上一个Activity,然后finish当前Activity. ActivityStack: 实现 Application.ActivityLifecycleCall

  • Android仿微信通讯录列表侧边栏效果

    先看Android仿微信通讯录列表侧边栏效果图 这是比较常见的效果了吧 列表根据首字符的拼音字母来排序,且可以通过侧边栏的字母索引来进行定位. 实现这样一个效果并不难,只要自定义一个索引View,然后引入一个可以对汉字进行拼音解析的jar包--pinyin4j-2.5.0即可 首先,先来定义侧边栏控件View,只要直接画出来即可. 字母选中项会变为红色,且滑动时背景会变色,此时SideBar并不包含居中的提示文本 public class SideBar extends View { priva

  • Android仿微信@好友功能 输入@跳转、删除整块

    最近在做聊天功能的时候,有一个需求是仿照微信做@好友的功能,本来以为挺简单,但是做到这块的时候,发现和想象的有点不一样,什么整块删除,块可编辑,总之,加个@的功能很简单,但是要做和微信的一样还是费了一些功夫,下面是一个demo仅供参考,防止遗忘 先上个效果图 就是这么个功能 1. 分析需求 输入@跳转到联系人界面,选中一个或者多个好友返回到当前界面 按退格键删除整块内容 块内的内容可编辑,编辑完了之后将不附带@功能,只是单纯的文字 2. 开始编码 既然是文本输入首先继承EditText自定义一个

  • Android仿微信实现左滑显示删除按钮功能

    在实际项目中删除列表中的某一项是非常常见的功能,传统的做法可以使用长按监听器等,而现在流行的做法是左滑弹出删除按钮,微信,QQ等都是这么做的,下面做一个示例,代码如下: 主页面MainActivity:代码比较简单常规 package com.home.testslideview; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; im

  • Android仿微信左右滑动点击切换页面和图标

    本文实例为大家分享了Android仿微信左右滑动点击切换页面和图标的具体代码,供大家参考,具体内容如下 目标效果: 使用鼠标滑动屏幕或者点击下边的小图标,可以更改页面和图标,因为没有那么多素材所以只用了两张图片区分. 1.layout文件夹下新建top.xml页面,作为顶部标题. top.xml页面: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="h

  • android仿微信好友列表功能

    android studio实现微信好友列表功能,注意有一个jar包我没有放上来,请大家到MainActivity中的那个网址里面下载即可,然后把pinyin4j-2.5.0.jar复制粘贴到项目的app/libs文件夹里面,然后clean项目就可以使用了 实现效果图: (1)在build.gradle中引用第三方的类库 compile 'com.android.support:recyclerview-v7:26.0.0-alpha1' compile files('libs/pinyin4j

  • Android 仿微信发动态九宫格拖拽、删除功能

    1.完美1比1 仿照微信仿微信发动态 九宫格拖拽.删除 暴力拖拽ui有点问题,不影响使用,资源文件自己找个+号 2.微信发动态拖拽bug 当选择完图片,长按图片拖拽过程中按下屏幕home键盘,再次进入这时候就不能点击输入文字,点击输入文字的时候会触发选择相册事件 3.拖拽事件用的basequickadapter implementation 'com.android.support:recyclerview-v7:28.0.0' implementation "com.github.CymCha

随机推荐

其他