美文网首页Android知识Android开发Android开发部落
自定义View之图片随手势方向动态加载

自定义View之图片随手势方向动态加载

作者: ac噜噜噜 | 来源:发表于2017-04-03 13:55 被阅读184次

    自定义View之图片随手势方向动态加载

    直接看实现出来的效果吧~

    ![slipView动画]](https://img.haomeiwen.com/i2099469/dd8526fae911645a.gif?imageMogr2/auto-orient/strip)

    图片和图片的标题会根据手势的不同以不同的方式动态加载,标题伴随透明变化,图片则有一定的阴影效果。

    第一次看到这个效果是在JeasonWong的个人博客里面,但是具体的地址不记得了~

    我在看了原作者的效果之后感觉很不错,于是就自己做了一些手势上的扩展,图片的加载使用Glide库

    分析

    • 图片的滑动效果和文字的滑动效果基本一致,但是为了日后使用方便,把图片和文字的实现代码分离,但是可以使用模板模式简化重复的部分。
    • 图片和文字的动态切换效果,使用ViewGroup中放置两个TextView和ImageView来动态的隐藏和显示实现,另外图片在切换的时候会有第三个ImageView作为遮罩层

    撸代码

    0x01

    首先是两个辅助类,SlipTo枚举滑动的方向,BaseEntey方便信息的传递。分别对应图片链接和图片标题

    /**
    * 滑动方向
    */
    public enum SlipTo {
    UP,
    DOWN,
    LEFT,
    RIGHT
    }
    
    public class BaseEntry {
        public String pathurl;
        public String title;
        ‘’‘省略’‘’
    }
    

    0x02

    SlipBase类作为SlipImage和SlipText的父类,使用监听属性动画的更新状态间接更新ViewGroup中对应子View的状态。实现动态的效果

    doAnimFinish()和 doAnim()方法则是留给子类分别实现自己的逻辑

      /**
     * 滑动的方法
     */
    public void slip(){
        if (isSlip){
            return;
        }
        isSlip = true;
        ValueAnimator valueAnimator = null;
        switch (slipTo){
            case DOWN:
            case UP:
                valueAnimator =  ValueAnimator.ofFloat(-mHeight,0)
                        .setDuration(mDuration);
                valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator valueAnimator) {
                        float margintop = (float)valueAnimator.getAnimatedValue();
                        mMarginTopHeight = (int)margintop;
                        if(margintop == 0){
                            postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    mMarginTopHeight = - mHeight;
                                    mRepeatCount++;
                                    //动画执行完毕  更新状态
                                    doAnimFinish();
                                    isSlip = false;
                                }
                            },50);
                        }else{
                            //动画执行中 不断更新状态
                            doAnim();
                        }
                    }
                });
             break;
    
            case LEFT:
            case RIGHT:
                valueAnimator =  ValueAnimator.ofFloat(-mWidth,0)
                        .setDuration(mDuration);
                valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator valueAnimator) {
                        float margintop = (float)valueAnimator.getAnimatedValue();
                        mMarginTopHeight = (int)margintop;
                        if(margintop == 0){
                            postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    mMarginTopHeight = - mWidth;
                                    mRepeatCount++;
                                    doAnimFinish();
                                    isSlip = false;
                                }
                            },50);
                        }else{
                            doAnim();
                        }
                    }
                });
            break;
        }
        valueAnimator.start();
    }
    

    0x03

    SlipImage就是实现图片滑动的逻辑的主要类,SlipText和她基本一样这里就主要介绍下这个类好了

    initView添加三个ImageView到ViewGroup里面,两个负责装载图片,一个是遮罩层

    doAnim()方法中设置遮罩层的透明度,并且调用requestLayout不断刷新界面

    doAnimFinish()里面则加载图片并且移除遮罩层

    其实主要的图片显示逻辑在onLayout方法里面,根据不同的状态设置不同的位置参数,从而实现视图的显示和隐藏。

    @Override
    protected void initView() {
        if(list.size()==0) return;
        removeAllViews();
        MarginLayoutParams marginLayoutParams = new MarginLayoutParams(mWidth,mHeight);
    
        for(int i=0; i<imageViews.length; i++){
            imageViews[i] = new ImageView(getContext());
            //加载图片
            Glide.with(getContext()).load(getCurrentPath(i)).dontTransform().dontAnimate().centerCrop().into(imageViews[i]);
            addView(imageViews[i],-1,marginLayoutParams);
        }
        ImageView imageView = new ImageView(getContext());
        imageView.setBackgroundColor(Color.parseColor("#90000000"));
        imageView.setAlpha(0f);
        addView(imageView,-1,marginLayoutParams);
    }
    
    @Override
    protected void doAnimFinish() {
        //根据循环的次数加载图片 实现循环加载
        if(isEvenRepeat()){
            Glide.with(getContext()).load(getCurrentPath(mRepeatCount+1)).dontTransform().centerCrop().dontAnimate().into(imageViews[1]);
        }else{
            Glide.with(getContext()).load(getCurrentPath(mRepeatCount+1)).dontTransform().centerCrop().dontAnimate().into(imageViews[0]);
        }
        //去除阴影
        getChildAt(2).setAlpha(0f);
    }
    
    @Override
    protected void doAnim() {
        switch (slipTo){
            case DOWN:
            case UP:
                getChildAt(2).setAlpha(1-(-mMarginTopHeight/(float)mHeight));
                break;
            case LEFT:
            case RIGHT:
                getChildAt(2).setAlpha(1-(-mMarginTopHeight/(float)mWidth));
                break;
        }
        //请求重绘
        requestLayout();
    }
    
    @Override
    protected void onLayout(boolean changeed, int l, int t, int r, int b) {
        if(getChildCount()<3) return;
        MarginLayoutParams marginLayoutParams;
        switch (slipTo){
            case DOWN:
                for (int i=0;i<getChildCount(); i++){
                    View childView = getChildAt(i);
                    marginLayoutParams = (MarginLayoutParams) childView.getLayoutParams();
                    int cl= marginLayoutParams.leftMargin, ct = 0, cr = cl + mWidth, cb;
                    if(isEvenRepeat()){
                        if(i==0) {
                            ct = mMarginTopHeight + mHeight;
                        }else if(i==1){
                            ct = mMarginTopHeight;
                        }
                    }else{
                        if(i==0){
                            ct = mMarginTopHeight;
                        }else if(i==1){
                            ct = mMarginTopHeight + mHeight;
                        }
                    }
                    if(i==2){
                        ct = mMarginTopHeight + mHeight;
                    }
                    cb = ct + mHeight;
                    childView.layout(cl,ct,cr,cb);
                }
                break;
    
            case UP:
                for (int i=0;i<getChildCount(); i++){
                    View childView = getChildAt(i);
                    marginLayoutParams = (MarginLayoutParams) childView.getLayoutParams();
                    int cl= marginLayoutParams.leftMargin, ct = 0, cr = cl + mWidth, cb;
                    if(isEvenRepeat()){
                        if(i==0) {
                            ct = -mHeight-mMarginTopHeight;
                        }else if(i==1){
                            ct = -mMarginTopHeight;
                        }
                    }else{
                        if(i==0){
                            ct = -mMarginTopHeight;
                        }else if(i==1){
                            ct = -mMarginTopHeight - mHeight;
                        }
                    }
                    if(i==2){
                        ct = -mMarginTopHeight - mHeight;
                    }
                    cb = ct + mHeight;
                    childView.layout(cl,ct,cr,cb);
                }
                break;
            case RIGHT:
                for (int i=0;i<getChildCount(); i++){
                    View childView = getChildAt(i);
                    marginLayoutParams = (MarginLayoutParams) childView.getLayoutParams();
                    int cl= 0, ct = marginLayoutParams.topMargin, cr , cb = ct + mHeight;
                    if(isEvenRepeat()){
                        if(i==0) {
                            cl = mMarginTopHeight+mWidth;
                        }else if(i==1){
                            cl = mMarginTopHeight;
                        }
                    }else{
                        if(i==0){
                            cl = mMarginTopHeight;
                        }else if(i==1){
                            cl =mMarginTopHeight+mWidth;
                        }
                    }
                    if(i==2){
                        cl = mMarginTopHeight+mWidth;
                    }
                    cr = cl + mWidth;
                    childView.layout(cl,ct,cr,cb);
                }
                break;
            case LEFT:
                for (int i=0;i<getChildCount(); i++){
                    View childView = getChildAt(i);
                    marginLayoutParams = (MarginLayoutParams) childView.getLayoutParams();
                    int cl= 0, ct = marginLayoutParams.topMargin, cr , cb = ct + mHeight;
                    if(isEvenRepeat()){
                        if(i==0) {
                            cl = -mMarginTopHeight-mWidth;
                        }else if(i==1){
                            cl = -mMarginTopHeight;
                        }
                    }else{
                        if(i==0){
                            cl =  -mMarginTopHeight;
                        }else if(i==1){
                            cl = -mMarginTopHeight-mWidth;
                        }
                    }
                    if(i==2){
                        cl = -mMarginTopHeight-mWidth;
                    }
                    cr = cl + mWidth;
                    childView.layout(cl,ct,cr,cb);
                }
                break;
    
    
        }
    
    }
    

    0x04

    在SlipView中将 SlipImage和SlipText组合,统一调度并添加手势控制

    SlipView还有公开方法:setData用于设置数据,slipTo用于使用者自行控制图片动态加载方向

     /**
     * 通过滑动事件  控制图片加载方向
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                downY = (int) event.getRawY();
                downX = (int) event.getRawX();
                return true;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                upY = (int) event.getRawY();
                upX = (int) event.getRawX();
                if(Math.abs(downY-upY)>y_limit){
                    if((downY - upY) >0)
                        slipTo(SlipTo.UP);
                    else
                        slipTo(SlipTo.DOWN);
                }
                if(Math.abs(downX-upX)>x_limit){
                    if((downX-upX) >0)
                        slipTo(SlipTo.LEFT);
                    else
                        slipTo(SlipTo.RIGHT);
                }
                break;
        }
        return false;
    }
    

    0x05

    使用

            //设置数据
        slipViewImage.setData(data);
    
        //自行控制图片加载方向
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                slipViewImage.slipTo(SlipTo.DOWN);
            }
        });
    

    下载查看全部代码github地址

    相关文章

      网友评论

        本文标题:自定义View之图片随手势方向动态加载

        本文链接:https://www.haomeiwen.com/subject/gfsnottx.html