当前位置: 移动技术网 > IT编程>移动开发>Android > Android自定义实现顶部粘性下拉刷新效果

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

李浩修,株洲草根网,马拉松的长度

本文实例为大家分享了android实现顶部粘性下拉刷新效果的具体代码,供大家参考,具体内容如下

学习:

activity_view_mv代码

<?xml version="1.0" encoding="utf-8"?>
<relativelayout
  xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:id="@+id/rl_view"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
 >

  <trunk.doi.base.ui.activity.test.touchpullview
   android:id="@+id/cs_view"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   app:pcolor="@color/cff3e19"
   app:pcontentdrawable="@drawable/shape_circle"
   app:pcontentdrawablemargin="2dp"
   app:pdragheight="100dp"
   app:ptangentangle="110"
   app:pradius="15dp"
   app:ptargetgravityheight="4dp"
   app:ptargetwidth="200dp"
   />
  <trunk.doi.base.ui.activity.test.testviewbezer
   android:layout_width="match_parent"
   android:visibility="gone"
   android:layout_height="wrap_content"
   />

</relativelayout>

viewmvactivity代码

import android.os.bundle;
import android.support.annotation.nullable;
import android.view.motionevent;
import android.view.view;
import android.widget.relativelayout;

import butterknife.bindview;
import trunk.doi.base.r;
import trunk.doi.base.base.baseactivity;

public class viewmvactivity extends baseactivity {


 @bindview(r.id.cs_view)
 touchpullview csview;
 @bindview(r.id.rl_view)
 relativelayout rl_view;

 private float mtouchstarty;
 private static final float touch_move_max_y=600;

 @override
 protected int initlayoutid() {
  return r.layout.activity_view_mv;
 }

 @override
 protected void initview(@nullable bundle savedinstancestate) {

  rl_view.setontouchlistener(new view.ontouchlistener() {
   @override
   public boolean ontouch(view v, motionevent event) {

    int action=event.getactionmasked();
    switch (action){

     case motionevent.action_down:

      mtouchstarty=event.gety();

      return true;
     case motionevent.action_move:
      float y=event.gety();
      if(y>=mtouchstarty){
       float movesize= y-mtouchstarty;
       float progress=movesize>=touch_move_max_y?1:movesize/touch_move_max_y;
       csview.setprogress(progress);
      }
      return true;
     case motionevent.action_up:

      csview.release();

      return true;

     default:
      break;

    }


    return false;
   }
  });

 }

 @override
 protected void setlistener() {

 }

 @override
 protected void initdata() {

 }


}

touchpullview代码

import android.animation.valueanimator;
import android.content.context;
import android.content.res.typedarray;
import android.graphics.canvas;
import android.graphics.paint;
import android.graphics.path;
import android.graphics.drawable.drawable;
import android.os.build;
import android.support.annotation.nullable;
import android.support.annotation.requiresapi;
import android.support.v4.view.animation.pathinterpolatorcompat;
import android.util.attributeset;
import android.util.log;
import android.view.view;
import android.view.animation.decelerateinterpolator;
import android.view.animation.interpolator;

import trunk.doi.base.r;

/**
 * 作者:mr.lee on 2017-9-27 11:57
 * 邮箱:569932357@qq.com
 */

public class touchpullview extends view {

 //圆的画笔
 private paint mcirclepaint;
 //圆的半径
 private int mcircleradius=50;
 private float mcirclepointx;
 private float mcirclepointy;
 private float mprogress;
 //可拖拽高度
 private int mdragheigh=800;
 //目标宽度
 private int mtargetwidth=400;
 //贝塞尔曲线
 private path mpath=new path();
 private paint mpathpaint;
 //重心点最终高度,决定控制点的y坐标
 private int mtargetgravityheight=10;
 //角度变换 0-135
 private int mtangentangle=100;
 private interpolator mprogressinterpolator=new decelerateinterpolator();
 private interpolator mtanentangleinterpolator;

 private drawable mcontent=null;
 private int mcontentmargin=0;


 public touchpullview(context context) {
  super(context);
  init(null);

 }

 public touchpullview(context context, @nullable attributeset attrs) {
  super(context, attrs);
  init(attrs);
 }

 public touchpullview(context context, @nullable attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);
  init(attrs);
 }

 @requiresapi(api = build.version_codes.lollipop)
 public touchpullview(context context, @nullable attributeset attrs, int defstyleattr, int defstyleres) {
  super(context, attrs, defstyleattr, defstyleres);
  init(attrs);
 }

 /**
  * 初始化
  */
 private void init(attributeset attrs){


  final context context=getcontext();
  typedarray array=context.obtainstyledattributes(attrs, r.styleable.touchpullview,0,0);
  int color=array.getcolor(r.styleable.touchpullview_pcolor,0x20000000);

  mcircleradius=(int)array.getdimension(r.styleable.touchpullview_pradius,mcircleradius);
  mdragheigh=array.getdimensionpixeloffset(r.styleable.touchpullview_pdragheight,mdragheigh);
  mtangentangle=array.getinteger(r.styleable.touchpullview_ptangentangle,mtangentangle);
  mtargetwidth=array.getdimensionpixeloffset(r.styleable.touchpullview_pdragheight,mtargetwidth);
  mtargetgravityheight=array.getdimensionpixeloffset(r.styleable.touchpullview_ptargetgravityheight,mtargetgravityheight);
  mcontent=array.getdrawable(r.styleable.touchpullview_pcontentdrawable);
  mcontentmargin=array.getdimensionpixeloffset(r.styleable.touchpullview_pcontentdrawablemargin,0);
  array.recycle();

  paint p=new paint(paint.anti_alias_flag);
  //抗锯齿
  p.setantialias(true);
  //防抖动
  p.setdither(true);
  //填充方式
  p.setstyle(paint.style.fill);
  p.setcolor(color);
  mcirclepaint=p;
  //初始化路径部分画笔
  p=new paint(paint.anti_alias_flag);
  //抗锯齿
  p.setantialias(true);
  //防抖动
  p.setdither(true);
  //填充方式
  p.setstyle(paint.style.fill);
  p.setcolor(color);
  mpathpaint=p;

  //切角路径插值器
  mtanentangleinterpolator= pathinterpolatorcompat.create(
    (mcircleradius*2.0f)/mdragheigh,
    90.0f/mtangentangle
  );

 }

 @override
 protected void onsizechanged(int w, int h, int oldw, int oldh) {
  super.onsizechanged(w, h, oldw, oldh);
  updatepathlayout();

 }

 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
//  super.onmeasure(widthmeasurespec, heightmeasurespec);

  int widthmode=measurespec.getmode(widthmeasurespec);
  int width=measurespec.getsize(widthmeasurespec);
  int heighmode=measurespec.getmode(heightmeasurespec);
  int heigh=measurespec.getsize(heightmeasurespec);

  int iheigh=(int)((mdragheigh*mprogress+0.5)+ 2*mcircleradius+getpaddingtop()+getpaddingbottom());
  int iwidth=2*mcircleradius+getpaddingleft()+getpaddingright();
  int measurewidth,measureheigh;

  if(widthmode==measurespec.exactly){
   measurewidth=width;
  }else if(widthmode==measurespec.at_most){
   measurewidth=math.min(iwidth,width);
  }else{
   measurewidth=iwidth;
  }

  if(heighmode==measurespec.exactly){
   measureheigh=heigh;
  }else if(heighmode==measurespec.at_most){
   measureheigh=math.min(iheigh,heigh);
  }else{
   measureheigh=iheigh;
  }

  setmeasureddimension(measurewidth,measureheigh);

 }

 @override
 protected void ondraw(canvas canvas) {
  super.ondraw(canvas);
  int count=canvas.save();
  float tranx=(getwidth()-getvaluebyline(getwidth(),mtargetwidth,mprogress))/2;
  canvas.translate(tranx,0);
  canvas.drawpath(mpath,mpathpaint);
  //画圆
  canvas.drawcircle(mcirclepointx,mcirclepointy,mcircleradius,mcirclepaint);
  drawable drawable=mcontent;
  if(drawable!=null){
   canvas.save();
   //剪切矩形区域
   canvas.cliprect(drawable.getbounds());
   //绘制
   drawable.draw(canvas);
   canvas.restore();
  }
  canvas.restoretocount(count);


 }



 /**
  * 设置进度
  * @param progress
  */
 public void setprogress(float progress){

  log.e("tag","progress="+progress);
  mprogress=progress;
  //重新请求测量
  requestlayout();


 }


 private void updatepathlayout(){

  final float progress=mprogressinterpolator.getinterpolation(mprogress);
  //获取可绘制区域高度宽度
  final float w=getvaluebyline(getwidth(),mtargetwidth,mprogress);
  final float h=getvaluebyline(0,mdragheigh,mprogress);

  //x对称轴的参数,圆的圆心x
  final float cpointx=w/2;
  //圆的半径
  final float cradius=mcircleradius;
  //圆的圆心y坐标
  final float cpointy =h-cradius;
  //控制点结束y坐标
  final float endcontroly=mtargetgravityheight;

  mcirclepointx=cpointx;
  mcirclepointy= cpointy;

  final path path=mpath;
  //重置
  path.reset();
  path.moveto(0,0);

  //左边部分的结束点和控制点
  float lendpointx,lendpointy;
  float lcontrolpointx,lcontrolpointy;
  //角度转弧度

  float angle=mtangentangle*mtanentangleinterpolator.getinterpolation(progress);
  double radian=math.toradians(angle);
  float x=(float) (math.sin(radian)*cradius);
  float y=(float) (math.cos(radian)*cradius);

  lendpointx=cpointx-x;
  lendpointy= cpointy +y;

  //控制点y坐标变化
  lcontrolpointy=getvaluebyline(0,endcontroly,progress);
  //控制点与结束定之前的高度
  float theigh=lendpointy-lcontrolpointy;
  //控制点与x坐标的距离
  float twidth= (float) (theigh/math.tan(radian));
  lcontrolpointx=lendpointx-twidth;
  //左边贝塞尔曲线
  path.quadto(lcontrolpointx,lcontrolpointy,lendpointx,lendpointy);
  //连接到右边
  path.lineto(cpointx+(cpointx-lendpointx),lendpointy);
  //右边贝塞尔曲线
  path.quadto(cpointx+cpointx-lcontrolpointx,lcontrolpointy,w,0);
  //更新内容部分drawable
  updatecontentlayout(cpointx,cpointy,cradius);

 }

 /**
  * 对内容部分进行测量并设置
  * @param cx
  * @param cy
  * @param radius
  */
 private void updatecontentlayout(float cx,float cy,float radius){

  drawable drawable=mcontent;
  if(drawable!=null){
   int margin=mcontentmargin;
   int l=(int)(cx-radius+margin);
   int r=(int)(cx+radius-margin);
   int t=(int)(cy-radius+margin);
   int b=(int)(cy+radius-margin);
   drawable.setbounds(l,t,r,b);
  }

 }

 //释放动画
 private valueanimator valueanimator;

 /**
  * 添加释放动作
  */

 public void release(){

  if(valueanimator==null){

   valueanimator animator=valueanimator.offloat(mprogress,0f);
   animator.setinterpolator(new decelerateinterpolator());
   animator.setduration(400);
   animator.addupdatelistener(new valueanimator.animatorupdatelistener() {
    @override
    public void onanimationupdate(valueanimator animation) {

     object val=animation.getanimatedvalue();
     if(val instanceof float){
      setprogress((float) val);
     }

    }
   });
   valueanimator=animator;

  }else{

   valueanimator.cancel();
   valueanimator.setfloatvalues(mprogress,0f);

  }
  valueanimator.start();


 }

 /**
  * 获取当前值
  * @param start
  * @param end
  * @param progress
  * @return
  */
 private float getvaluebyline(float start,float end ,float progress){
  return start+(end-start)*progress;
 }
 }

testviewbezer代码

import android.content.context;
import android.graphics.canvas;
import android.graphics.paint;
import android.graphics.path;
import android.os.build;
import android.support.annotation.nullable;
import android.support.annotation.requiresapi;
import android.util.attributeset;
import android.view.view;

/**
 * 作者:mr.lee on 2017-9-27 18:08
 * 邮箱:569932357@qq.com
 */

public class testviewbezer extends view {

 private paint mpaint=new paint(paint.anti_alias_flag);
 private path mpath=new path();

 public testviewbezer(context context) {
  super(context);
  init();
 }

 public testviewbezer(context context, @nullable attributeset attrs) {
  super(context, attrs);
  init();
 }

 public testviewbezer(context context, @nullable attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);
  init();
 }

 @requiresapi(api = build.version_codes.lollipop)
 public testviewbezer(context context, @nullable attributeset attrs, int defstyleattr, int defstyleres) {
  super(context, attrs, defstyleattr, defstyleres);
  init();
 }

 private void init(){


  paint paint=mpaint;
  paint.setantialias(true);
  paint.setdither(true);
  mpaint.setcolor(0xff000000);
  paint.setstyle(paint.style.stroke);
  paint.setstrokewidth(10);

  path path=mpath;
  path.moveto(100,100);
  path.lineto(400,400);

  path.quadto(600,100,800,400);

  path.moveto(400,800);
  path.cubicto(500,600,700,1200,800,800);


 }

 @override
 protected void ondraw(canvas canvas) {
  super.ondraw(canvas);
  canvas.drawpath(mpath,mpaint);
  canvas.drawpoint(600,100,mpaint);
  canvas.drawpoint(500,600,mpaint);
  canvas.drawpoint(700,1200,mpaint);

 }
}

attr_pull.xml代码

 <declare-styleable name="touchpullview">
  <attr name="pcolor" format="color" />
  <attr name="pradius" format="dimension" />
  <attr name="pdragheight" format="dimension"></attr>
  <attr name="ptangentangle" format="integer" />
  <attr name="ptargetwidth" format="dimension" />
  <attr name="ptargetgravityheight" format="dimension" />
  <attr name="pcontentdrawable" format="reference" />
  <attr name="pcontentdrawablemargin" format="dimension" />
 </declare-styleable>

shape_circle代码

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
 android:shape="oval"
 >
 <solid android:color="#fff" />
</shape>

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网