• 下拉刷新动画研究


    昨天公司提了一个需求。说是要有自己特色的下拉刷新上拉载入很多其它,随后就去万能的github上面看看自己之前存过的那些。偶然间看到这个Android-AnimatePullToRefreshListView,这玩意能够使用gif图片或者帧动画去运行headview动画载入,而且是基于chrisbanes的Android-PullToRefresh,这样还方便与我项目无缝衔接

    上一张效果图
    这里写图片描写叙述
    大体上简单说明下:
    1.gif与帧动画播放採用的是android-gif-drawable
    2.主题上是改动了RotateLoadingLayout类。看代码

    //帧动画三张图
    private int[] mGifRes = {
                R.drawable.dropdown_loading_00,
                R.drawable.dropdown_loading_01,
                R.drawable.dropdown_loading_02,
        };
    //通过下拉的scale比例,去计算应该显示哪张图片(下拉距离/headview高度)
    protected void onPullImpl(float scaleOfLayout) {
        int index = (int) (scaleOfLayout / 1f * 10);
        if (index == mPrevIndex) {
            return;
        } else {
            if (index > 10) {
                index = 10;
            }
            int res = getResources().getIdentifier(String.format("dropdown_anim_%02d",  index), "drawable", getContext().getPackageName());
            mHeaderImage.setImageResource(res);
            mPrevIndex = index;
        }
    }
    //正在刷新,就播放一下动画
    @Override
    protected void refreshingImpl() {
           if (mGifAnimation == null) {
               mGifAnimation = new GifAnimation(mHeaderImage, mGifRes);
           }
           mGifAnimation.start();
       }
    
    //刷新结束,就停止动画播放
    @Override
    protected void resetImpl() {
           mHeaderImage.clearAnimation();
           if (mGifAnimation != null) {
               mGifAnimation.stop();
           }
    }

    在PullToRefreshBase中能够看到

    /**
         * Actions a Pull Event
         *
         * @return true if the Event has been handled, false if there has been no
         * change
         */
        private void pullEvent() {
            final int newScrollValue;
            final int itemDimension;
            final float initialMotionValue, lastMotionValue;
    
            switch (getPullToRefreshScrollDirection()) {
                case HORIZONTAL:
                    initialMotionValue = mInitialMotionX;
                    lastMotionValue = mLastMotionX;
                    break;
                case VERTICAL:
                default:
                    initialMotionValue = mInitialMotionY;
                    lastMotionValue = mLastMotionY;
                    break;
            }
            //得到对应的高度
            switch (mCurrentMode) {
                case PULL_FROM_END:
                    newScrollValue = Math.round(Math.max(initialMotionValue
                            - lastMotionValue, 0)
                            / FRICTION);
                    itemDimension = getFooterSize();
                    break;
                case PULL_FROM_START:
                default:
                    newScrollValue = Math.round(Math.min(initialMotionValue
                            - lastMotionValue, 0)
                            / FRICTION);
                    itemDimension = getHeaderSize();
                    break;
            }
    
            setHeaderScroll(newScrollValue);
    
            if (newScrollValue != 0 && !isRefreshing()) {
                //通过当前移动的比例跟view自身的高度,计算出scale
                float scale = Math.abs(newScrollValue) / (float) itemDimension;
                //不管你设置的是何种mode。都会有对应的回调
                switch (mCurrentMode) {
                    case PULL_FROM_END:
                        mFooterLayout.onPull(scale);
                        break;
                    case PULL_FROM_START:
                    default:
                        mHeaderLayout.onPull(scale);
                        break;
                }
                //前台接口回调
                if (mState != State.PULL_TO_REFRESH
                        && itemDimension >= Math.abs(newScrollValue)) {
                    setState(State.PULL_TO_REFRESH);
                } else if (mState == State.PULL_TO_REFRESH
                        && itemDimension < Math.abs(newScrollValue)) {
                    setState(State.RELEASE_TO_REFRESH);
                }
            }
        }

    只是这边有个情况要考虑下,就是之前我们能够直接使用ptrDrawable、ptrDrawableStart、ptrDrawableEnd去替换上拉下拉不同的图片

    <!-- Drawable to use as Loading Indicator. Changes both Header and Footer. -->
            <attr name="ptrDrawable" format="reference" />
    
            <!-- Drawable to use as Loading Indicator in the Header View. Overrides value set in ptrDrawable. -->
            <attr name="ptrDrawableStart" format="reference" />
    
            <!-- Drawable to use as Loading Indicator in the Footer View. Overrides value set in ptrDrawable. -->
            <attr name="ptrDrawableEnd" format="reference" />

    可是通过如今代码去构建view的话。这些自己定义属性是不具备这个能力,所以要自行替换foot和head

    // We need to create now layouts now
            mHeaderLayout = createLoadingLayout(context, Mode.PULL_FROM_START, a);
            mFooterLayout = createLoadingLayout(context, Mode.PULL_FROM_END, a);
    
    //创建视图的方法
    protected LoadingLayout createLoadingLayout(Context context, Mode mode, TypedArray attrs) {
            LoadingLayout layout = mLoadingAnimationStyle.createLoadingLayout(
                    context, mode, getPullToRefreshScrollDirection(), attrs);
            layout.setVisibility(View.INVISIBLE);
            return layout;
        }
    
    //能够改造这个枚举。返回须要的layout
    public static enum AnimationStyle {
        /**
         * This is the default for Android-PullToRefresh. Allows you to use any
         * drawable, which is automatically rotated and used as a Progress Bar.
         */
        ROTATE,
    
        /**
         * This is the old default, and what is commonly used on iOS. Uses an
         * arrow image which flips depending on where the user has scrolled.
         */
        FLIP,
    
        GIF;
    
        static AnimationStyle getDefault() {
            return ROTATE;
        }
    
        /**
         * Maps an int to a specific mode. This is needed when saving state, or
         * inflating the view from XML where the mode is given through a attr
         * int.
         *
         * @param modeInt - int to map a Mode to
         * @return Mode that modeInt maps to, or ROTATE by default.
         */
        static AnimationStyle mapIntToValue(int modeInt) {
            switch (modeInt) {
                case 0x0:
                default:
                    return ROTATE;
                case 0x1:
                    return FLIP;
                case 0x10:
                    return GIF;
            }
        }
    
        LoadingLayout createLoadingLayout(Context context, Mode mode,
                                          Orientation scrollDirection, TypedArray attrs) {
            switch (this) {
                case ROTATE:
                default:
                    return new RotateLoadingLayout(context, mode, scrollDirection,
                            attrs);
                case FLIP:
                    return new FlipLoadingLayout(context, mode, scrollDirection,
                            attrs);
                case GIF:
                    return new GifLoadingLayout(context, mode, scrollDirection,
                            attrs);
            }
        }
    }

    仅仅有这样才干创建出不同的head与foot

    OK,今天就说这么多,有疑问大家一起交流

  • 相关阅读:
    CTO成长之路分享会
    MySQL 数据库 varchar 到底可以存多少个汉字,多少个英文呢?我们来搞搞清楚
    《共享经济》创业沙龙
    旅游代购
    沙漏哟的书单
    qt5---滑动条QSlider
    qt5---步长调节器SpinBox和QDoubleSpinBox
    qt5--自定义控件封装
    qt5--表格控件QTableWidget
    qt5--树形控件QTreeWidget
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7082075.html
Copyright © 2020-2023  润新知