本文参考鸿洋大神的文章
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();
}
});