Android简洁的下拉放大刷新效果示例

序言

国庆放假过后眼看一年又要过完了,年初指望着已经有一年的经验本以为自己不是刚出校的学生以为翅膀已经硬了,打算辞职换新工作,一面试才发现自己就是个垃圾,什么oninterceptEvent,dispatchTouchEvent ,Aysnctask都不会。做了一年的项目也是用的Xutils2.6版本 还有一堆不常用不好的不主流不时尚的框架,技术也没任何长进。还好公司真的轻松(所以也学不到任何东西)可以趁闲下来的时间多学点东西。于是写了个简单但也有需求的控件练练手。

首先先看效果图吧

这个是listview的效果还有一个ScrollView的效果当然使用和实现时一样的原理这里就一listview来讲解,文末传送门可以看到全部的代码

1、具体使用

项目build.gradle

allprojects {
 repositories {
  jcenter()
  maven { url 'https://jitpack.io' }
 }
}

app model build.gradle

compile 'com.github.xypmhxy:PullZoomLayout:1.1'

布局文件中

<com.ren.pullzoom.widget.PullZoomLayout
  android:id="@+id/pull"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  app:image_height="200dp" 图片高度
  app:image_res="@mipmap/timg" 图片资源
  app:refresh_enable="true" 是否开启刷新
  app:scale_type="center_crop">//图片缩放方式

  <ListView
   android:id="@+id/listview"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:background="@android:color/white" />

 </com.ren.pullzoom.widget.PullZoomLayout>

2、实现思路

其思路很简单

1.首先在构造方法中动态添加下拉缩放的imageView和刷新的refreshProgress(控件中为实现跟随手指滑动旋转因此使用的为imageView)

2.获取到listview对象,然后监听listview的滑动事件,判断滑到顶部后继续向下滑动的时候将需要放大的ImageView高度增加然后利用ImageView的Scale方法完成缩放。

3.最后放开手指的时候用属性动画让imageView平滑回到最初状态,并且如果开启下拉刷新则回调其方法。

3、具体实现

1.动态添加两个ImageView(下拉放大的和刷新的progress),大致原理就是将这两个ImageView添加到RelativeLayout中然后将RelativeLayout 添加到自身中。代码如下

/*实例化头部布局包含pullZoomImage 和 refreshProgress*/
protected void init(Context context) {
  RelativeLayout head = new RelativeLayout(context);
  ViewGroup.LayoutParams headParams = new ViewGroup.LayoutParams(-1, -2);
  head.setLayoutParams(headParams);
  /*实例化pullZoomImage*/
  ·······
  pullZoomImage.setImageResource(imageRes);
  originalParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, imageHeight);
  pullZoomImage.setLayoutParams(originalParams);
  head.addView(pullZoomImage);
  /*实例化refreshProgress*/
  refreshProgress = new ImageView(context);
  refreshProgress.setVisibility(GONE);
  refreshProgress.setImageResource(R.drawable.refresh);
  RelativeLayout.LayoutParams refreshParams = new RelativeLayout.LayoutParams(dip2px(context, 35), dip2px(context, 35));
  refreshParams.addRule(RelativeLayout.ALIGN_PARENT_END, RelativeLayout.TRUE);
  refreshProgress.setLayoutParams(refreshParams);
  head.addView(refreshProgress);
  /*将头部添加到此控件中*/
  addView(head, 0);
}

2.是获取listview对象,因为listview属于子控件所以不能在构造方法里直接获取,因为此时控件不一定加载完成所以需要等待子控件加载完成后获取因此在onFinishInflate方法中获取

 @Override
 protected void onFinishInflate() {
  super.onFinishInflate();
  /*获取listview*/
  if (getChildAt(1) instanceof ListView) {
   listView = (ListView) getChildAt(1);
   listView.setOnScrollListener(scrollListener);
   listView.setOnTouchListener(touchListener);
  }
 }

3.添加listview滑动监听判断是否滑动到顶部,可以开启下拉放大功能

 /*listview滑动监听*/
 protected AbsListView.OnScrollListener scrollListener = new AbsListView.OnScrollListener() {
  @Override
  public void onScrollStateChanged(AbsListView view, int scrollState) {
   /*判断是否滑动到顶部*/
   int firstVisibleItem = listView.getFirstVisiblePosition();
   if (firstVisibleItem == 0 && scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
    View firstView = getChildAt(0);
    canZoom = firstView != null && firstView.getTop() == 0;
   } else
    canZoom = false;
  }

  @Override
  public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
  }
 };

4.实现OnTouchListener根据事件调用放大和缩小动画,抬手时实现刷新等操作

/*listview touchListener监听*/
 protected OnTouchListener touchListener = new OnTouchListener() {
  @Override
  public boolean onTouch(View v, MotionEvent ev) {
   if (pullZoomImage == null) return false;
   switch (ev.getAction()) {
    case MotionEvent.ACTION_DOWN:
     pressY = ev.getY();//获取按下的Y坐标
     break;
    case MotionEvent.ACTION_MOVE:
     if (canZoom)//如果已经滑动到顶部并继续滑动则开始放大pullZoomImage
      return zoomView(ev);
     break;
    case MotionEvent.ACTION_CANCEL:
    case MotionEvent.ACTION_UP:
     if (canZoom)
      restroe();//还原pullZoomImage动画
     if (needRefresh && refreshListener != null) {//达到刷新条件并且实现刷新监听
      refreshListener.onRefresh();
      rotationProgress();//刷新时progress旋转动画
     } else
      refreshProgress.setVisibility(GONE);
     //重置变量
     needRefresh = false;
     canZoom = false;
     break;

   }
   return false;
  }
 };

缩放imageview

 /*放大pullZoomImage*/
 protected boolean zoomView(MotionEvent ev) {
  float offY = ev.getY() - pressY;
  if (offY <= 0 || offY < 16)//滑动方向上滑或者滑动距离小于16则不管
   return false;
  /*如果开启下拉刷新判断滑动距离是否大于refrshSlop则显示refreshProgress*/
  if (refreshEnable) {
   needRefresh = offY >= refrshSlop;
   if (needRefresh)
    refreshProgress.setVisibility(VISIBLE);
  }
  ViewGroup.LayoutParams params = pullZoomImage.getLayoutParams();
  float height = originalParams.height + offY / damp;//根据滑动距离增加pullZoomImage的高度
  params.height = (int) height;
  scaleImage(height);//放大图片
  rotationProgress(offY);//旋转refreshProgress
  if (params.height >= originalParams.height)
   pullZoomImage.setLayoutParams(params);//为pullZoomImage设置改变后的params
  return true;
 }
 /*缩放imageview*/
 protected void scaleImage(float height) {
//  if (pullZoomImage.getScaleType() == ImageView.ScaleType.CENTER_CROP)
//   return;
  float scale = (height - originalParams.height) / originalParams.height;//根据滑动的大小判断缩放比例
  pullZoomImage.setScaleX(1 + scale);
  pullZoomImage.setScaleY(1 + scale);
 }

抬手后通过属性动画还原pullZoomImage

 /*放开后还原pullZoomImage*/
 protected void restroe() {
  ValueAnimator animator = ValueAnimator.ofFloat(pullZoomImage.getLayoutParams().height, originalParams.height);// 动画更新的监听
  animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

   @Override
   public void onAnimationUpdate(ValueAnimator arg0) {
    float height = (float) arg0.getAnimatedValue();// 获取动画当前变化的值
    // 根据最新高度,更新布局高度
    ViewGroup.LayoutParams params = pullZoomImage.getLayoutParams();
    params.height = (int) height;
    scaleImage(height);
    pullZoomImage.setLayoutParams(params);
   }
  });
  animator.setDuration(200);// 动画时间
  animator.start();// 开启动画
 }

大致原理就是这样最后传送门开启 PullZoomLayout

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

(0)

相关推荐

  • android教你打造独一无二的上拉下拉刷新加载框架

    其实早在去年七月,群里小伙伴就有让我共享这个.但我当时绝的技术不纯熟.代码有bug什么的.没有写出来.现在感觉整理的差不多了.就写出来让大家看看,有问题一起讨论解决. 说到刷新加载,我们第一个想到啥,对了就是swiperefreshlayout,还有什么SuperSwiperefreshlayout,XRecyclerView等等.反正老多了,我还是之前那句话,不管用什么,我们需要知道他的原理. 打造框架开始 对于刷新加载的实现,你们第一个想到的是什么?是用swiperefresh然后在recy

  • Android自定义控件实现下拉刷新效果

    app开发中下拉刷新是最常接触到的一个功能,也有很多开源的框架,封装的非常棒.前段时间了解了一下ViewDragHelper,遂用它实现了下拉刷新的功能. 大概和我之前的ViewDragHelper之拖动加载(类似淘宝)这篇代码类似.只是做了相关改动.具体的可以看一下那篇博文了解一下用到的ViewDragHelper的一些知识点.该界面主要是一个LinearLayout,上面的下拉刷新是一个textview(用TV代替),当然这个可以定制,在此只是用一个textview代替,实现简单的功能,下面

  • Android微信端的下拉刷新功能

    在Android和iOS上对于下拉刷新的处理方法: 在微信公众号内,在面对下拉刷新这个问题上,Android和iOS都自己的表现方式: iOS: Android: 所以我们要给内容加载监听器 function bindEvent() { document.addEventListener('touchstart', touchSatrtFunc, false); document.addEventListener('touchmove', touchMoveFunc, false); docum

  • Android实现RecyclerView下拉刷新效果

    本文为大家分享了Android实现RecyclerView下拉刷新效果的具体代码,供大家参考,具体内容如下 思路 RealPullRefreshView继承了一个LinearLayout 里面放置了一个刷新头布局,将其margin_top设置为负的刷新头的高度的 再添加一个RecyclerView 触摸事件分发机制,当在特定条件下让RealPullRefreshView拦截触摸事件,否则的话,不拦截,让RecyclerView自己去处理触摸事件 在手指下拉时,定义好不同的状态STATE,在不同状

  • Android下拉刷新PtrFrameLayout的使用实例代码

    1.介绍: 可以包含所有的控件 :ListView, GridView, ScrollView, FrameLayout, 甚至 TextView. 可以自定义刷新头(这点非常实用) 使用简单方便 不足就是不支持上拉加载. 2.使用 首先添加依赖到项目 compile 'in.srain.cube:ultra-ptr:1.0.11' 在Xml中使用 <in.srain.cube.views.ptr.PtrFrameLayout xmlns:android="http://schemas.a

  • Android中ListView下拉刷新的实现代码

    Android中ListView下拉刷新 实现效果图: ListView中的下拉刷新是非常常见的,也是经常使用的,看到有很多同学想要,那我就整理一下,供大家参考.那我就不解释,直接上代码了. 这里需要自己重写一下ListView,重写代码如下: package net.loonggg.listview; import java.util.Date; import android.content.Context; import android.util.AttributeSet; import a

  • Android RecyclerView设置下拉刷新的实现方法

    Android RecyclerView设置下拉刷新的实现方法 1 集成 SwipeRefreshLayout 1.1 xml布局文件中使用 <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/refresh" android:layout_width = "match_parent" android:layout_height = "match_parent" &g

  • Android SwipereFreshLayout下拉刷新

    Android SwipereFreshLayout下拉刷新 我们都知道现在android5.0以后就提倡使用Material Design设计了.在Material Design设计就有一个非常好的设计SwipereFreshLayout,下面我们就来看看它的使用.既然它来源于Material Design,我们第一步就应该是添加它的库. 1.我们就在build.gradle添加库: compile 'com.android.support:support-v4:22.1.1' 2.然后我们就

  • Android自定义实现顶部粘性下拉刷新效果

    本文实例为大家分享了Android实现顶部粘性下拉刷新效果的具体代码,供大家参考,具体内容如下 学习:视频地址 activity_view_mv代码 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://sche

  • Android简洁的下拉放大刷新效果示例

    序言 国庆放假过后眼看一年又要过完了,年初指望着已经有一年的经验本以为自己不是刚出校的学生以为翅膀已经硬了,打算辞职换新工作,一面试才发现自己就是个垃圾,什么oninterceptEvent,dispatchTouchEvent ,Aysnctask都不会.做了一年的项目也是用的Xutils2.6版本 还有一堆不常用不好的不主流不时尚的框架,技术也没任何长进.还好公司真的轻松(所以也学不到任何东西)可以趁闲下来的时间多学点东西.于是写了个简单但也有需求的控件练练手. 首先先看效果图吧 这个是li

  • android ScrollView实现下拉放大头部图片

    前言 之前做项目的时候,需要实现类似微博个人主页的ScrollView效果,就是到顶部时继续下拉会放大顶部的图片.然后在网上找了一篇相关的实现,效果非常好,代码也很简洁易懂.(传送门: 自定义scrollView实现顶部图片下拉放大),那么我这里就只是在其基础上修改了一点点而已,比如在代码中控制图片居中.增加动态设置放大的控件.使用自定义的最大放大倍数等,都是很简单的修改,还添加了滑动的监听回调(项目需要). 效果如下: 思路 老样子,我们先来说下思路,比起代码,思路才是最重要的.具体步骤如下:

  • jquery实现的下拉和收缩效果示例

    下拉和收缩类似的效果应用非常的频繁,本章节简单介绍一下如何实现此效果. 代码实例如下: <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta name="author" content="http://www.softwhy.com/" /> <head> <title>蚂蚁部落</title

  • Android实现下拉放大图片松手自动反弹效果

    本文实例为大家分享了Android实现下拉放大图片松手自动反弹的具体代码,供大家参考,具体内容如下 直接看效果: 下面就是代码 HeadZoomScrollView类 import android.animation.ValueAnimator; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; i

  • Android 实现的下拉刷新效果

    下面是自己实现的效果: 1.分析 可以将动画分解成: 睁眼毛驴绕着中心地球旋转,并且在到达地球中心时,切换为闭眼毛驴,最后发射出去 地球自我旋转,随着下拉而缓缓上升,达到半径距离后停止上升 一颗上下来回移动的卫星 2.实现 (1)下载赶集app,然后将其后缀名改为zip解压获取我们需要的资源图片: (2) 我们先实现卫星的上下移动 核心代码: @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Matrix

  • Android中ListView下拉刷新的实现方法实例分析

    本文实例讲述了Android中ListView下拉刷新的实现方法.分享给大家供大家参考,具体如下: ListView中的下拉刷新是非常常见的,也是经常使用的,看到有很多同学想要,那我就整理一下,供大家参考.那我就不解释,直接上代码了. 这里需要自己重写一下ListView,重写代码如下: package net.loonggg.listview; import java.util.Date; import android.content.Context; import android.util.

  • Android中Listview下拉刷新和上拉加载更多的多种实现方案

    listview经常结合下来刷新和上拉加载更多使用,本文总结了三种常用到的方案分别作出说明. 方案一:添加头布局和脚布局 android系统为listview提供了addfootview和addheadview两个API.这样可以直接自定义一个View,以添加视图的形式实现下来刷新和上拉加载. 实现步骤    1.创建一个类继承ListView:class PullToRefreshListView extends ListView: 2.在构造方法中添加HeadView:addHeaderVi

  • 安卓(android)怎么实现下拉刷新

    这里我们将采取的方案是使用组合View的方式,先自定义一个布局继承自LinearLayout,然后在这个布局中加入下拉头和ListView这两个子元素,并让这两个子元素纵向排列.初始化的时候,让下拉头向上偏移出屏幕,这样我们看到的就只有ListView了.然后对ListView的touch事件进行监听,如果当前ListView已经滚动到顶部并且手指还在向下拉的话,那就将下拉头显示出来,松手后进行刷新操作,并将下拉头隐藏.那我们现在就来动手实现一下,新建一个项目起名叫PullToRefreshTe

随机推荐