项目中需要使用头像可以循环轮播的效果,哈哈,啥也不说,先上效果图,

不要看例子花里胡哨的,其实只是中间那四个头像啊!单独抽出来是右边这样的图片效果,这里是搞了个按钮开启自动更新的任务。

         

 

要想使用自动轮播头像闪动,首先需要圆形的头像,这个圆形的头像图片使用的是一个叫CircleImageView的开源控件,大家可以参考下面这篇博客,  https://blog.csdn.net/zhoubin1992/article/details/47258639

写的已经非常清晰了,他就是一个CircleImageView.java文件,复制过来这个java文件和一个arrrs.xml文件就可以使用了,目的是将我们提供的各种形状的图片替换成圆形的头像。

具体实现,先看下布局文件,很简单,就是四个上面使用的控件,四个CircleImageView,就这样,木有了:(请忽略这四个图片的名字,太乱了,不想改了o(╥﹏╥)o)

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/ly_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="@color/light">

        <com.example.fake_hago_2.view.CircleImageView
            android:id="@+id/top_2"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_toLeftOf="@+id/top_img"
            android:layout_marginRight="7dp"
            android:layout_centerInParent="true"
            android:src="@drawable/pic2"
            app:civ_border_width="2dp"
            app:civ_border_color="@color/light" />
        <com.example.fake_hago_2.view.CircleImageView
            android:id="@+id/top_img"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:src="@drawable/hugh"
            android:layout_marginRight="7dp"
            app:civ_border_width="2dp"
            app:civ_border_color="@color/light" />
        <com.example.fake_hago_2.view.CircleImageView
            android:id="@+id/top_3"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_toRightOf="@+id/top_img"
            android:layout_marginRight="7dp"
            android:layout_centerInParent="true"
            android:src="@drawable/pic3"
            app:civ_border_width="2dp"
            app:civ_border_color="@color/light" />
        <com.example.fake_hago_2.view.CircleImageView
            android:id="@+id/top_4"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:layout_toRightOf="@+id/top_3"
            android:src="@drawable/pic4"
            app:civ_border_width="2dp"
            app:civ_border_color="@color/light" />

    </RelativeLayout>

</merge>

接下来要自定义布局啦,我们继承RelativeLayout,然后重写初始化函数,在bindView()里面find到我们的每一个ImageView的Id,因为需要单独控制每个ImageView图片播放动画的时机,这样才有四个图片挨个播放的效果,具体的实现就是从MainActivity中启动我们这个自定义View的函数startFlashAvaterTask(),里面定义一个TimerTask,这个Task每隔两秒,发送四个之间间隔100毫秒的消息,交个Handler处理,handler根据接收到消息的先后顺序去开始四个ImageView各自的动画,大致逻辑就是这样子,具体看代码吧,注释写的比较清楚了:

public class FlashAvaterView extends RelativeLayout{

    private ImageView top_2;
    private ImageView top_3;
    private ImageView top_4;
    private ImageView mTopImg;

    private Timer mTimer;
    private long mIntervalTime = 0;

    private volatile boolean isRun = true;

    private static class AnimHandler extends Handler {}

    //不同时间间隔接受到的消息,播放对应的View的动画
    private AnimHandler mHandler = new AnimHandler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 0) {
                scaleAnimator(top_2);
            } else if (msg.what == 1) {
                scaleAnimator(mTopImg);
            } else if (msg.what == 2) {
                scaleAnimator(top_3);
            } else if (msg.what == 3) {
                scaleAnimator(top_4);
            }
            super.handleMessage(msg);
        }

    };

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

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

    public FlashAvaterView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        bindViews(context);
    }

    private void bindViews(Context context) {
        LayoutInflater.from(context).inflate(R.layout.flash_avater_view, this, true);
        if (mTimer == null) {
            mTimer = new Timer();
        }

        top_2 = (CircleImageView) findViewById(R.id.top_2);
        mTopImg = (CircleImageView) findViewById(R.id.top_img);
        top_3 = (CircleImageView) findViewById(R.id.top_3);
        top_4 = (CircleImageView) findViewById(R.id.top_4);
    }

    //启动轮播任务的时间点
    public void startFlashAvaterTask(long time) {
        if (mTimer == null) {
            mTimer = new Timer();
        } else {
            if (isRun) {
                mTimer.scheduleAtFixedRate(new MyTask(), 1, 2000);
                isRun = false;
            }
        }
    }

    //由于需要四个头像之间播放也有先后顺序,因此设置一个时间间隔,间隔mIntervalTime发送消息给handler
    private class MyTask extends TimerTask {
        @Override
        public void run() {
            for (int i = 0 ; i < 4; i++) {
                mIntervalTime += 100;
                mHandler.sendEmptyMessageDelayed(i, mIntervalTime);
            }
        }
    }

    //缩小、放大的动画
    private void scaleAnimator(final ImageView img){
        final float scale = 0f;
        AnimatorSet scaleSet = new AnimatorSet();
        ValueAnimator valueAnimatorSmall = ValueAnimator.ofFloat(1.0f, scale);
        valueAnimatorSmall.setDuration(200);

        ValueAnimator valueAnimatorLarge = ValueAnimator.ofFloat(scale, 1.0f);
        valueAnimatorLarge.setDuration(200);

        valueAnimatorSmall.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float scale = (Float) animation.getAnimatedValue();
                img.setScaleX(scale);
                img.setScaleY(scale);
            }
        });
        valueAnimatorLarge.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float scale = (Float) animation.getAnimatedValue();
                img.setScaleX(scale);
                img.setScaleY(scale);
            }
        });
        scaleSet.play(valueAnimatorSmall).before(valueAnimatorLarge);
        scaleSet.start();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
    }
}

具体怎个用法就很简单了,在XML布局文件中引入这个FlashAvaterView,然后findViewById(),和使用普通控件一样了:

xml中引入:

<com.example.fake_hago_2.view.FlashAvaterView
            android:id="@+id/flash_avater"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal" />

java中find它:

FlashAvaterView flashAvaterView = (FlashAvaterView) helper.getView(R.id.flash_avater);
flashAvaterView.startFlashAvaterTask(3000);

项目完整的地址:

https://github.com/buder-cp/base_component_learn/tree/master/circle_small_big

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐