仿Win8图标按下回弹效果

本文参考鸿洋大神的文章
https://blog.csdn.net/lmj623565791/article/details/23441455

效果如图:
这里写图片描述

布局如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context="com.yeaper.contentproviderdemo.MainActivity"
   android:background="#af3fdf">

   <LinearLayout
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:orientation="vertical"
       android:layout_centerInParent="true">

       <com.yeaper.contentproviderdemo.widget.SFImageView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:src="@drawable/timg"
           android:scaleType="matrix" />

       <LinearLayout
           android:layout_width="wrap_content"
           android:layout_height="wrap_content">

           <com.yeaper.contentproviderdemo.widget.SFImageView
               android:id="@+id/sf_iv_avatar"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:src="@drawable/timg"
               android:scaleType="matrix" />

           <com.yeaper.contentproviderdemo.widget.SFImageView
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:src="@drawable/timg"
               android:scaleType="matrix" />

       </LinearLayout>

       <com.yeaper.contentproviderdemo.widget.SFImageView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:src="@drawable/timg"
           android:scaleType="matrix" />
   </LinearLayout>
</RelativeLayout>

自定义ImageView代码如下:

1. 缩放常量的取值

    float val = 1;   
    float s = 0.85f;  
    int i = 0;  
    s = (float) Math.sqrt(1 / s);  
    System.out.println(val);  
    while (i < 5)  
    {  
        val = val *s ;  
        System.out.println(val);  
        i++;  
    }  
    s = 0.85f;  
    i = 0;  
    s = (float) Math.sqrt(s);  
    while (i < 5)  
    {  
        val = val *s ;  
        System.out.println(val);  
        i++;  
    }  

输出结果如下:

    1.0  
    1.0846523  
    1.1764706  
    1.2760615  
    1.384083  
    1.5012488  
    1.384083  
    1.2760615  
    1.1764706  
    1.0846523  
    1.0  

基本是个对称的梯度数据,梯度的幅度由代码中的s控制

2.拦截点击事件,使用Handler,通过不断改变缩放值,控制缩放变换
共有三种状态:
1. SCALE_REDUCE_INIT 收缩开始
2. SCALING 缩放中
3. SCALE_ADD_INIT 扩大开始

3.matrix.postScale的使用
缩放锚点为图片的中心,即宽高的一半,postScale为前后乘matrix矩阵

整体代码:

public class SFImageView extends android.support.v7.widget.AppCompatImageView {

    private static final int SCALE_REDUCE_INIT = 0; //收缩开始状态
    private static final int SCALING = 1; //缩放中状态
    private static final int SCALE_ADD_INIT = 2; //扩张开始状态

    private int mWidth;
    private int mHeight;
    private float mCenterWidth;
    private float mCenterHeight;

    /**
     * 设置一个缩放的常量
     */
    private float mMinScale = 0.85f;
    /**
     * 缩放是否结束
     */
    private boolean isFinish = true;

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

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

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


    @Override
    public void layout(int l, int t, int r, int b) {
        super.layout(l, t, r, b);

        mWidth = getWidth() - getPaddingLeft() - getPaddingRight();
        mHeight = getHeight() - getPaddingTop() - getPaddingBottom();

        mCenterWidth = mWidth/2;
        mCenterHeight = mHeight/2;

        Drawable drawable = getDrawable();
        BitmapDrawable bd = (BitmapDrawable) drawable;
        bd.setAntiAlias(true); //取消锯齿
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mScaleHandler.sendEmptyMessage(SCALE_REDUCE_INIT);
                break;
            case MotionEvent.ACTION_UP:
                mScaleHandler.sendEmptyMessage(SCALE_ADD_INIT);
                break;
        }
        return true;
    }

    /**
     * 控制缩放的Handler
     */
    @SuppressLint("HandlerLeak")
    private Handler mScaleHandler = new Handler() {

        private Matrix matrix = new Matrix();
        private int count = 0;
        private float s;
        private float v;
        /**
         * 是否已经调用了点击事件
         */
        private boolean isClicked = false;

        /**
         * 1.收缩时,s0=sqrt(0.85),v0=1;si=sqrt(0.85),vi+1=vi*si;
         * 2.扩大时,s0=sqrt(1/0.85),v0=1;=sqrt(1/0.85),vi+1=vi*si;
         *
         * 收缩前isFinish = true;收缩那一刻isFinish = false;收缩完isFinish = true
         * 扩大前isFinish = true;扩大那一刻isFinish = false;扩大完isFinish = true
         *
         *
         * @param msg
         */
        public void handleMessage(android.os.Message msg) {
            matrix.set(getImageMatrix());
            switch (msg.what) {
                case SCALE_REDUCE_INIT: //收缩
                    if (!isFinish) {
                        mScaleHandler.sendEmptyMessage(SCALE_REDUCE_INIT);
                    } else {
                        isFinish = false;
                        count = 0;
                        s = (float) Math.sqrt(Math.sqrt(mMinScale));
                        v = 1;
                        mScaleHandler.sendEmptyMessage(SCALING);
                    }
                    break;
                case SCALING: //缩放中
                    v = v * s;
                    beginScale(matrix, v);
                    if (count < 4) {
                        mScaleHandler.sendEmptyMessage(SCALING);
                    } else {
                        isFinish = true;
                        if (mOnViewClickListener != null && !isClicked) {
                            isClicked = true;
                            mOnViewClickListener.onViewClick(SFImageView.this);
                        } else {
                            isClicked = false;
                        }
                    }
                    count++;
                    break;
                case SCALE_ADD_INIT: //扩大
                    if (!isFinish) {
                        mScaleHandler.sendEmptyMessage(SCALE_ADD_INIT);
                    } else {
                        isFinish = false;
                        count = 0;
                        s = (float) Math.sqrt(Math.sqrt(1.0f / mMinScale));
                        v = 1;
                        mScaleHandler.sendEmptyMessage(SCALING);
                    }
                    break;
            }
        }
    };

    /**
     * 缩放
     *
     * @param matrix
     * @param scale
     */
    private synchronized void beginScale(Matrix matrix, float scale) {
        //改变scale值,通过Matrix进行缩放变换
        matrix.postScale(scale, scale, mCenterWidth, mCenterHeight);
        Log.i("SFImageView", "scale="+scale);
        setImageMatrix(matrix);
    }

    /**
     * 回调接口
     */
    private OnViewClickListener mOnViewClickListener;

    public void setOnClickIntent(OnViewClickListener onViewClickListener) {
        this.mOnViewClickListener = onViewClickListener;
    }

    public interface OnViewClickListener {
        void onViewClick(SFImageView view);
    }

}

SFImageView使用如下:
因为消费了点击事件,所以在按下并且收缩完成后,触发点击回调,并设置isClicked为true,扩大完成后,设置isClicked为false,完成一次点击事件

a = findViewById(R.id.sf_iv_avatar);
a.setOnClickIntent(new SFImageView.OnViewClickListener() {
    @Override
    public void onViewClick(SFImageView view) {
        Toast.makeText(MainActivity.this, "eeded", Toast.LENGTH_LONG).show();
    }
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值