栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android 仿微信朋友圈下拉

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android 仿微信朋友圈下拉

 这次是改了SmartRefreshLayout 中 根据官方提供的刷新 头,还有一些博客参考

修改源码自定义SwipeRefreshLayout样式——高仿微信朋友圈下拉刷新_u011443509的博客-CSDN博客_swiperefreshlayout 自定义动画

GitHub - wdsqjq/FengYunWeather: 风云天气是Android 平台开源天气 App,采用Kotlin、Room、OKHttp3、 协程等框架实现。

  

            

主要修改的

MaterialProgressDrawable 和 其中的 CircleImageView
public class MyCircleImageView extends ImageView {

    protected static final int KEY_SHADOW_COLOR = 0x1E000000;
    protected static final int FILL_SHADOW_COLOR = 0x3D000000;
    // PX
    protected static final float X_OFFSET = 0f;
    protected static final float Y_OFFSET = 1.75f;
    protected static final float SHADOW_RADIUS = 3.5f;
    protected static final int SHADOW_ELEVATION = 4;

    //    private Animation.AnimationListener mListener;
    int mShadowRadius;

    public MyCircleImageView(Context context, int color) {
        super(context);
        final View thisView = this;
        final float density = thisView.getResources().getDisplayMetrics().density;
        final int shadowYOffset = (int) (density * Y_OFFSET);
        final int shadowXOffset = (int) (density * X_OFFSET);

        mShadowRadius = (int) (density * SHADOW_RADIUS);

        ShapeDrawable circle;
        if (Build.VERSION.SDK_INT >= 21) {
            circle = new ShapeDrawable(new OvalShape());
            thisView.setElevation(SHADOW_ELEVATION * density);
        } else {
            OvalShape oval = new OvalShadow(mShadowRadius);
            circle = new ShapeDrawable(oval);
            thisView.setLayerType(LAYER_TYPE_SOFTWARE, circle.getPaint());
            circle.getPaint().setShadowLayer(mShadowRadius, shadowXOffset, shadowYOffset,
                    KEY_SHADOW_COLOR);
            final int padding = mShadowRadius;
            // set padding so the inner image sits correctly within the shadow.
            thisView.setPadding(padding, padding, padding, padding);
        }
//        circle.getPaint().setColor(color);
//        thisView.setBackground(circle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final View thisView = this;
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (Build.VERSION.SDK_INT < 21) {
            super.setMeasuredDimension(
                    thisView.getMeasuredWidth() + mShadowRadius * 2,
                    thisView.getMeasuredHeight() + mShadowRadius * 2);
        }
    }

//    public void setAnimationListener(Animation.AnimationListener listener) {
//        mListener = listener;
//    }
//
//    @Override
//    public void onAnimationStart() {
//        super.onAnimationStart();
//        if (mListener != null) {
//            mListener.onAnimationStart(getAnimation());
//        }
//    }
//
//    @Override
//    public void onAnimationEnd() {
//        super.onAnimationEnd();
//        if (mListener != null) {
//            mListener.onAnimationEnd(getAnimation());
//        }
//    }

//    
//    public void setBackgroundColorRes(int colorRes) {
//        Context context = getContext();
//        if (Build.VERSION.SDK_INT >= 23) {
//            setBackgroundColor(context.getResources().getColor(colorRes, context.getTheme()));
//        } else {
//            //noinspection deprecation
//            setBackgroundColor(context.getResources().getColor(colorRes));
//        }
//    }
//
    @Override
    public void setBackgroundColor( int color) {
        final View thisView = this;
        if (thisView.getBackground() instanceof ShapeDrawable) {
            ((ShapeDrawable) thisView.getBackground()).getPaint().setColor(color);
        }
    }

    private class OvalShadow extends OvalShape {
        private RadialGradient mRadialGradient;
        private Paint mShadowPaint;

        OvalShadow(int shadowRadius) {
            super();
            mShadowPaint = new Paint();
            mShadowRadius = shadowRadius;
            updateRadialGradient((int) super.rect().width());
        }

        @Override
        protected void onResize(float width, float height) {
            super.onResize(width, height);
            updateRadialGradient((int) width);
        }

        @Override
        public void draw(Canvas canvas, Paint paint) {
            final View thisView = MyCircleImageView.this;
            final int viewWidth = thisView.getWidth();
            final int viewHeight = thisView.getHeight();
            canvas.drawCircle(viewWidth / 2f, viewHeight / 2f, viewWidth / 2f, mShadowPaint);
            canvas.drawCircle(viewWidth / 2f, viewHeight / 2f, viewWidth / 2f - mShadowRadius, paint);
        }

        private void updateRadialGradient(int diameter) {
            mRadialGradient = new RadialGradient(diameter / 2f, diameter / 2f,
                    mShadowRadius, new int[] { FILL_SHADOW_COLOR, Color.TRANSPARENT },
                    null, Shader.TileMode.CLAMP);
            mShadowPaint.setShader(mRadialGradient);
        }
    }
}
public class CustomProgressDrawable extends MaterialProgressDrawable {
 
//    旋转因子,调整旋转速度
    private static final int ROTATION_FACTOR = 5*360;
//    加载时的动画
    private Animation mAnimation;
    private View mParent;
    private Bitmap mBitmap ;
//    旋转角度
    private float rotation;
    private Paint paint;
 
 
    public CustomProgressDrawable(View parent) {
        super(parent);
        mParent = parent;
        paint = new Paint();
        setupAnimation();
    }
 
    private void setupAnimation() {
//        初始化旋转动画
        mAnimation = new Animation(){
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                setProgressRotation(-interpolatedTime);
            }
        };
        mAnimation.setDuration(3000);
//        无限重复
        mAnimation.setRepeatCount(Animation.INFINITE);
        mAnimation.setRepeatMode(Animation.RESTART);
//        均匀转速
        mAnimation.setInterpolator(new LinearInterpolator());
    }
 
 
    @Override
    public void start() {
        mParent.startAnimation(mAnimation);
    }
    public void setBitmap(Bitmap mBitmap) {
        this.mBitmap = mBitmap;
    }
 
    @Override
    public void setProgressRotation(float rotation) {
//        取负号是为了和微信保持一致,下拉时逆时针转加载时顺时针转,旋转因子是为了调整转的速度。
        this.rotation = -rotation*ROTATION_FACTOR;
        invalidateSelf();
    }
 
    @SuppressLint("ResourceAsColor")
    @Override
    public void draw(Canvas c) {

        c.drawColor(android.R.color.black);
        Rect bound = getBounds();
        c.rotate(rotation,bound.exactCenterX(),bound.exactCenterY());
        Rect src = new Rect(0,0,mBitmap.getWidth(),mBitmap.getHeight());
        c.drawBitmap(mBitmap,src,bound,paint);
    }
}
public class MyMaterialHeader extends SimpleComponent implements RefreshHeader {

    // Maps to ProgressBar.Large style
    public static final int SIZE_LARGE = 0;
    // Maps to ProgressBar default style
    public static final int SIZE_DEFAULT = 1;

    protected static final int CIRCLE_BG_LIGHT = 0xFFFAFAFA;
    protected static final float MAX_PROGRESS_ANGLE = .8f;
    @VisibleForTesting
    protected static final int CIRCLE_DIAMETER = 40;
    @VisibleForTesting
    protected static final int CIRCLE_DIAMETER_LARGE = 56;

    protected boolean mFinished;
    protected int mCircleDiameter;
    protected MyCircleImageView mCircleView;
    //    protected MaterialProgressDrawable mProgress;
    protected CustomProgressDrawable mProgress;

    
    protected int mWaveHeight;
    protected int mHeadHeight;
    protected Path mBezierPath;
    protected Paint mBezierPaint;
    protected RefreshState mState;
    protected boolean mShowBezierWave = false;
    protected boolean mScrollableWhenRefreshing = true;

    //
    public MyMaterialHeader(Context context) {
        this(context, null);
    }

    public MyMaterialHeader(Context context, AttributeSet attrs) {
        super(context, attrs, 0);

        mSpinnerStyle = SpinnerStyle.MatchLayout;
        final View thisView = this;
        final ViewGroup thisGroup = this;
        thisView.setMinimumHeight(SmartUtil.dp2px(100));

//        mProgress = new MaterialProgressDrawable(this);
        mProgress = new CustomProgressDrawable(this);
        mProgress.setBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.rainbow_ic));

//        mProgress.setBackgroundColor(CIRCLE_BG_LIGHT);
//        mProgress.setAlpha(255);
//        mProgress.setColorSchemeColors(0xff0099cc,0xffff4444,0xff669900,0xffaa66cc,0xffff8800);

        // 这里上颜色是给图标上颜色
        mCircleView = new MyCircleImageView(context, getResources().getColor(R.color.black));
        mCircleView.setImageDrawable(mProgress);
//        mCircleView.setAlpha(0f);
        thisGroup.addView(mCircleView);

        final DisplayMetrics metrics = thisView.getResources().getDisplayMetrics();
        mCircleDiameter = (int) (CIRCLE_DIAMETER * metrics.density);

        mBezierPath = new Path();
        mBezierPaint = new Paint();
        mBezierPaint.setAntiAlias(true);
        mBezierPaint.setStyle(Paint.Style.FILL);

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MaterialHeader);

        mShowBezierWave = ta.getBoolean(R.styleable.MaterialHeader_srlShowBezierWave, mShowBezierWave);
        mScrollableWhenRefreshing = ta.getBoolean(R.styleable.MaterialHeader_srlScrollableWhenRefreshing, mScrollableWhenRefreshing);
        mBezierPaint.setColor(ta.getColor(R.styleable.MaterialHeader_srlPrimaryColor, 0xff11bbff));
        if (ta.hasValue(R.styleable.MaterialHeader_srlShadowRadius)) {
            int radius = ta.getDimensionPixelOffset(R.styleable.MaterialHeader_srlShadowRadius, 0);
            int color = ta.getColor(R.styleable.MaterialHeader_mhShadowColor, 0xff000000);
            mBezierPaint.setShadowLayer(radius, 0, 0, color);
            thisView.setLayerType(LAYER_TYPE_SOFTWARE, null);
        }

        mShowBezierWave = ta.getBoolean(R.styleable.MaterialHeader_mhShowBezierWave, mShowBezierWave);
        mScrollableWhenRefreshing = ta.getBoolean(R.styleable.MaterialHeader_mhScrollableWhenRefreshing, mScrollableWhenRefreshing);
        if (ta.hasValue(R.styleable.MaterialHeader_mhPrimaryColor)) {
            mBezierPaint.setColor(ta.getColor(R.styleable.MaterialHeader_mhPrimaryColor, 0xff11bbff));
        }
        if (ta.hasValue(R.styleable.MaterialHeader_mhShadowRadius)) {
            int radius = ta.getDimensionPixelOffset(R.styleable.MaterialHeader_mhShadowRadius, 0);
            int color = ta.getColor(R.styleable.MaterialHeader_mhShadowColor, 0xff000000);
            mBezierPaint.setShadowLayer(radius, 0, 0, color);
            thisView.setLayerType(LAYER_TYPE_SOFTWARE, null);
        }

        ta.recycle();

    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.setMeasuredDimension(getSize(widthMeasureSpec), getSize(heightMeasureSpec));
        final View circleView = mCircleView;
        circleView.measure(MeasureSpec.makeMeasureSpec(mCircleDiameter, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(mCircleDiameter, MeasureSpec.EXACTLY));
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        final ViewGroup thisGroup = this;
        if (thisGroup.getChildCount() == 0) {
            return;
        }
        final View thisView = this;
        final View circleView = mCircleView;
        final int width = thisView.getMeasuredWidth();
        int circleWidth = circleView.getMeasuredWidth();
        int circleHeight = circleView.getMeasuredHeight();

        if (thisView.isInEditMode() && mHeadHeight > 0) {
            int circleTop = mHeadHeight - circleHeight / 2;
//            circleView.layout((width / 2 - circleWidth / 2), circleTop,
//                    (width / 2 + circleWidth / 2), circleTop + circleHeight);
            circleView.layout(100, circleTop,
                    circleWidth + 100, circleTop + circleHeight);

            mProgress.showArrow(true);
            mProgress.setStartEndTrim(0f, MAX_PROGRESS_ANGLE);
            mProgress.setArrowScale(1);
            circleView.setAlpha(1f);
            circleView.setVisibility(VISIBLE);
        } else {
//            circleView.layout((width / 2 - circleWidth / 2), -circleHeight,
//                    (width / 2 + circleWidth / 2), 0);
            circleView.layout(100, -circleHeight,
                    circleWidth + 100, 0);
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        if (mShowBezierWave) {
            //重置画笔
            mBezierPath.reset();
            mBezierPath.lineTo(0, mHeadHeight);
            //绘制贝塞尔曲线
            final View thisView = this;
            mBezierPath.quadTo(thisView.getMeasuredWidth() / 2f, mHeadHeight + mWaveHeight * 1.9f, thisView.getMeasuredWidth(), mHeadHeight);
            mBezierPath.lineTo(thisView.getMeasuredWidth(), 0);
            canvas.drawPath(mBezierPath, mBezierPaint);
        }
        super.dispatchDraw(canvas);
    }
    //

    //
    @Override
    public void onInitialized(@NonNull RefreshKernel kernel, int height, int maxDragHeight) {
        final View thisView = this;
        if (!mShowBezierWave) {
            kernel.requestDefaultTranslationContentFor(this, false);
        }
        if (thisView.isInEditMode()) {
            mWaveHeight = mHeadHeight = height / 2;
        }
    }

    @Override
    public void onMoving(boolean isDragging, float percent, int offset, int height, int maxDragHeight) {
        if (mState == RefreshState.Refreshing) {
            return;
        }

        if (mShowBezierWave) {
            mHeadHeight = Math.min(offset, height);
            mWaveHeight = Math.max(0, offset - height);

            final View thisView = this;
            thisView.postInvalidate();
        }

        if (isDragging || (!mProgress.isRunning() && !mFinished)) {

            if (mState != RefreshState.Refreshing) {
                float originalDragPercent = 1f * offset / height;

                float dragPercent = Math.min(1f, Math.abs(originalDragPercent));
                float adjustedPercent = (float) Math.max(dragPercent - .4, 0) * 5 / 3;
                float extraOS = Math.abs(offset) - height;
                float tensionSlingshotPercent = Math.max(0, Math.min(extraOS, (float) height * 2)
                        / (float) height);
                float tensionPercent = (float) ((tensionSlingshotPercent / 4) - Math.pow(
                        (tensionSlingshotPercent / 4), 2)) * 2f;
                float strokeStart = adjustedPercent * .8f;
                mProgress.showArrow(true);
                mProgress.setStartEndTrim(0f, Math.min(MAX_PROGRESS_ANGLE, strokeStart));
                mProgress.setArrowScale(Math.min(1f, adjustedPercent));

                float rotation = (-0.25f + .4f * adjustedPercent + tensionPercent * 2) * .5f;
                mProgress.setProgressRotation(rotation);
            }

            final View circleView = mCircleView;
            float targetY = offset / 2f + mCircleDiameter * 3 / 4f;
//            float targetY = offset / 2f + mCircleDiameter / 2f;
            circleView.setTranslationY(Math.min(offset, targetY));
            circleView.setAlpha(Math.min(1f, 4f * offset / mCircleDiameter));
        }
    }


    @Override
    public void onReleased(@NonNull RefreshLayout layout, int height, int maxDragHeight) {
        mProgress.start();
    }

    @Override
    public void onStateChanged(@NonNull RefreshLayout refreshLayout, @NonNull RefreshState oldState, @NonNull RefreshState newState) {
        final View circleView = mCircleView;
        mState = newState;
        switch (newState) {
            case None:
            case ReleaseToRefresh:
            case Refreshing:
                break;
            case PullDownToRefresh:
                mFinished = false;
                circleView.setVisibility(VISIBLE);
                circleView.setTranslationY(0);
                circleView.setScaleX(1);
                circleView.setScaleY(1);
                break;
        }
    }

    @Override
    public int onFinish(@NonNull RefreshLayout layout, boolean success) {
        final View circleView = mCircleView;
        mProgress.stop();
        final int deltaY = -mCircleView.getBottom();
        circleView.animate().setDuration(200).translationY(deltaY);
        mFinished = true;
        return 0;
    }

    
    @Override
    @Deprecated
    public void setPrimaryColors(@ColorInt int... colors) {
        if (colors.length > 0) {
            mBezierPaint.setColor(colors[0]);
        }
    }
    //


    //

    
    public MyMaterialHeader setProgressBackgroundColorSchemeResource(@ColorRes int colorRes) {
        final View thisView = this;
        final Context context = thisView.getContext();
        final int color = ContextCompat.getColor(context, colorRes);
        setProgressBackgroundColorSchemeColor(color);
        return this;
    }

    
    public MyMaterialHeader setProgressBackgroundColorSchemeColor(@ColorInt int color) {
        final View circle = mCircleView;
        circle.setBackgroundColor(color);
//        mProgress.setBackgroundColor(color);
        return this;
    }

    
    public MyMaterialHeader setColorSchemeColors(@ColorInt int... colors) {
        mProgress.setColorSchemeColors(colors);
        return this;
    }

    
    public MyMaterialHeader setColorSchemeResources(@ColorRes int... colorIds) {
        final View thisView = this;
        final Context context = thisView.getContext();
        int[] colors = new int[colorIds.length];
        for (int i = 0; i < colorIds.length; i++) {
            colors[i] = ContextCompat.getColor(context, colorIds[i]);
        }
        return setColorSchemeColors(colors);
    }

    
    public MyMaterialHeader setSize(int size) {
        if (size != SIZE_LARGE && size != SIZE_DEFAULT) {
            return this;
        }
        final View thisView = this;
        DisplayMetrics metrics = thisView.getResources().getDisplayMetrics();
        if (size == SIZE_LARGE) {
            mCircleDiameter = (int) (CIRCLE_DIAMETER_LARGE * metrics.density);
        } else {
            mCircleDiameter = (int) (CIRCLE_DIAMETER * metrics.density);
        }
        // force the bounds of the progress circle inside the circle view to
        // update by setting it to null before updating its size and then
        // re-setting it
        mCircleView.setImageDrawable(null);
        mProgress.updateSizes(size);
        mCircleView.setImageDrawable(mProgress);
        return this;
    }

    
    public MyMaterialHeader setShowBezierWave(boolean show) {
        this.mShowBezierWave = show;
        return this;
    }

    
    public MyMaterialHeader setScrollableWhenRefreshing(boolean scrollable) {
        this.mScrollableWhenRefreshing = scrollable;
        return this;
    }
    //
}

需要用到的图片

设置关掉回弹

 //关掉回弹
        mViewBinding.refresh.setEnableOverScrollBounce(false);

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/732472.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号