打造通用下拉刷新上拉加载更多组件

android开发中最常用的就是列表组件,如ListView,recycleView,用到它们感觉就会涉及到数据更新,分页加载。

最开始的时候,刷新组件我是在技术群里头找了一个被人绑定好的库,是绑定的github上一个星星很多的java原生组件。但是demo很简单,对于当时小白的我懵逼了,不晓得咋个用,而且一直觉得banding的库总感觉有问题,就想着直接找一个java的库翻译成C#版本的。功夫不负苦心人,在csdn上找到了一篇http://blog.csdn.net/zhongkejingwang/article/details/38868463

写的很详细,翻译起来也省了不少力,也很感谢原作者。

突然想起一句话,叫做我们不生产代码,只是代码的搬运工!

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

 这里贴上我翻译好的其中几个很重要的组件的代码:

1.PullToRefreshLayout

using System;using System.Threading.Tasks;using Android.Content;using Android.OS;using Android.Util;using Android.Views;using Android.Views.Animations;using Android.Widget;using CNBlog.Droid.Utils;namespace CNBlog.Droid.PullableView
{    public class PullToRefreshLayout : RelativeLayout
    {        // 初始状态  
        private const int initStatus = 0;        // 释放刷新  
        private const int releaseToRefresh = 1;        // 正在刷新  
        private const int refreshing = 2;        // 释放加载  
        private const int releaseToLoad = 3;        // 正在加载  
        private const int loading = 4;        // 操作完毕  
        private const int complete = 5;        // 当前状态  
        private int currentStatus = 0;        // 刷新回调接口  
        private OnRefreshListener mListener;        // 刷新成功  
        private const int succeed = 0;        // 刷新失败  
        private const int failed = 1;        // 按下Y坐标,上一个事件点Y坐标  
        private float downY, lastY;        // 下拉的距离。注意:pullDownY和pullUpY不可能同时不为0  
        private float pullDownY = 0;        // 上拉的距离  
        private float pullUpY = 0;        // 释放刷新的距离  
        private float refreshDist = 200;        // 释放加载的距离  
        private float loadmoreDist = 200;        private UIScheduling uScheduling;        // 回滚速度  
        private float moveSpeed = 8;        // 第一次执行布局  
        private bool isLayout = false;        // 在刷新过程中滑动操作  
        private bool isTouch = false;        // 手指滑动距离与下拉头的滑动距离比,中间会随正切函数变化  
        private float radio = 2;        // 下拉箭头的转180°动画  
        private RotateAnimation rotateAnimation;        // 均匀旋转动画  
        private RotateAnimation refreshingAnimation;        // 下拉头  
        private View refreshView;        // 下拉的箭头  
        public View pullView;        // 正在刷新的图标  
        private View refreshingView;        // 刷新结果图标  
        private View refreshStateImageView;        // 刷新结果:成功或失败  
        private TextView refreshStateTextView;        // 上拉头  
        private View loadmoreView;        // 上拉的箭头  
        public View pullUpView;        // 正在加载的图标  
        private View loadingView;        // 加载结果图标  
        private View loadStateImageView;        // 加载结果:成功或失败  
        private TextView loadStateTextView;        //请求加载错误View
        private View errorView;        // 实现了Pullable接口的View  
        private View pullableView;        // 过滤多点触碰  
        private int mEvents;        // 这两个变量用来控制pull的方向,如果不加控制,当情况满足可上拉又可下拉时没法下拉  
        private bool canPullDown = true;        private bool canPullUp = true;        private Context mContext;        private Handler updateUIHandler;        public void setOnRefreshListener(OnRefreshListener listener)
        {
            mListener = listener;
        }        public PullToRefreshLayout(Context context)
            : base(context)
        {
            initView(context);
        }        public PullToRefreshLayout(Context context, IAttributeSet attrs)
            : base(context, attrs)
        {
            initView(context);
        }        public PullToRefreshLayout(Context context, IAttributeSet attrs, int defStyle)
            : base(context, attrs, defStyle)
        {
            initView(context);
        }        private void initView(Context context)
        {
            mContext = context;
            updateUIHandler = new Handler((Message msg) =>
            {                    // 回弹速度随下拉距离moveDeltaY增大而增大
                    moveSpeed = (float)(8 + 5 * Math.Tan(Math.PI / 2 / MeasuredHeight * (pullDownY + Math.Abs(pullUpY))));                    if (!isTouch)
                    {                        // 正在刷新,且没有往上推的话则悬停,显示"正在刷新..."
                        if (currentStatus == refreshing && pullDownY <= refreshDist)
                        {
                            pullDownY = refreshDist;
                            uScheduling.Cancel();
                        }                        else if (currentStatus == loading && -pullUpY <= loadmoreDist)
                        {
                            pullUpY = -loadmoreDist;
                            uScheduling.Cancel();
                        }
                    }                    if (pullDownY > 0)
                        pullDownY -= moveSpeed;                    else if (pullUpY < 0)
                        pullUpY += moveSpeed;                    if (pullDownY < 0)
                    {                        // 已完成回弹
                        pullDownY = 0;
                        pullView.ClearAnimation();                        // 隐藏下拉头时有可能还在刷新,只有当前状态不是正在刷新时才改变状态
                        if (currentStatus != refreshing && currentStatus != loading)
                            changeStatus(initStatus);
                        uScheduling.Cancel();
                        RequestLayout();
                    }                    if (pullUpY > 0)
                    {                        // 已完成回弹
                        pullUpY = 0;
                        pullUpView.ClearAnimation();                        // 隐藏上拉头时有可能还在刷新,只有当前状态不是正在刷新时才改变状态
                        if (currentStatus != refreshing && currentStatus != loading)
                            changeStatus(initStatus);
                        uScheduling.Cancel();
                        RequestLayout();
                    }                    // 刷新布局,会自动调用onLayout                    RequestLayout();                    // 没有拖拉或者回弹完成
                    if (pullDownY + Math.Abs(pullUpY) == 0)
                    {
                        uScheduling.Cancel();
                    }
            });
            uScheduling = new UIScheduling(updateUIHandler);
            rotateAnimation = (RotateAnimation)AnimationUtils.LoadAnimation(
                context, Resource.Animator.reverse_anim);
            refreshingAnimation = (RotateAnimation)AnimationUtils.LoadAnimation(
                context, Resource.Animator.rotating);            // 添加匀速转动动画
            LinearInterpolator lir = new LinearInterpolator();
            rotateAnimation.Interpolator = lir;
            refreshingAnimation.Interpolator = lir;
        }        private void initView()
        {            // 初始化下拉布局
            pullView = refreshView.FindViewById<View>(Resource.Id.pull_icon);
            refreshStateTextView = refreshView.FindViewById<TextView>(Resource.Id.state_tv);
            refreshingView = refreshView.FindViewById<View>(Resource.Id.refreshing_icon);
            refreshStateImageView = refreshView.FindViewById<View>(Resource.Id.state_iv);            // 初始化上拉布局
            pullUpView = loadmoreView.FindViewById<View>(Resource.Id.pullup_icon);
            loadStateTextView = loadmoreView.FindViewById<TextView>(Resource.Id.loadstate_tv);
            loadingView = loadmoreView.FindViewById<View>(Resource.Id.loading_icon);
            loadStateImageView = loadmoreView.FindViewById<View>(Resource.Id.loadstate_iv);
        }        /// <summary>
        /// 完成刷新操作,显示刷新结果。注意:刷新完成后一定要调用这个方法        /// </summary>
        /// <param name="refreshResult">succeed代表成功, failed代表失败</param>
        public void refreshFinish(int refreshResult)
        {
            refreshingView.ClearAnimation();
            refreshingView.Visibility = ViewStates.Gone;            switch (refreshResult)
            {                case 0:                    // 刷新成功
                    refreshStateImageView.Visibility = ViewStates.Visible;
                    refreshStateTextView.Text = "刷新成功";
                    refreshStateImageView.SetBackgroundResource(Resource.Mipmap.refresh_succeed);                    break;                case 1:                default:                    // 刷新失败
                    refreshStateImageView.Visibility = ViewStates.Visible;
                    refreshStateTextView.Text = "刷新失败";
                    refreshStateImageView.SetBackgroundResource(Resource.Mipmap.refresh_failed);                    break;
            }            if (pullDownY > 0)
            {                // 刷新结果停留1秒
                new Handler((Message msg) =>
                {
                    changeStatus(complete);
                    hide();
                }).SendEmptyMessageDelayed(0, 1000);
            }            else
            {
                changeStatus(complete);
                hide();
            }
        }        /// <summary>
        /// 加载完毕,显示加载结果。注意:刷新完成后一定要调用这个方法        /// </summary>
        /// <param name="refreshResult">succeed代表成功, failed代表失败</param>
        public void loadmoreFinish(int refreshResult)
        {
            loadingView.ClearAnimation();
            loadingView.Visibility = ViewStates.Gone;            switch (refreshResult)
            {                case 0:                    // 加载成功
                    loadStateImageView.Visibility = ViewStates.Visible;
                    loadStateTextView.Text = "加载成功";
                    loadStateImageView.SetBackgroundResource(Resource.Mipmap.load_succeed);                    break;                case 1:                default:                    // 加载失败
                    loadStateImageView.Visibility = ViewStates.Visible;
                    loadStateTextView.Text = "加载失败";
                    loadStateImageView.SetBackgroundResource(Resource.Mipmap.load_failed);
                    pullableView.Visibility = ViewStates.Gone;                    break;
            }            if (pullUpY < 0)
            {                // 刷新结果停留1秒
                new Handler((Message msg) =>
                {
                    changeStatus(complete);
                    hide();
                }).SendEmptyMessageDelayed(0, 1000);
            }            else
            {
                changeStatus(complete);
                hide();
            }
        }        /// <summary>
             break;