上上周写的一个demo,仿照网易一元夺宝的下拉刷新效果。

原效果是(第一部分)一个小太阳拉下来,然后松开回弹上去,

(第二部分)再掉下来一个硬币进行中轴旋转。

本文实现的效果的是第一部分的,效果演示图如下:

Android 仿网易一元夺宝客户端下拉加载动画实现(一)_第1张图片

Gif图看起来比较卡顿。。。其实真机演示效果还是很流畅的。

下面分析实现过程

当时因为时间有限没有写在下拉刷新的组件中,也没有封装成一个单独的组件,只是在主布局后面写了一个View然后实现相应的操作,进行封装并不难,这里就不花时间BB了,下面是布局文件:

                                                
布局文件预览:

Android 仿网易一元夺宝客户端下拉加载动画实现(一)_第2张图片

因为设置了透明,所以这里在没有item的情况下是能看到后面的布局的。

代码实现

通过下拉刷新类NGReFlashListView进行事件判断,然后通过回调把相应的事件传递给NGImageView中改变视图显示。

下面是两个类的源代码:

NGReFlashListView类:

package location.haidian.com.wypulltoreflush.view;import android.content.Context;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.AbsListView;import android.widget.AbsListView.OnScrollListener;import android.widget.ListView;import location.haidian.com.wypulltoreflush.R;public class NGReFlashListView extends ListView implements OnScrollListener {    private View header;    private int headerHeight;    private int firstVisibleItem;    private int scrollState;    private final int NONE = 0;    private final int PULL = 1;    private final int RELESE = 2;    private final int REFLASHING = 3;    public NGReFlashListView(Context context) {        super(context);        initView(context);    }    public NGReFlashListView(Context context, AttributeSet attrs) {        super(context, attrs);        initView(context);    }    public NGReFlashListView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        initView(context);    }    /**     * @param context     */    private void initView(Context context) {        LayoutInflater inflater = LayoutInflater.from(context);        header = inflater.inflate(R.layout.layout_heard, null);        measureView(header);        headerHeight = header.getMeasuredHeight();        topPadding(-headerHeight);        this.addHeaderView(header);        this.setOnScrollListener(this);    }    /**     * @param view     */    private void measureView(View view) {        ViewGroup.LayoutParams p = view.getLayoutParams();        if (p == null) {            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,                    ViewGroup.LayoutParams.WRAP_CONTENT);        }        int width = ViewGroup.getChildMeasureSpec(0, 0, p.width);        int height;        int tempHeight = p.height;        if (tempHeight > 0) {            height = MeasureSpec.makeMeasureSpec(tempHeight,                    MeasureSpec.EXACTLY);        } else {            height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);        }        view.measure(width, height);    }    /**     * @param topPadding     */    private void topPadding(int topPadding) {        header.setPadding(header.getPaddingLeft(), topPadding,                header.getPaddingRight(), header.getPaddingBottom());        header.invalidate();    }    @Override    public void onScroll(AbsListView view, int firstVisibleItem,                         int visibleItemCount, int totalItemCount) {        this.firstVisibleItem = firstVisibleItem;    }    @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {        this.scrollState = scrollState;    }    boolean isRemark;//初始化标识    int startY;    int state;    @Override    public boolean onTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                if (firstVisibleItem == 0) {                    onRlvScrollListener.onScrollYChangged(0, 0);                    isRemark = true;                    startY = (int) ev.getY();                }                break;            case MotionEvent.ACTION_MOVE:                onMove(ev);                break;            case MotionEvent.ACTION_UP:                if (state == RELESE) {                    onRlvScrollListener.onScrollYChangged(0, 3);                    state = REFLASHING;                    reflashViewByState();                    //iReflashListener.onReflash();                } else if (state == PULL) {                    state = NONE;                    onRlvScrollListener.onScrollYChangged(0, 0);                    isRemark = false;                    reflashViewByState();                }                break;        }        return super.onTouchEvent(ev);    }    int space;  //间距    int topPadding;     //headview距离顶端的距离,初始-200    /**     * @param ev     */    private void onMove(MotionEvent ev) {        if (!isRemark) {            return;        }        int tempY = (int) ev.getY();        space = tempY - startY;        if (space >= 230) {            space = 230;        }        topPadding = space - headerHeight;        onRlvScrollListener.onScrollYChangged(space, state);        switch (state) {            case NONE:                if (space > 0) {                    state = PULL;                    reflashViewByState();                }                break;            case PULL:                topPadding(topPadding);                if (space == headerHeight + 30                        && scrollState == SCROLL_STATE_TOUCH_SCROLL) {                    state = RELESE;                    reflashViewByState();                }                break;            case RELESE:                if (space < headerHeight + 30) {                    state = PULL;                    reflashViewByState();                } else if (space <= 0) {                    state = NONE;                    isRemark = false;                    reflashViewByState();                }                break;        }    }    /**     * 控制下拉刷新的图像文字显示     */    private void reflashViewByState() {        switch (state) {            case NONE:                //缓慢滑上去                topPadding(-headerHeight);                break;            case PULL:                break;            case RELESE:                break;            case REFLASHING:                break;        }    }    /**     * 刷新完成     */    public void reflashComplete() {        state = NONE;        onRlvScrollListener.onScrollYChangged(0, state);        isRemark = false;        reflashViewByState();    }    //绘制背景的接口    public interface OnRlvScrollListener {        void onScrollYChangged(int Y, int state);    }    private OnRlvScrollListener onRlvScrollListener;    public void setOnRlvScrollListener(OnRlvScrollListener onRlvScrollListener) {        this.onRlvScrollListener = onRlvScrollListener;    }}

NGImgView.java

实现比较简单,根据传来的回调状态改变进行小太阳和两只球球手以及手臂的绘制就可以了。

package location.haidian.com.wypulltoreflush.view;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.drawable.BitmapDrawable;import android.util.AttributeSet;import android.util.Log;import android.widget.ImageView;import location.haidian.com.wypulltoreflush.R;/** * Created by nangua on 2016/8/28. */public class NGImgView extends ImageView implements NGReFlashListView.OnRlvScrollListener {    private float scale;    private final int NONE = 0;    private final int PULL = 1;    private final int RELESE = 2;    private final int REFLASHING = 3;    public int state = 0;    private float WITH;     //屏幕总宽    private float scrollY;    private Bitmap sun0;    public float time = 0;    public NGImgView(Context context, AttributeSet attrs) {        super(context, attrs);        initView();    }    private void initView() {        sun0 = ((BitmapDrawable) getResources().getDrawable(R.drawable.ic_sun0)).getBitmap();        scale = this.getResources().getDisplayMetrics().density;    }    @Override    protected void onDraw(Canvas canvas) {        Paint paint = new Paint();        paint.setAntiAlias(true);//抗锯齿        paint.setColor(Color.parseColor("#C4885A"));        Log.d("xiaojingyu","State:" + state);        if (state!=3) {            time = 0; //重置时间            //画两只球球手            canvas.drawCircle(WITH / 2 - 40 * scale, 55 * scale, 5 * scale, paint);            canvas.drawCircle(WITH / 2 + 40 * scale, 55 * scale, 5 * scale, paint);            //画笑脸            canvas.drawBitmap(sun0,                    null,                    new RectF(WITH / 2 - 50,                            55 * scale + scrollY - (scrollY / 230) * 50,                            WITH / 2 + 50,                            55 * scale + scrollY - (scrollY / 230) * 50 + 100),                    null            );            //画手臂            paint.setStrokeWidth(1);            canvas.drawLine(WITH / 2 - 40 * scale, 55 * scale,                    WITH / 2 - 50, 55 * scale + scrollY,                    paint            );            canvas.drawLine(WITH / 2 + 40 * scale, 55 * scale,                    WITH / 2 + 50, 55 * scale + scrollY,                    paint            );        } else if (state == 3) {            //1秒钟拉上去,2秒钟旋转            //第一秒            if (time < 30) {                time += 1;                //画两只球球手                canvas.drawCircle(WITH / 2 - 40 * scale, 55 * scale, 5 * scale, paint);                canvas.drawCircle(WITH / 2 + 40 * scale, 55 * scale, 5 * scale, paint);                //画笑脸                canvas.drawBitmap(sun0,                        null,                        new RectF(WITH / 2 - 50,                                55 * scale + 180 - (time / 30) * 230,                                WITH / 2 + 50,                                55 * scale + 280 - (time / 30) * 230),                        null                );                //画手臂                paint.setStrokeWidth(1);                canvas.drawLine(WITH / 2 - 40 * scale, 55 * scale,                        WITH / 2 - 50,                        55 * scale + 230 - (time / 30) * 230,                        paint                );                canvas.drawLine(WITH / 2 + 40 * scale, 55 * scale,                        WITH / 2 + 50,                        55 * scale + 230 - (time / 30) * 230,                        paint                );                postInvalidateDelayed(1);            } else {                if (!isBeginMainAnimation) {                    isBeginMainAnimation = true;                    iReflashListener.onReflash();                }            }        }        super.onDraw(canvas);    }    public static boolean isBeginMainAnimation = false;    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        WITH = this.getWidth();    }    @Override    public void onScrollYChangged(int Y, int state) {        this.state = state;        switch (state) {            case NONE:                break;            case PULL:                //下拉                scrollY = Y;                break;            case RELESE:                break;            case REFLASHING:                break;        }    }    private IReflashListener iReflashListener;  //回调接口    public void setInterface(IReflashListener iReflashListener) {        this.iReflashListener = iReflashListener;    }    /**     * @author Administrator     */    public interface IReflashListener {        void onReflash();    }}





更多相关文章

  1. 【Android 性能优化】布局渲染优化 ( GPU 过度绘制优化总结 | CP
  2. Android 中ListView悬浮头部效果设置
  3. Android 屏幕切换效果实现 (转)
  4. Android 优化布局层次结构
  5. 谈谈android 布局 的优化
  6. android Activity线性布局和表格布局实例讲解
  7. 【ALearning】第四章 Android Layout组件布局(一)
  8. android 拖动效果 Gallery 实例

随机推荐

  1. 三分钟搞定Android数据库升级
  2. Android消息机制源码解读
  3. (转载)Android显示GIF
  4. Android F&Q
  5. APK签名
  6. android 学习第一课
  7. TabLayout用法,android顶部导航栏,android
  8. 去除Android系统应用的通知功能
  9. android multi user中MTP 多用户的处理
  10. 关于Android APK反编译的探索