com.shizhefei.view.coolrefreshview.header.JellyHeader.java Source code

Java tutorial

Introduction

Here is the source code for com.shizhefei.view.coolrefreshview.header.JellyHeader.java

Source

package com.shizhefei.view.coolrefreshview.header;
/*
 * Copyright (C) 2016 LuckyJayce
 * Copyright (C) 2015 imallan
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Build;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.DecelerateInterpolator;

import com.shizhefei.view.coolrefreshview.CoolRefreshView;
import com.shizhefei.view.coolrefreshview.PullHeader;

/**
 * Created by LuckyJayce on 2016/11/28.
 * header ??https://github.com/imallan/JellyRefreshLayout
 * ?
 */

public class JellyHeader extends ViewGroup implements PullHeader {

    private final Paint mPaint;
    private final Path mPath;
    private ViewOutlineProvider mViewOutlineProvider;
    private int currentDistance;
    private int status;
    private float mPointX;
    private int mColor = Color.GRAY;

    private int defaultMinHeight;

    public JellyHeader(Context context) {
        this(context, null);
    }

    public JellyHeader(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    private Animation showLoadingAnimation;
    private Animation hideLoadingAnimation;

    public JellyHeader(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setWillNotDraw(false);

        defaultMinHeight = Utils.dipToPix(context, 208);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.FILL);

        mPath = new Path();

        showLoadingAnimation = new AlphaAnimation(0, 1);
        showLoadingAnimation.setDuration(300);
        showLoadingAnimation.setInterpolator(new AccelerateInterpolator());

        hideLoadingAnimation = new AlphaAnimation(1, 0);
        hideLoadingAnimation.setDuration(300);
        hideLoadingAnimation.setInterpolator(new DecelerateInterpolator());

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mViewOutlineProvider = new ViewOutlineProvider() {
                @TargetApi(Build.VERSION_CODES.LOLLIPOP)
                @Override
                public void getOutline(View view, Outline outline) {
                    if (mPath.isConvex())
                        outline.setConvexPath(mPath);
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
                        outline.offset(0, totalDistance() - currentDistance);
                    }
                }
            };
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                setElevation(Utils.dipToPix(context, 4));
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int suggestedMiniHeight = getSuggestedMinimumHeight();
        suggestedMiniHeight = Math.max(defaultMinHeight, suggestedMiniHeight);
        int childState = 0;
        int height = ViewCompat.resolveSizeAndState(suggestedMiniHeight, heightMeasureSpec,
                childState << MEASURED_HEIGHT_STATE_SHIFT);
        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), height);

        if (loadingView != null) {
            int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(offsetToKeepHeaderWhileLoading(),
                    MeasureSpec.EXACTLY);
            int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, getPaddingLeft() + getPaddingRight(),
                    LayoutParams.MATCH_PARENT);
            loadingView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
    }

    @Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop() + totalDistance() - offsetToKeepHeaderWhileLoading();
        int measureHeight = loadingView.getMeasuredHeight();
        int measuredWidth = loadingView.getMeasuredWidth();
        loadingView.layout(childLeft, childTop, measuredWidth + childLeft, childTop + measureHeight);
    }

    @Override
    public void onPullBegin(CoolRefreshView refreshView) {
        this.loadingView.setVisibility(View.GONE);
    }

    @Override
    public void onPositionChange(CoolRefreshView refreshView, int status, int dy, int currentDistance) {
        this.currentDistance = currentDistance;
        this.status = status;
        ViewCompat.postInvalidateOnAnimation(this);
    }

    @Override
    public void onRefreshing(CoolRefreshView refreshView) {
        this.loadingView.setVisibility(View.VISIBLE);
        loadingView.clearAnimation();
        loadingView.startAnimation(showLoadingAnimation);
    }

    @Override
    public void onReset(CoolRefreshView refreshView, boolean pullRelease) {
        this.loadingView.setVisibility(View.GONE);
    }

    @Override
    public void onPullRefreshComplete(CoolRefreshView refreshView) {
        loadingView.clearAnimation();
        loadingView.startAnimation(hideLoadingAnimation);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int totalDistance = totalDistance();
        int headerHeight;
        int pullHeight;
        int offsetToKeepHeaderWhileLoading = offsetToKeepHeaderWhileLoading();
        if (status == CoolRefreshView.PULL_STATUS_REFRESHING) {
            headerHeight = offsetToKeepHeaderWhileLoading;
            pullHeight = currentDistance;
        } else {
            headerHeight = Math.min(currentDistance / 2, offsetToKeepHeaderWhileLoading);
            pullHeight = currentDistance;
        }
        if (headerHeight == 0) {
            return;
        }

        int saveCount = canvas.save();
        canvas.translate(0, totalDistance - currentDistance);

        final int width = canvas.getWidth();
        //??touchx ????touchx??
        mPointX = width / 2;

        final float mDisplayX = (mPointX - width / 2f) * 0.5f + width / 2f;
        mPaint.setColor(mColor);

        mPath.rewind();
        // ?
        mPath.moveTo(0, 0);
        mPath.lineTo(0, headerHeight);
        // ???
        mPath.quadTo(mDisplayX, pullHeight, width, headerHeight);
        mPath.lineTo(width, 0);
        mPath.close();
        canvas.drawPath(mPath, mPaint);
        canvas.restoreToCount(saveCount);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            setOutlineProvider(mViewOutlineProvider);
        }
    }

    @Override
    public View createHeaderView(CoolRefreshView refreshView) {
        return this;
    }

    @Override
    public Config getConfig() {
        return config;
    }

    private int totalDistance() {
        return getMeasuredHeight();
    }

    private int offsetToRefresh() {
        return getMeasuredHeight() / 2;
    }

    private int offsetToKeepHeaderWhileLoading() {
        return offsetToRefresh() / 2;
    }

    private DefaultConfig config = new DefaultConfig() {

        @Override
        public int headerViewLayoutOffset(CoolRefreshView refreshView, View headerView) {
            return headerView.getMeasuredHeight();
        }

        @Override
        public int offsetToRefresh(CoolRefreshView refreshView, View headerView) {
            return JellyHeader.this.offsetToRefresh();
        }

        @Override
        public int totalDistance(CoolRefreshView refreshView, View headerView) {
            return JellyHeader.this.totalDistance();
        }

        @Override
        public int offsetToKeepHeaderWhileLoading(CoolRefreshView refreshView, View headerView) {
            return JellyHeader.this.offsetToKeepHeaderWhileLoading();
        }
    };

    private View loadingView;

    /**
     * 
     *
     * @param view
     */
    public void setLoadingView(View view) {
        this.loadingView = view;
        LayoutParams layoutParams = view.getLayoutParams();
        if (layoutParams == null) {
            layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        }
        addView(loadingView, layoutParams);
    }

    /**
     * 
     *
     * @param layoutId
     */
    public void setLoadingView(int layoutId) {
        this.loadingView = LayoutInflater.from(getContext()).inflate(layoutId, this, false);
        addView(loadingView);
    }

    /**
     * 
     *
     * @param color
     */
    public void setDragLayoutColor(int color) {
        mColor = color;
        ViewCompat.postInvalidateOnAnimation(this);
    }

}