您的位置:首页 > Web前端 > CSS

不引入扩展包,使用SwipeRefreshLayout样式下拉刷新(Canva绘制)

2017-01-14 00:00 387 查看
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import org.json.JSONException;
import org.json.JSONObject;

/**
* Created by DCloud on 2017/1/6.
*/
public class PullRefreshCircleView extends View {
CircleRefreshDrawer drawer = null;
public PullRefreshCircleView(Context context) {
super(context);
//        setBackgroundColor(Color.RED);
drawer = new CircleRefreshDrawer(this, new CircleRefreshDrawer.OnRefreshListener() {
@Override
public void onRefreshing(int state) {
Log.d("PullRefreshCircleView","启动刷新 state=" + state);
postDelayed(new Runnable() {
@Override
public void run() {
drawer.endRefresh();
}
},5000);
}
});
try {
int pw = getResources().getDisplayMetrics().widthPixels;
int ph = getResources().getDisplayMetrics().heightPixels;
float scale = getResources().getDisplayMetrics().density;
drawer.parseData(new JSONObject("{height:'100',range:'200',offset:'50'}"),pw,ph,scale);
} catch (JSONException e) {
e.printStackTrace();
}
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(720,1210);
}

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

@Override
public boolean onTouchEvent(MotionEvent event) {
boolean ret = drawer.onTouchEvent(event);
if(ret){
invalidate();
return true;
}else{
return super.onTouchEvent(event);
}
}
}

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;

import org.json.JSONObject;

/**
* Created by DCloud on 2017/1/5.
*/
class CircleRefreshDrawer {
Paint paint = new Paint();
/**整个下拉刷新的位置*/
float mDrawerX,mDrawerY,mDrawerYDefault;
/**怎个个下拉刷新的高度*/
float mDrawerWidth,mDrawerHeight;

static final int State_Normal = 0;
static final int State_Enable = 1;
static final int State_Refreshing = 2;
static final int State_Refresh_End = 3;

//刷新状态数据
int mRefreshState = State_Normal;
int mRefreshEnableOffsetY = 100,mRefreshRefreshingOffsetMaxY = 100;
//控件底部y轴值
int mRefreshOffsetY;
//控件底部开始出现时的y轴值
int mOffsetY;
int mAutoBackV;
//    刷新圆弧
RectF mArcRectF = null;
int mRefreshArcStartAngle,mRefreshArcSweepAngle,mRefreshArcX,mRefreshArcY,mRefreshArcWidth,mRefreshArcHeight;
int mCha,mArcColor,mArcRotateAngle,mArcColorAlpha;
final int F_ArcColorAlphaMin = 100;
int mRefreshArcSweepAngleMax = 280;
float mArcStrokeWidth ;
float mCircleShadeStrokeWidth;
int mCircleShadeColor;
float mLastMoveY;
View mBindView = null;
//箭头
int mArrowHeight = 0;
int F_Arrow_Max_Height;
int mArrowColor;
Path mArrowPath = new Path();
JSONObject mJsonData = null;
int mParentWidth,mParentHeight;
private DisplayMetrics mDisplayMetrics;
OnRefreshListener mListener = null;
CircleRefreshDrawer(View adaWebview,OnRefreshListener listener){
mBindView = adaWebview;
mListener = listener;
}

float px2dp(float px){
if(null==mDisplayMetrics){
mDisplayMetrics = mBindView.getResources().getDisplayMetrics();
}
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, px, mDisplayMetrics);
}
void parseData(JSONObject obj,int parentWidth,int parentHeight,float scale){
scale = 3.0f;
mJsonData = obj;
mParentWidth = parentWidth;
mParentHeight = parentHeight;
mArcColor = 0xff2BD009;
mArrowColor = mArcColor;
mCircleShadeColor = 0xDDDDDDDD;
mDrawerWidth = px2dp(40);
mDrawerHeight = px2dp(40);
mArcStrokeWidth = px2dp(2);
mCircleShadeStrokeWidth = px2dp(2f);
F_Arrow_Max_Height = (int)px2dp(5);
mCha = (int)px2dp(11);
mAutoBackV = (int)px2dp(7);
mArcRectF = new RectF();
mRefreshEnableOffsetY = convertToScreenInt(obj.optString("height"), parentWidth, mRefreshEnableOffsetY, scale);
mRefreshRefreshingOffsetMaxY = convertToScreenInt(obj.optString("range"), parentWidth, mRefreshRefreshingOffsetMaxY, scale);
mOffsetY = convertToScreenInt(obj.optString("offset"), parentWidth, mOffsetY, scale);

mRefreshOffsetY = 0;
reset();
mDrawerYDefault = mDrawerY;
}

private void reset(){
mDrawerX = (mParentWidth - mDrawerWidth ) / 2;
mDrawerY = mOffsetY - mDrawerHeight;//绘制位置
mRefreshArcX = (int)mDrawerX + mCha;
mRefreshArcY = (int)mDrawerY + mCha;
mRefreshArcSweepAngle = 0;
mRefreshArcWidth = (int)mDrawerWidth - mCha * 2;
mRefreshArcHeight = (int)mDrawerHeight - mCha * 2;
mRefreshOffsetY = mOffsetY;
mArcRotateAngle = 0;
mRefreshRotate = 0;
mArrowHeight = 0;
mArcScale = 1f;
mArcColorAlpha = F_ArcColorAlphaMin;
mArcRectF.left = mRefreshArcX;
mArcRectF.right = mRefreshArcX + mRefreshArcWidth;
mArcRectF.top = mRefreshArcY;
mArcRectF.bottom = mRefreshArcY + mRefreshArcHeight;
mHandle = false;
}
public void onResize(int parentWidth,int parentHeight,float scale){
parseData(mJsonData,parentWidth,parentHeight,scale);
}
protected void paint(Canvas canvas,int left, int top) {
canvas.save();
canvas.translate(left, top);
onDraw(canvas);
canvas.restore();
}

boolean isRefreshing(){
return mRefreshState == State_Refresh_End || mRefreshState == State_Refreshing;
}
protected void onDraw(Canvas canvas) {
if(mArcScale < 0){
return;
}
canvas.save();
//        Rect rect = new Rect();
//        mBindView.getDrawingRect(rect);
canvas.translate(mBindView.getScrollX() + mBindView.getLeft(), mBindView.getScrollY() + mBindView.getTop());
//        canvas.translate(rect.left, rect.top);
canvas.clipRect(mDrawerX - mArcStrokeWidth, mOffsetY, mDrawerX + mDrawerWidth + mArcStrokeWidth, mRefreshRefreshingOffsetMaxY + mDrawerHeight);
//        canvas.clipRect(mDrawerX, mRefreshOffsetY, mDrawerX + mDrawerWidth, mRefreshOffsetY + mDrawerHeight);
{//调试 数据
//            paint.setColor(Color.BLUE);
//            canvas.drawLine(0, mDrawerY, mParentWidth, mDrawerY, paint);
//            canvas.drawLine(0, mOffsetY, mParentWidth, mOffsetY, paint);
//            paint.setColor(Color.RED);
//            canvas.drawLine(0, mRefreshOffsetY, mParentWidth, mRefreshOffsetY, paint);
//            paint.setColor(Color.BLUE);
//            canvas.drawLine(0, mRefreshEnableOffsetY, mParentWidth, mRefreshEnableOffsetY, paint);
//            canvas.drawLine(0, mRefreshRefreshingOffsetMaxY, mParentWidth, mRefreshRefreshingOffsetMaxY, paint);
//
//            paint.setColor(Color.BLACK);
//            paint.setStyle(Paint.Style.STROKE);
//            canvas.drawRect(mDrawerX, mOffsetY, mDrawerX + mDrawerWidth, mRefreshRefreshingOffsetMaxY + mDrawerHeight, paint);
}

//        Logger.d("Drawer", "mArcRotateAngle=" + mArcRotateAngle + ";mArcRectF=" + mArcRectF + ";mDrawerY=" + mDrawerY + ";mAutoBack=" + mAutoBack + ";mRefreshRotate=" + mRefreshRotate);
if(mRefreshState == State_Refresh_End ) {
canvas.scale(mArcScale, mArcScale, mArcRectF.left + mArcRectF.width() / 2, mArcRectF.top + mArcRectF.height() / 2);
mRunnableEndReFresh.run();
}
if(mAutoBack){
mRunnableEndReFresh.run();
}
drawCircleShade(canvas);
canvas.rotate(mRefreshRotate, mDrawerX + mDrawerWidth / 2, mDrawerY + mDrawerHeight / 2);
drawRefresh(canvas);
canvas.restore();
if(mRefreshState == State_Refreshing){
mRunnableRefresh.run();
}
}

private void drawCircleShade(Canvas canvas){
paint.reset();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(mCircleShadeStrokeWidth);

paint.setColor(mCircleShadeColor);
canvas.drawCircle(mDrawerX + mDrawerWidth / 2, mDrawerY + mDrawerHeight / 2 + mCircleShadeStrokeWidth / 3 , mDrawerWidth / 2 - mCircleShadeStrokeWidth /2, paint);//绘制阴影

//        paint.setColor(mCircleShadeColor | 0xFFCCCCCC);
//        canvas.drawCircle(mDrawerX + mDrawerWidth / 2, mDrawerY + mDrawerHeight / 2, mDrawerWidth / 2 - mCircleShadeStrokeWidth/2, paint);//绘制阴影

paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
canvas.drawCircle(mDrawerX + mDrawerWidth / 2, mDrawerY + mDrawerHeight / 2, mDrawerWidth / 2 - mCircleShadeStrokeWidth /2, paint);//y 方向起始位置为0
}

private void drawRefresh(Canvas canvas){
canvas.save();
mArcRectF.bottom = mRefreshArcY + mArcRectF.height();
mArcRectF.top = mRefreshArcY ;
//设置整个旋转角度
canvas.rotate(mArcRotateAngle - 45, mArcRectF.left + mArcRectF.width() / 2, mArcRectF.top + mArcRectF.height() / 2);
drawRefreshArc(canvas);
if(mRefreshOffsetY != mRefreshEnableOffsetY // 未处在可刷新位置
||( mRefreshState != State_Refreshing && mArcScale == 1)) {//刷新中,消失中均不绘制箭头
drawArrow(canvas);
}
canvas.restore();
}

private void drawRefreshArc(Canvas canvas){
paint.reset();
paint.setColor(Color.argb(mArcColorAlpha, Color.red(mArcColor), Color.green(mArcColor), Color.blue(mArcColor)));
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(mArcStrokeWidth);
canvas.drawArc(mArcRectF, mRefreshArcStartAngle, mRefreshArcSweepAngle, false, paint);
}

private void drawArrow(Canvas canvas){
canvas.save();
canvas.rotate(mRefreshArcSweepAngle, mArcRectF.left + mArcRectF.width() / 2, mArcRectF.top + mArcRectF.height() / 2);//进行旋转,与箭头尾巴随拖动转
canvas.translate(mArcRectF.right, mArcRectF.top + mArcRectF.height() / 2);
paint.setAntiAlias(true);
//绘制箭头
paint.setStyle(Paint.Style.FILL);
mArrowPath.reset();
//等边直角三角形
mArrowPath.lineTo(-mArrowHeight, 0);
mArrowPath.lineTo(0, mArrowHeight);
mArrowPath.lineTo(mArrowHeight, 0);
mArrowPath.close();
paint.setColor(Color.argb(mArcColorAlpha,Color.red(mArcColor),Color.green(mArcColor),Color.blue(mArcColor)));
canvas.drawPath(mArrowPath, paint);
canvas.restore();
}

float mTouchDownX,mTouchDownY;
boolean mHandle = false;
public boolean onTouchEvent(MotionEvent event) {
if(mRefreshState == State_Refreshing) return false;
int action = event.getAction();
switch (action){
case MotionEvent.ACTION_DOWN:
mTouchDownX = event.getX();
mLastMoveY = mTouchDownY = event.getY();
reset();
mHandle = true;
break;
case MotionEvent.ACTION_UP:
if(mRefreshState == State_Enable){
setRefreshState(State_Refreshing);
}else{
endRefresh();
}
break;
case MotionEvent.ACTION_MOVE:
//change松手后的状态
if(event.getY() > mTouchDownY && event.getX() - mTouchDownX < 10){
mHandle = true;
}
mArcScale = 1;
update(event.getX(),event.getY());
if(mRefreshOffsetY > mRefreshEnableOffsetY){//移动距离大于可刷新位置
refreshRotate();
setRefreshState(State_Enable);
}else{
mRefreshState = State_Normal;
}
invalidate();
Log.d("Drawer","mDrawerY=" + mDrawerY + ";mRefreshOffsetY=" + mRefreshOffsetY + ";mRefreshArcSweepAngle=" + mRefreshArcSweepAngle + ";mArcRotateAngle=" + mArcRotateAngle);
break;
}
return mHandle;
}

private void invalidate(){
//        mBindView.invalidate();
mBindView.invalidate((int)mDrawerX, (int)mOffsetY, (int)(mDrawerX + mDrawerWidth), (int)(mRefreshRefreshingOffsetMaxY + mDrawerHeight));
//        mBindView.invalidate((int)mDrawerX, (int)mRefreshOffsetY, (int)(mDrawerX + mDrawerWidth), (int)(mRefreshOffsetY + mDrawerHeight));
//        mBindView.invalidate((int)mDrawerX, (int)mOffsetY, (int)(mDrawerX + mDrawerWidth), (int)(mDrawerX + mDrawerHeight));
}
final static int mRefreshColorChangeAngle = 270;
private int refreshColorRatio(){
return (255 - F_ArcColorAlphaMin) / (mRefreshArcSweepAngleMax - mRefreshColorChangeAngle);
}
private void updateRefreshColor(float moveY){
if(mRefreshArcSweepAngle > mRefreshColorChangeAngle) {
mArcColorAlpha = F_ArcColorAlphaMin + (mRefreshArcSweepAngle - mRefreshColorChangeAngle) * refreshColorRatio();
if (mArcColorAlpha > 255) {
mArcColorAlpha = 255;
} else if (mArcColorAlpha < F_ArcColorAlphaMin) {
mArcColorAlpha = F_ArcColorAlphaMin;
}
}
}

final static int mArrowHeightChangeAngle = 90;
private float arrowHeightRatio(){
return (float)F_Arrow_Max_Height / (mRefreshArcSweepAngleMax - mArrowHeightChangeAngle)  ;
}

private void updateArrowHeight(float moveY){
if(mRefreshArcSweepAngle > mArrowHeightChangeAngle) {
mArrowHeight = (int)((mRefreshArcSweepAngle - mArrowHeightChangeAngle) * arrowHeightRatio());//计算箭头高度
if (mArrowHeight > F_Arrow_Max_Height) {
mArrowHeight = F_Arrow_Max_Height;
} else if (mArrowHeight < 0) {
mArrowHeight = 0;
}
}
}

private void updateRefreshArcSweepAngle(){
float offsetY = (mRefreshOffsetY - mOffsetY);
mRefreshArcSweepAngle = (int)( (offsetY) * arcRatio() );
if(mRefreshArcSweepAngle > mRefreshArcSweepAngleMax) {
mRefreshArcSweepAngle = mRefreshArcSweepAngleMax;
}else if(mRefreshArcSweepAngle < 0){
mRefreshArcSweepAngle = 0;
}
}
private float yRatio(){
return 1.0f;
}

private float arcRatio(){
return (float) mRefreshArcSweepAngleMax / (mRefreshEnableOffsetY - mOffsetY)  ;
}

private void update(float moveTouchX, float moveTouchY){
float offsetY = moveTouchY - mLastMoveY;
float changeY = (int)((offsetY) * yRatio());
mRefreshOffsetY += changeY;
if(mRefreshOffsetY > mRefreshRefreshingOffsetMaxY){
mRefreshOffsetY = mRefreshRefreshingOffsetMaxY;
mDrawerY  += (mRefreshRefreshingOffsetMaxY - mRefreshOffsetY);
}else{
mDrawerY += changeY;//移动位置
}
if(mRefreshOffsetY <= mRefreshRefreshingOffsetMaxY) {
updateRefreshArcSweepAngle();
updateArrowHeight(moveTouchY);
updateRefreshColor(moveTouchY);
//            Log.d("Drawer", "update mDrawerY=" + mDrawerY + ";mRefreshOffsetY=" + mRefreshOffsetY + ";mRefreshArcSweepAngle=" + mRefreshArcSweepAngle + ";mArcRotateAngle=" + mArcRotateAngle);

}
mRefreshArcY = (int) mDrawerY + mCha;
mLastMoveY = moveTouchY;
}
private void setRefreshState(int state){
int t = mRefreshState;
mRefreshState = state;
if(t != state){
onRefreshStateChange(state);
}
}

void endRefresh(){
if(mRefreshState == State_Refreshing){
setRefreshState(State_Refresh_End);
}else{
mRunnableEndReFresh.run();
}
}

float mArcScale = 1;
boolean mAutoBack = false;
Runnable mRunnableEndReFresh = new Runnable() {
@Override
public void run() {
//            Log.d("Drawer","mArcScale=" + mArcScale + ";mDrawerY=" + mDrawerY);

if(mRefreshState == State_Refresh_End) {
if(mArcScale >= 0) { //缩放消失
mArcScale = mArcScale - 0.1f;
refreshingRotate();
}else{
setRefreshState(State_Normal);
}
}else{
if(mDrawerY > mDrawerYDefault){//结束刷新
mAutoBack = true;
update(-1, mLastMoveY - mAutoBackV);
}else{
mAutoBack = false;
setRefreshState(State_Normal);
}
}
invalidate();
}
};

boolean mSweepAngleUp = false;
private void refreshingRotate(){
mArcRotateAngle += 7;//扭动画布
if(mArcRotateAngle >= 360){
mArcRotateAngle = 0;
}
if(mRefreshState == State_Refreshing) {
if (mSweepAngleUp) {
mRefreshArcSweepAngle += 5;
if (mRefreshArcSweepAngle > mRefreshArcSweepAngleMax) {
mRefreshArcSweepAngle = mRefreshArcSweepAngleMax;
mSweepAngleUp = false;
}
} else {
mRefreshArcSweepAngle -= 5;
if (mRefreshArcSweepAngle < 50) {
mRefreshArcSweepAngle = 50;
mSweepAngleUp = true;
}
}
}else{
mSweepAngleUp = false;
}
}

int mRefreshRotate = 0;
private void refreshRotate(){
int offset = (int)((mRefreshOffsetY - mRefreshEnableOffsetY) * refreshRotateRatio());
mRefreshRotate = offset;
}

private float refreshRotateRatio(){
return 270f / (mRefreshRefreshingOffsetMaxY - mRefreshEnableOffsetY);
}
Runnable mRunnableRefresh = new Runnable() {
@Override
public void run() {
if (mRefreshState == State_Refreshing){
if(mRefreshOffsetY > mRefreshEnableOffsetY){//回退到松手可刷新位置
update(-1, mLastMoveY - mAutoBackV);
if(mRefreshOffsetY - mRefreshEnableOffsetY < mAutoBackV){
mRefreshOffsetY = mRefreshEnableOffsetY;
}
}else{//在松手可刷新位置进行 转圈刷新
refreshingRotate();
}
invalidate();
}
}
};

static final String STATE_CHANGED_TEMPLATE = "{status:'%s'}";
private void onRefreshStateChange(int newState){
switch (newState){
case State_Normal:
reset();
//                Log.d("Drawer","普通状态");
break;
case State_Enable:
//                Log.d("Drawer","可刷新");
break;
case State_Refreshing://启动刷新
mRunnableRefresh.run();
//                Log.d("Drawer", "正在刷新");
mListener.onRefreshing(3);
//                mBindView.postDelayed(new Runnable() {
//                    @Override
//                    public void run() {
//                      endRefresh();
//                    }
//                },3000);
break;
case State_Refresh_End:{
mRunnableEndReFresh.run();
//                Log.d("Drawer","刷新结束");
break;
}
}
}

public static int convertToScreenInt(String pStrInt, int pRelInt, int pDeft,float scale){
try {
if(pStrInt == null) return pDeft;
if(pStrInt.endsWith("px")){
pStrInt = pStrInt.substring(0,pStrInt.length() - 2);
if (pStrInt != null && pStrInt.contains(".")) {
return (int)(Float.parseFloat(pStrInt) * scale);
}
return (int)(Integer.parseInt(pStrInt) * scale);
}
if(pStrInt.endsWith("%")){
pStrInt = pStrInt.substring(0,pStrInt.length() - 1);
try {
return pRelInt * Integer.parseInt(pStrInt) / 100;
} catch (NumberFormatException e1) {
return pDeft;
}
}else{//解决当pStrInt 为45.0时,Integer.parseInt异常的问题
return (int)(Double.parseDouble(pStrInt) * scale);
}
} catch (Exception e) {//非px值时
return pDeft;
}
}

interface OnRefreshListener{
void onRefreshing(int state);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐