gpt4 book ai didi

android - 从先前的布局方向在相同位置重绘多个路径

转载 作者:塔克拉玛干 更新时间:2023-11-02 18:55:43 24 4
gpt4 key购买 nike

根据我之前的“How to create a BottomBar as StickyBottomCaptureLayout in camera2 Android api?”问题,我创建了一个带有 StickyBar (SB) 的布局,它始终锁定在系统栏上方/附近。我在 onLayout() 中设置了 SB 和其他布局的默认位置和坐标(完全是 as my answer )。

上层布局是一个简单的自定义 DrawView,它有一个由用户绘制的 Path 的 ArrayList。当设备旋转时,它会调用 onDraw() 并多次调用 canvas.drawPath()。但是,Path 将使用与以前相同的坐标重新绘制,但位置和布局大小不同。这些屏幕截图演示了实际行为:

portrait landscape

左:纵向 - 右:横向

但我想在方向改变时保持相同的坐标和位置,如下所示:

portrait lanscape

左:与上图相同的肖像 - 右:具有“肖像”坐标的风景

使用 android:orientation="portrait" 锁定我的 Activity 不是预期的解决方案。我使用 android:configChanges="orientation" 和一个 OrientationListener 来检测旋转并防止完全重新创建 Activity

  • 我试图在 onLayout() 中设置其他不同的位置,但显然,这不是正确的方法。
  • 我以前试过像这样转换多个 Path:

    for (Path path : mPathList) {
    Matrix matrix = new Matrix();
    RectF bounds = new RectF();
    path.computeBounds(bounds, true);

    // center points to rotate
    final float px = bounds.centerX();
    final float py = bounds.centerY();
    // distance points to move
    final float dx; // ?
    final float dy; // ?
    /** I tried many calculations without success, it's
    not worth to paste these dumb calculations here... **/

    matrix.postRotate(rotation, px, py); // rotation is 90°, -90° or 0
    matrix.postTranslate(dx, dy); // ?
    path.transform(matrix);
    }
  • 我还尝试按如下方式旋转 Canvas :

    @Override
    protected void onDraw(Canvas canvas) {
    canvas.save();
    canvas.rotate(rotation); // rotation is 90°, -90° or 0

    canvas.drawColor(mDrawHelper.getBackgroundViewColor());
    for (int i=0; i < mPathList.size(); i++) {
    canvas.drawPath(mPathList.get(i), mPaintList.get(i));
    }
    if (mPath != null && mPaint != null)
    canvas.drawPath(mPath, mPaint);

    canvas.restore();
    }

无论如何,我尝试了很多操作,但在这种特定情况下似乎没有任何效果。是否有人可以分享一个可以引导我朝着正确方向前进的绝妙想法?
预先感谢您的帮助。

最佳答案

更新:方法论已得到简化,更易于遵循。示例应用已更新。

我想我明白你想做什么。您希望图形保持与您定义的 StickyCaptureLayout 的关系。我喜欢使用 PathMatrix 转换的方法。

确定设备发生的旋转后,创建一个Matrix做相应的旋转,围绕图形中心旋转。

mMatrix.postRotate(rotationDegrees, oldBounds.centerX(), oldBounds.centerY());

这里的oldBounds是location之前图形的边界。我们将使用它来确定旋转图形的边距。继续旋转

mPath.transform(mMatrix)

图形已旋转但位置不正确。它处于旧位置但已旋转。创建一个翻译 Matrix 以将 Path 移动到适当的位置。实际计算取决于旋转。对于 90 度旋转,计算是

transY = -newBounds.bottom; // move bottom of graphic to top of View
transY += getHeight(); // move to bottom of rotated view
transY -= (getHeight() - oldBounds.right); // finally move up by old right margin
transX = -newBounds.left; // Pull graphic to left of container
transX += getWidth() - oldBounds.bottom; // and pull right for margin

其中 transY 是 Y 平移,transX 是 X 平移。 oldBounds 是旋转前边界,newBounds 是旋转后边界。这里要注意的重要一点是 getWidth() 会给你“旧的”View 高度,而 getHeight() 会给你旧的 查看宽度。

这是一个示例程序,可以完成我上面描述的内容。下面的几个图形显示了使用此示例应用程序进行的 90 度旋转。

演示应用

package com.example.rotatetranslatedemo;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.Display;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;

public class MainActivity extends Activity {

private DrawingView dv;
private Paint mPaint;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dv = new DrawingView(this);
setContentView(dv);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.GREEN);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
}

public class DrawingView extends View {

private Bitmap mBitmap;
private Path mPath;
private Paint mBitmapPaint;
Context context;
private Paint paint;
Matrix mMatrix = new Matrix();
RectF oldBounds = new RectF();
RectF newBounds = new RectF();

public DrawingView(Context c) {
super(c);
context = c;
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.MITER);
paint.setStrokeWidth(4f);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);

mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}

@Override
protected void onDraw(Canvas canvas) {
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
int rotationDegrees = 0;
float transX = 0;
float transY = 0;

super.onDraw(canvas);

canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

// Determine the rotation of the screen.
switch (display.getRotation()) {
case Surface.ROTATION_0:
break;

case Surface.ROTATION_90:
rotationDegrees = 270;
break;

case Surface.ROTATION_180:
rotationDegrees = 180;
break;

case Surface.ROTATION_270:
rotationDegrees = 90;
break;

default:
rotationDegrees = 0;
break;
}

if (mPath == null) { // Just define what we are drawing/moving
mPath = setupGraphic();
}

// Reposition the graphic taking into account the current rotation.
if (rotationDegrees != 0) {
mMatrix.reset();
// Rotate the graphic by its center and in place.
mPath.computeBounds(oldBounds, true);
mMatrix.postRotate(rotationDegrees, oldBounds.centerX(), oldBounds.centerY());
mPath.transform(mMatrix);
// Get the bounds of the rotated graphic
mPath.computeBounds(newBounds, true);
mMatrix.reset();
if (rotationDegrees == 90) {
transY = -newBounds.bottom; // move bottom of graphic to top of View
transY += getHeight(); // move to bottom of rotated view
transY -= (getHeight() - oldBounds.right); // finally move up by old right margin
transX = -newBounds.left; // Pull graphic to left of container
transX += getWidth() - oldBounds.bottom; // and pull right for margin
} else if (rotationDegrees == 270) {
transY = -newBounds.top; // pull top of graphic to the top of View
transY += getHeight() - oldBounds.right; // move down for old right margin
transX = getWidth() - newBounds.right; // Pull to right side of View
transX -= getHeight() - oldBounds.right; // Reestablish right margin
}
mMatrix.postTranslate(transX, transY);
mPath.transform(mMatrix);
}
canvas.drawPath(mPath, mPaint);
}

// Define the graphix that we will draw and move.
private Path setupGraphic() {
int startX;
int startY;
final int border = 20;
Path path;

if (getHeight() > getWidth()) {
startX = getWidth() - border - 1;
startY = getHeight() - border - 1;
} else {
startX = getHeight() - border - 1;
startY = getWidth() - border - 1;
}
startX = startX - 200;

Pt[] myLines = {
new Pt(startX, startY),
new Pt(startX, startY - 500),

new Pt(startX, startY),
new Pt(startX - 100, startY),

new Pt(startX, startY - 500),
new Pt(startX - 50, startY - 400),

new Pt(startX, startY - 500),
new Pt(startX + 50, startY - 400),

new Pt(startX + 200, startY),
new Pt(startX + 200, startY - 500)
};

// Create the final Path
path = new Path();
for (int i = 0; i < myLines.length; i = i + 2) {
path.moveTo(myLines[i].x, myLines[i].y);
path.lineTo(myLines[i + 1].x, myLines[i + 1].y);
}

return path;
}

private static final String TAG = "DrawingView";

}

// Class to hold ordered pair
private class Pt {
float x, y;

Pt(float _x, float _y) {
x = _x;
y = _y;
}
}
}

纵向

enter image description here

风景

enter image description here

关于android - 从先前的布局方向在相同位置重绘多个路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42986817/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com