我正在尝试创建一个无尽的可缩放环,像这样-
每当用户捏放大时,就会在中心创建一个新的小圆圈,而外圆圈会变大。我正在使用pinch zoom in relative layout来创建以下效果,但无法正确实现。我已经为此创建了一个仓库,让我知道您是否可以提供帮助 https://github.com/rohankandwal/zoomable-growing-circles
更新:-
在提到的stackoverflow答案上更改了dispatchDraw
方法-
protected void dispatchDraw(Canvas canvas) {
Paint myPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
myPaint.setStyle(Paint.Style.STROKE);
int strokeWidth = 4; // or whatever
myPaint.setStrokeWidth(strokeWidth);
myPaint.setColor(0xffff0000); //color.RED
float radius = (float) (0.5 * (width + height) * 2.5);
for (int i = 1; i <= 51; i=i+10) {
canvas.drawCircle(canvas.getWidth() / 2, canvas.getWidth() / 2, (radius) + mScaleFactor + i,
myPaint);
}
canvas.save();
super.dispatchDraw(canvas);
canvas.restore();
}
此代码允许圈子扩大-
没有捏缩放的原始图像
缩放时的图像
如您所见,缩放有效,但不知道在特定级别缩放时如何创建新的圆圈。
答案 0 :(得分:3)
如果我正确理解了您想要的内容,则代码中没有太多更改
在OnPinchListener
中:
public boolean onScale(ScaleGestureDetector detector) {
// 1 : no zoom
final float zoomLevel = detector.getCurrentSpan() / startingSpan;
zoomableRadarLayout.scale(zoomLevel, startFocusX, startFocusY);
return true;
}
和ZoomableRadarLayout
中的
// current pinch
private float mScaleFactor = 1;
// previous pinches
private float mAccumulatedScaleFactor = 1;
protected void dispatchDraw(Canvas canvas) {
...
float radius = (float) (0.5 * (width + height) * 2.5);
// space between circles
int step = 10;
// radius of the outer circle
int outerRadius = (int) (radius * mScaleFactor * mAccumulatedScaleFactor);
// radius of the inner circle
int innerRadius = 0;
for (int i = outerRadius; i >= innerRadius; i = i - step) {
canvas.drawCircle(canvas.getWidth() / 2, canvas.getWidth() / 2, i, myPaint);
}
...
}
public void restore() {
// add the ending pinch to the previous ones
mAccumulatedScaleFactor = mAccumulatedScaleFactor * mScaleFactor;
mScaleFactor = 1;
this.invalidate();
}
如果可能的话,建议避免在绘图时创建诸如Paint
之类的绘图对象。例如将创建内容放在某种init方法中。
答案 1 :(得分:1)
您可以使用这种方法:计算内圆的半径(最小半径),然后绘制圆并增大半径,而圆在屏幕上可见(最大半径不大于从屏幕中心到其一个角的距离) )。尝试使用ScaleGestureDetector
的自定义视图:
public class ZoomableRingView extends View {
private Paint mPaint;
private ScaleGestureDetector mScaleDetector;
private float mDeltaRadius = 0;
private final float mBaseRadius = 50;
private float mPinchBaseRadius = mBaseRadius;
private float mMinRadius = mBaseRadius;
public ZoomableRingView(Context context) {
super(context);
init(context);
}
public ZoomableRingView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ZoomableRingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public ZoomableRingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
@Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.save();
drawCircles(canvas);
canvas.restore();
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
mScaleDetector.onTouchEvent(ev);
return true;
}
private void init(Context context) {
setWillNotDraw(false);
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setAntiAlias(true);
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
private void drawCircles(Canvas canvas) {
int canvasWidth = canvas.getWidth();
int canvasHeight = canvas.getHeight();
int centerX = canvasWidth / 2;
int centerY = canvasHeight / 2;
float maxRadius = (float) Math.sqrt(centerX * centerX + centerY * centerY);
int nCircles = (int) Math.ceil(maxRadius / mBaseRadius) + 1;
// calculate radius change
mMinRadius = mPinchBaseRadius + mDeltaRadius / 2;
// bring radius to [0..2 * mBaseRadius] interval
while (mMinRadius < 1f) {
mMinRadius += 2 * mBaseRadius;
}
while (mMinRadius > 2 * mBaseRadius) {
mMinRadius -= 2 * mBaseRadius;
}
// draw circles from min to max
float radius = mMinRadius;
for (int ixCircle = 0; ixCircle < nCircles; ixCircle++) {
canvas.drawCircle(centerX, centerY, radius, mPaint);
radius += 2 * mBaseRadius;
}
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
float startingSpan;
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mPinchBaseRadius = mMinRadius;
startingSpan = detector.getCurrentSpan();
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
mDeltaRadius = detector.getCurrentSpan() - startingSpan;
invalidate();
return true;
}
}
}
您拥有该自定义视图的activity.xml
可能像这样:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_channel1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<{YOUR_PACKAGE_NAME}.ZoomableRingView
android:id="@+id/zoomablering_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
您应该得到类似的东西: