欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-12-05 15:13:46
本文实例为大家分享了android实现顶部粘性下拉刷新效果的具体代码,供大家参考,具体内容如下 学习: activity_view_mv代码 <...

本文实例为大家分享了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://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>

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