Android自定义View之Layout的放缩
在项目中遇到一个需要进行布局放大的需求,但是查找只找到了ImageView的放缩,后期经过查找资料,完成了该需求:
首先我们新建ScaleLayoutDemo并新建ScaleLayout继承自RelativeLayout
新建后的ScaleLayout代码如下所示:
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
/**
* Created by tuozhaobing on 16-4-10.
* Add Some Description There
*/
public class ScaleLayout extends RelativeLayout {
public ScaleLayout(Context context) {
super(context);
}
public ScaleLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScaleLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
添加手势监听类:ScaleGestureDetector
详细代码如下:
private Context mContext;
private ScaleGestureDetector mScaleDetector =null;
public void init(Context context){
mContext = context;
mScaleDetector = new ScaleGestureDetector(mContext, new OnPinchListener());
}
private class OnPinchListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
float currentSpan;
float startFocusX;
float startFocusY;
public boolean onScaleBegin(ScaleGestureDetector detector) {
currentSpan = detector.getCurrentSpan();
startFocusX = detector.getFocusX();
startFocusY = detector.getFocusY();
return true;
}
public boolean onScale(ScaleGestureDetector detector) {
ScaleLayout zoomableRelativeLayout= (ScaleLayout) ((Activity)mContext).findViewById(R.id.scalelayout);
zoomableRelativeLayout.relativeScale(detector.getCurrentSpan() / currentSpan, startFocusX, startFocusY);
currentSpan = detector.getCurrentSpan();
return true;
}
public void onScaleEnd(ScaleGestureDetector detector) {
ScaleLayout zoomableRelativeLayout= (ScaleLayout) ((Activity)mContext).findViewById(R.id.scalelayout);
zoomableRelativeLayout.release();
}
}
public void relativeScale(float scaleFactor, float pivotX, float pivotY) {
mScaleFactor *= scaleFactor;
if(scaleFactor >= 1) {
mPivotX = mPivotX + (pivotX - mPivotX) * (1 - 1 / scaleFactor);
mPivotY = mPivotY + (pivotY - mPivotY) * (1 - 1 / scaleFactor);
}
else {
pivotX = getWidth()/2;
pivotY = getHeight()/2;
mPivotX = mPivotX + (pivotX - mPivotX) * (1 - scaleFactor);
mPivotY = mPivotY + (pivotY - mPivotY) * (1 - scaleFactor);
}
this.invalidate();
}
public void release() {
if(mScaleFactor < MIN_SCALE) {
final float startScaleFactor = mScaleFactor;
Animation a = new Animation(){
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
scale(startScaleFactor + (MIN_SCALE - startScaleFactor)*interpolatedTime,mPivotX,mPivotY);
}
}
;
a.setDuration(300);
startAnimation(a);
}
else if(mScaleFactor > MAX_SCALE) {
final float startScaleFactor = mScaleFactor;
Animation a = new Animation() {
@Override protected void applyTransformation(float interpolatedTime, Transformation t) {
scale(startScaleFactor + (MAX_SCALE - startScaleFactor)*interpolatedTime,mPivotX,mPivotY);
}
}
;
a.setDuration(300);
startAnimation(a);
}
}
public void scale(float scaleFactor, float pivotX, float pivotY) {
mScaleFactor = scaleFactor;
mPivotX = pivotX;
mPivotY = pivotY;
this.invalidate();
}
重写onTouchevent
接管Touch事件:
@Override
public boolean onTouchEvent(MotionEvent event) {
mScaleDetector.onTouchEvent(event);
return true;
}
重写OnDraw方法,实现放缩效果:
@Override
protected void onDraw(Canvas canvas) {
setScaleX(mScaleFactor);
setScaleY(mScaleFactor);
super.onDraw(canvas);
}
至此我们就完成了一个可以放缩的Layout,下一次,我们会解释
setScaleX(mScaleFactor);
setScaleY(mScaleFactor);
和canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(mScaleFactor, mScaleFactor, mPivotX, mPivotY);
的区别。