此次牵扯到的知识点有:Android手势,Handler,java多线程,java聚合,Android帧动画,属性动画;

如果有对上述提到过的知识点不太了解,或者编程能力较差的小伙伴可以关闭此页面啦一,因为接下来的装逼过程

你可能会是一脸懵B 。如果你执意要看也没事啦,因为代码里面我写了足够详细的注释,如果你努力用心去看的话

,我相信你还是能看懂滴!
                                       

本源码已经上传至GitHub,有兴趣的小伙伴欢迎欢迎对本插件进行改进和升级

Github源码下载地址

都让开,我要开始装逼了

装逼图:

由于代码里面的注释写的非常详细,我就只简单的描述一下步骤吧!


1、我们先创建一个下拉出来的布局xml文件;文件名:listview_head_layout.xml

<?xml version="1.0" encoding="utf-8"?>                                                                                                        


2、然后定义相关的动画xml;
圆形帧动画滚动条:progress.xml
这里图片大家就自己去找吧,百度上一大把的

<?xml version="1.0" encoding="utf-8"?>                                                


下拉箭头旋转动画:
  pullimage.xml(箭头向上旋转)
<?xml version="1.0" encoding="utf-8"?>    

pullimage.xml(箭头向下旋转)    
<?xml version="1.0" encoding="utf-8"?>    


3、创建一个CustomListView类,继承ListView(详细实现思路请看代码);

package com.example.zking.example;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.drawable.AnimationDrawable;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.animation.Animation;import android.view.animation.AnimationUtils;import android.widget.ImageView;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.TextView;/** * Created by Administrator on 2017/7/25 0025. */public class CustomListView extends ListView {    //记录刷新状态  1 刷新前、2 刷新中、3刷新成功    private static int refreshState=1;    //刷新监听事件接口    private OnRefreshListener listener=null;    //刷新动画    private AnimationDrawable animDra;    private Context context;    //下拉的HeaderView    private View headView;    //HeaderView的高度    private int headViewHeight;    //下拉提示语    private TextView pullText;    private TextView progress_Text;    //刷新图标    private ImageView pullImage;    private ImageView progress_bar;    //控制高度的布局    private RelativeLayout pullLayout;    //布局管理器    private ViewGroup.LayoutParams lp;    //标记标签    //记录是否第一次改变高度    boolean firstFlag=true;    //记录改变下拉图标的状态    boolean changePullImageFlag=true;        //按下的Y轴 释放的Y轴 下拉高度(按下-释放)    float flagYDown,flagYMove,flagY;    //定义一个Handler来处理子线程给我们返回的信息    Handler myHandler=new Handler(){        @Override        public void handleMessage(Message msg) {             switch(msg.what){                 case 1:                     progress_Text.setText("刷新成功!");                     animDra.stop();                     progress_bar.setBackgroundResource(R.drawable.obu);                     break;                 case 2:                     //状态设为 刷新完毕                     refreshState=3;                     changeViewHeight(headViewHeight,0);                     if(listener!=null){                         listener.refreshAfter(CustomListView.this);                     }                     break;             }        }    };    public CustomListView(Context context) {        super(context);    }    public CustomListView(Context context, AttributeSet attrs) {        super(context, attrs);        this.context=context;        headView=(View)LayoutInflater.from(context).inflate(R.layout.listview_head_layout,null);        pullLayout=(RelativeLayout) headView.findViewById(R.id.pullLayout);        lp=pullLayout.getLayoutParams();        headView.addOnLayoutChangeListener(new OnLayoutChangeListener() {            @Override            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {                //判断是否是第一次改变布局,如果是的话,则把布局的高度设为0                if(firstFlag){                    headViewHeight=v.getHeight();                    lp.height=0;                    pullLayout.setLayoutParams(lp);                    firstFlag=false;                }            }        });        //设置HeaderView        this.addHeaderView(headView);        initHeadView();    }    //初始化控件    void initHeadView(){        //圆形刷新动画        animDra = (AnimationDrawable) headView.findViewById(R.id.progress_bar).getBackground();        //圆形刷新图标        progress_bar=(ImageView) headView.findViewById(R.id.progress_bar);        //刷新提示文本        progress_Text=(TextView) headView.findViewById(R.id.progress_Text);        //下滑的提示文本        pullText=(TextView)headView.findViewById(R.id.pullText);        //下滑箭头图标        pullImage=(ImageView)headView.findViewById(R.id.refreshIcon);    }    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        //判断是否是最顶部和是否处于刷新状态        if(this.getFirstVisiblePosition()==0&&refreshState!=2){        switch(ev.getAction()){            case MotionEvent.ACTION_DOWN://手指按下时                flagYDown=ev.getY();                //按下时隐藏圆形进度条和提示文本,显示下拉箭头图、提示文本                progress_bar.setVisibility(View.GONE);                progress_Text.setVisibility(View.GONE);                pullText.setVisibility(View.VISIBLE);                pullImage.setBackgroundResource(R.drawable.rjd_down);                refreshState=1;                if(listener!=null){                    listener.refreshBefore(CustomListView.this);                }                break;            case MotionEvent.ACTION_MOVE://手指滑动时                this.setSelection(0);                flagYMove=ev.getY();                //下拉的高度                flagY=(float)((flagYMove-flagYDown)*0.3);//这里*0.3是设置下拉的难易度,*的数越大越容易下拉                //判断下拉的高度是否大于ListView头布局原始的高度                if(flagY>headViewHeight){                    pullText.setText("松开立即刷新");                    //设置上下小箭头的旋转动画                    //changePullImageFlag,设置一个标签,防止多次设置动画,当下拉的高宽改变时才设置动画                    if(changePullImageFlag){                        changePullIconAnimation(1,pullImage);                        changePullImageFlag=false;                    }                }else{                    pullText.setText("下拉刷新");                    if(changePullImageFlag==false){                        changePullIconAnimation(0,pullImage);                        changePullImageFlag=true;                    }                }                //判断一下下拉的高度是否大于0               if(flagY>0){                       lp.height=(int)flagY;                       pullLayout.setLayoutParams(lp);                }                break;            case MotionEvent.ACTION_UP://手指放开时                //判断下拉的高度是否大于ListView头布局原始的高度                if(flagY>headViewHeight){                    pullText.setVisibility(View.GONE);                    pullImage.setBackgroundResource(R.color.pullImage);                    //将圆形进度条,和提示文字显示出来                    progress_bar.setVisibility(View.VISIBLE);                    progress_Text.setVisibility(View.VISIBLE);                    progress_Text.setText("正在刷新...");                    //调用改变高度的缓冲动画的方法,并传入参数                    changeViewHeight(lp.height,headViewHeight);                    progress_bar.setBackgroundResource(R.drawable.progress_bar);                    animDra=(AnimationDrawable) progress_bar.getBackground();                    animDra.start();                    //将状态设置为 正在刷新                    refreshState=2;                    //调用正在刷新                    if(listener!=null){                        listener.refreshStart(CustomListView.this);                    }                }else{                        changeViewHeight(lp.height,0);                }                break;        }        }        return super.dispatchTouchEvent(ev);    }    //改变高度的缓冲动画           开始动画的高度     结束动画的高度    public void changeViewHeight(int startHeight,int endHeight){        ValueAnimator va;        //判断开始的高度和结束的高度是否大于30大于30就设置启用弹跳效果        if(startHeight>headViewHeight||startHeight<30){         va= ValueAnimator.ofInt(startHeight,endHeight);        }else{                                  //开始高度  结束高度 弹跳的高度  结束高度           va= ValueAnimator.ofInt(startHeight,endHeight,15,endHeight);        }        //监听动画改变的事件        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator valueAnimator) {                //获取当前的height值                int h =(Integer)valueAnimator.getAnimatedValue();                //动态更新高度                lp.height=h;                pullLayout.setLayoutParams(lp);            }        });        va.setDuration(200);        //开始动画        va.start();    }   //  改变下拉箭头图标动画           状态  0转上去(松开立即刷新) 1转下来(下拉刷新)    public void changePullIconAnimation(int state,ImageView view){        Animation anim;        if(state==1){            anim=AnimationUtils.loadAnimation(this.getContext(),R.anim.pullimage);        }else{            anim=AnimationUtils.loadAnimation(this.getContext(),R.anim.pullimage_down);        }        anim.setFillAfter(true);        view.startAnimation(anim);    }    //设置刷新监听    public void setOnRefreshListener(OnRefreshListener listener){        this.listener=listener;    }}


4、创建一个接口用来作为我们CustomListView类的刷新监听接口;

package com.example.zking.example;/** * Created by Administrator on 2017/7/29 0029. */public interface OnRefreshListener {    public void refreshBefore(CustomListView civ);//刷新前    public void refreshAfter(CustomListView civ);//刷新后    public void refreshStart(CustomListView civ);//开始刷新}

5、在我们展示的xml里面设置我们自定义的CustomListView,使用方法和ListView一样;

<?xml version="1.0" encoding="utf-8"?>        
6、在java类里面进行找出我们定义的CustomListView,为它初始出一些数据,然后再设置监听方法即可
package com.example.zking.example;import android.graphics.drawable.AnimationDrawable;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.view.animation.Animation;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.ImageView;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.Toast;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity {    CustomListView clv;    List list = new ArrayList();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        clv=(CustomListView)findViewById(R.id.customLV);        initDataSource();        clv.setAdapter(new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,list));        //设置刷新监听事件        clv.setOnRefreshListener(new OnRefreshListener() {            @Override            public void refreshBefore(CustomListView civ) {            }            @Override            public void refreshAfter(CustomListView civ) {            }            @Override            public void refreshStart(final CustomListView civ) {                //这里new一个线程,用于模仿网络刷新请求时长                new Thread(){                    @Override                    public void run() {                        try {                            this.sleep(4000);                            civ.myHandler.sendEmptyMessage(1);                            this.sleep(1000);                            clv.myHandler.sendEmptyMessage(2);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                    }                }.start();            }        });    }    //初始数据    public void initDataSource() {        for (int i = 0; i <30; i++) {            list.add("a" + i);        }    }}   

呼呼,好啦   老夫已装完逼。接下来大伙儿去消化消化吧。


如需源码和素材的小伙伴,可以加我的QQ2557606319,添加好友时验证消息记得填写“CSDN”。








更多相关文章

  1. Android(安卓)View 的刷新机制
  2. Android使用Sensor感应器实现线程中刷新UI创建android测力计的功
  3. UWP与Android中如何在多线程中刷新UI
  4. Android:通过ValueAnimator动画改变控件长宽失效的问题解决
  5. Android各种键盘挡住输入框解决办法
  6. android根据屏幕高度改变item占ListView高度
  7. Android高仿网易新闻客户端之动态添加标签
  8. android:屏幕自适应
  9. 安卓开发定时刷新界面

随机推荐

  1. android 显示Gift图片
  2. Android播放视频(一)
  3. Android 创建Kotlin项目出现 Could not d
  4. Include Native *.so Library in APK Wit
  5. ProGuard用法
  6. android content命令
  7. [置顶] 我的Android进阶之旅------>Andro
  8. 生成android的bks证书
  9. 仿微信摇一摇功能,android 重力感应开发
  10. [Android 界面] Android: 自定义DIALOG