自定义View练习一之图片以及标题随手势方向平滑加载

这个效果最初是在 http://www.wangyuwei.me/ 看到和学习的,不过我自己做了一些手势上的扩展。 感谢JeasonWong

先放效果图:


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

step1:

标题的透明度变化,图片的阴影以及图片和标题的滑动,考虑使用监听属性动画的更新状态来实现。因为标题和图片的功能大致相似,所以这里抽出SlipBase类作为基类,实现公共部分。

SlipBase核心代码

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();
                        }
                    }
                });

其中mMarginTopHeight 是为了计算ViewGroup里面的子View距离ViewGroup顶部或者右边的变量。另外这里展示出来的只是上下滑动时需要的属性动画,左右滑动时大同小异,详细的请下载代码查看。

这里说明一下:子View的隐藏这里都是使用负margintop实现的。


step2:

分别在SlipImage(控制图片)和SlipText(控制标题)里面实现

<span style="font-family:Microsoft YaHei;font-size:18px;">//动画执行完毕  更新状态
doAnimFinish();</span>
<span style="font-family:Microsoft YaHei;font-size:18px;">和</span>
<pre name="code" class="java"><span style="font-family:Microsoft YaHei;font-size:18px;"> //动画执行中 不断更新状态
 doAnim();</span>
 

这两个方法

以SilpImage类为例

首先初始化自定义View   两个加载图片的ImageView和一个阴影ImageView

   @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);
    }

先看doAnimFinish方法 比较容易看

    @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);
    }
再看doAnim方法,不断的请求更新UI

 @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();
    }
最终导致界面UI变化的肯定就是onLayout方法了,瞅一眼,代码虽然较多但是都是大白话一样,就是根据mMarginTopHeight以及手势和循环的次数控制子View的位置参数。

    @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;


        }


step3:

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

判断手势的代码如下

 /**
     * 通过滑动事件  控制图片加载方向
     * @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;
    }

step4

在使用的时候直接放入数据调用

slipViewImage.setData(data);


当然这只是实现这种效果的一种方式而已,主要是练习一下自定义View的写法。

如果对这个小View有兴趣也可以去下载源码看一看,改一改。


github下载   点击打开链接

csdn下载     源码










  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值