打造自己的RecylerView,GridView,ListView...下拉刷新和上啦加载的动画真的很简单。

一,自定义自己项目的刷新效果:

很多时候我们项目也许需要自己的刷新效果。如果我们达不到那种自定义刷新控件的力,那么来看看这篇文章吧!!!基于(TwinklingRefreshLayout和SwipeToLoadLayout)都是给变头布局来实现的。

二,看看我们公司的需求:

刚下拉时候,有一个小医生慢慢出现变大变亮,后面一个下拉刷新的文字,当松开手时候文字变
为正在刷新中。
上啦加载时候:同样一个医生出现变大变亮。

这里写图片描述

三,实现过程:
1,需要很多的图片你不会ps么?找美工吧。反正我会我自己ps搞的图片但时候在项目中有的。
来个图片不然你们不信:我把48x48最为最大,然后ps图像大小然后逐个变小储存。
这里写图片描述
2,我们来新建一个项目吧!然后进入gradle里面写去依赖这句话
compile ‘com.lcodecorex:tkrefreshlayout:1.0.3’就可以用TwinklingRefreshLayout了。

3,我们来进行基本的布局和适配器吧这个都会的。
布局:

<?xml version="1.0" encoding="utf-8"?>
<com.lcodecore.tkrefreshlayout.TwinklingRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:id="@+id/refreshLayout"
    android:scrollbars="none"
    android:layout_height="match_parent"
    >

    <android.support.v7.widget.RecyclerView
        android:background="#ffffff"
        android:layout_below="@+id/ling_item1"
        android:id="@+id/activity_last_infor_rv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</com.lcodecore.tkrefreshlayout.TwinklingRefreshLayout>

适配器:

/**
 * Created by ls on 2017/11/14.
 */

public class LastInforAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context mContext;
    private List<String> mData;

    public LastInforAdapter(Context mContext, List<String> mData) {
        this.mContext = mContext;
        this.mData = mData;
    }

    @Override
    public int getItemCount() {
        return mData == null ? 0 : mData.size();
    }


    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.my_item, null);
        FirstViewHolder holder = new FirstViewHolder(view, mContext);
        return holder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        FirstViewHolder holder1 = (FirstViewHolder) holder;
        holder1.setData(mData.get(position), position);
    }

    class FirstViewHolder extends RecyclerView.ViewHolder {
        private Context mContex;
        private TextView first_view;

        public FirstViewHolder(View itemView, Context mContex) {
            super(itemView);
            this.mContex = mContex;
            first_view=itemView.findViewById(R.id.tv_my);

        }

        public void setData(String str, final int position) {
           first_view.setText(str);
        }
    }
}

最重要的来了。一个好的开源框架不可能不提供给开发者拓展的接口。那么我们去看看源码呗:

首先我们直接运行我们会发现有默认的刷新效果如下:

这里写图片描述

这里写图片描述

既然有默认的我们可以点击该控件进去看看源码:
我们会发现一些熟悉的变量:

 //子控件
    private View mChildView;

    //头部layout
    protected FrameLayout mHeadLayout;

    private IHeaderView mHeadView;
    private IBottomView mBottomView;

    //底部高度
    private float mBottomHeight;

    //底部layout
    private FrameLayout mBottomLayout;


    //刷新的状态
    protected boolean isRefreshing;

    //加载更多的状态
    protected boolean isLoadingmore;

    //是否需要加载更多,默认需要
    protected boolean enableLoadmore = true;
    //是否需要下拉刷新,默认需要
    protected boolean enableRefresh = true;

    //是否在越界回弹的时候显示下拉图标
    protected boolean isOverlayRefreshShow = true;

其中有一个

//头部layout
    protected FrameLayout mHeadLayout;

我们看注释就知道头部的layout,然后我们顺藤摸瓜,找到这里:

 //添加头部
        if (mHeadLayout == null) {
            FrameLayout headViewLayout = new FrameLayout(getContext());
            LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
            layoutParams.gravity = Gravity.TOP;
            headViewLayout.setLayoutParams(layoutParams);

            mHeadLayout = headViewLayout;

            this.addView(mHeadLayout);//addView(view,-1)添加到-1的位置

            if (mHeadView == null) setHeaderView(new GoogleDotView(getContext()));
        }

        //添加底部
        if (mBottomLayout == null) {
            FrameLayout bottomViewLayout = new FrameLayout(getContext());
            LayoutParams layoutParams2 = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
            layoutParams2.gravity = Gravity.BOTTOM;
            bottomViewLayout.setLayoutParams(layoutParams2);

            mBottomLayout = bottomViewLayout;
            this.addView(mBottomLayout);

            if (mBottomView == null) {
                BottomProgressView mProgressView = new BottomProgressView(getContext());
                setBottomView(mProgressView);
            }
        }

我看到这句话:

 if (mHeadView == null) setHeaderView(new GoogleDotView(getContext()));

当mHeadView为空时候我们看到有一个GoogleDotView(getContext())谷歌什么view控件来填充,我们
点进去看看呗,我们会发现我去,居然这里搞了那几个圆圈圈动画之类的:

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int w = getMeasuredWidth() / num - 10;
        for (int i = 0; i < num; i++) {
            if (animating) {
                switch (i) {
                    //                    case 0:
                    //                        mPath.setAlpha(35);
                    //                        mPath.setColor(getResources().getColor(R.color.Orange));
                    //                        canvas.drawCircle(getMeasuredWidth() / 2 - cir_x * 3 - 3 * w / 3 * 2, getMeasuredHeight() / 2, r*fraction2, mPath);
                    //                        break;
                    case 0:
                        mPath.setAlpha(105);
                        mPath.setColor(getResources().getColor(R.color.Yellow));
                        canvas.drawCircle(getMeasuredWidth() / 2 - cir_x * 2 - 2 * w / 3 * 2, getMeasuredHeight() / 2, r * fraction2, mPath);
                        break;
                    case 1:
                        mPath.setAlpha(145);
                        mPath.setColor(getResources().getColor(R.color.Green));
                        canvas.drawCircle(getMeasuredWidth() / 2 - cir_x * 1 - w / 3 * 2, getMeasuredHeight() / 2, r * fraction2, mPath);
                        break;
                    case 2:
                        mPath.setAlpha(255);
                        mPath.setColor(getResources().getColor(R.color.Blue));
                        canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, r * fraction1, mPath);
                        break;
                    case 3:
                        mPath.setAlpha(145);
                        mPath.setColor(getResources().getColor(R.color.Orange));
                        canvas.drawCircle(getMeasuredWidth() / 2 + cir_x * 1 + w / 3 * 2, getMeasuredHeight() / 2, r * fraction2, mPath);
                        break;
                    case 4:
                        mPath.setAlpha(105);
                        mPath.setColor(getResources().getColor(R.color.Yellow));
                        canvas.drawCircle(getMeasuredWidth() / 2 + cir_x * 2 + 2 * w / 3 * 2, getMeasuredHeight() / 2, r * fraction2, mPath);
                        break;
                    //                    case 6

我们发现这个GogleDotView实现了IHeaderView 接口,我们去看看吧:

public interface IHeaderView {
    View getView();

    /**
     * 下拉准备刷新动作
     * @param fraction  当前下拉高度与总高度的比
     * @param maxHeadHeight
     * @param headHeight
     */
    void onPullingDown(float fraction,float maxHeadHeight,float headHeight);

    /**
     * 下拉释放过程
     * @param fraction
     * @param maxHeadHeight
     * @param headHeight
     */
    void onPullReleasing(float fraction,float maxHeadHeight,float headHeight);

    void startAnim(float maxHeadHeight,float headHeight);

    void onFinish();
}

好了这里我一切都清除了,我们需要定义一个view类实现这个IHeaderView,和IBottomView接口或者内部类也可以的。这里我两种都搞一稿,必进写在activity内部扩展不太好。由于我太懒,我一个类就同时实现了这两个接口,其实这样感觉少一个类挺简洁的,你们根据自己的喜好弄吧。代码如下:

public class MyGoleView extends View implements IHeaderView, IBottomView {
    private Context mcontext;
    //这个是下拉式上部的显示文本
    private TextView refrush_tv;
    //最后给这个图片设置动画就可以了。
    private ImageView refrush_image;
    //设置帧动画用的
    private AnimationDrawable animationDrawable;
    //这个用来判断是下拉还是上拉
    private int up_down = 0;//默认为上哈哈其他就为下了。

    public MyGoleView(Context context, int up_down) {
        super(context);
        this.mcontext = context;
        this.up_down = up_down;
    }

    public MyGoleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public View getView() {
        if (up_down == 0) {
            View view = LayoutInflater.from(mcontext).inflate(R.layout.refrush_header, null);
            refrush_tv = view.findViewById(R.id.refrush_tv);
            refrush_image = view.findViewById(R.id.refrush_image);
            return view;
        } else {
            View view = LayoutInflater.from(mcontext).inflate(R.layout.refrush_bootom, null);
            refrush_image = view.findViewById(R.id.refrush_image1);
            return view;
        }
    }

    @Override
    public void onPullingUp(float fraction, float maxHeadHeight, float headHeight) {
         //这里当上啦过过程中的操锁自己试试看。我懒不想研究了。
    }

    @Override
    public void onPullingDown(float fraction, float maxHeadHeight, float headHeight) {
       //我在上啦过程中布局里面没有设置文字哦!!看看我的item就知道了
        if (refrush_tv != null) {
            refrush_tv.setText("下拉刷新");
        }
    }

    @Override
    public void onPullReleasing(float fraction, float maxHeadHeight, float headHeight) {
        if (refrush_tv != null) {
            refrush_tv.setText("正在刷新中");
        }

    }

    @Override
    public void startAnim(float maxHeadHeight, float headHeight) {
        //这里是我们的动画哦!!!
        refrush_image.setBackgroundResource(R.drawable.anim_loading_view);
        animationDrawable = (AnimationDrawable)
                refrush_image.getBackground();
        animationDrawable.start();
    }

    @Override
    public void onFinish() {
        animationDrawable.stop();
    }
}

第二种就是本类中写,这样真的好么。我不推荐这样写,复用性太差了代码每次写都要一大堆,自己看着办吧,我这里不贴代码了,我的Demon里面有的。运行如下图:

这里写图片描述

这里写图片描述

最后github贴出来:https://github.com/luhenchang/FreshDemon_Luhenchang.git

猜你喜欢

转载自blog.csdn.net/m0_37667770/article/details/78666351