- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
根据我之前的“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
将使用与以前相同的坐标重新绘制,但位置和布局大小不同。这些屏幕截图演示了实际行为:
左:纵向 - 右:横向
但我想在方向改变时保持相同的坐标和位置,如下所示:
左:与上图相同的肖像 - 右:具有“肖像”坐标的风景
使用 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
的关系。我喜欢使用 Path
和 Matrix
转换的方法。
确定设备发生的旋转后,创建一个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;
}
}
}
纵向
风景
关于android - 从先前的布局方向在相同位置重绘多个路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42986817/
我正在尝试获取从过去的 startposition/location 到当前移动的 currentposition/location 的距离(以米为单位)。 我确实有工作正常的currentposit
所以我有一堆绝对覆盖的 div。用户通过在叠加层上拖动来创建方形 div。如果您要创建一个 div,然后放大和缩小,div 会保持在同一位置,因为它对叠加层是绝对的,如前所述。 然而问题就出在这里。您
我想找到 View 在显示屏幕上的位置。 为此,我使用了 view.getLeft() 、view.getBottom() 、view.getRight() 等方法> , view.getTop()。
我有一个看起来像这样的 View 层次结构(基于其他答案和 Apple 的使用 UIScrollView 的高级 AutoLayout 指南): ScrollView 所需的2 个步骤是: 为 Scr
所以我有一个名为 MARKS 的表,我有这些列 STUDENT_ID, CLASSFORM_NAME, ACADEMIC_YEAR, TERM, SUBJECT_NAME, TOTAL_MARKS
我有一个问题我无法理解,请帮助: 我开发了带有图像的 html 页面,并使用 jQuery UI 帮助使它们可拖动,我将这些图像位置设置为相对位置并给出了左侧和顶部像素,这是页面的链接 http://
我正在尝试创建一个 CSS 动画,它在 sprite 表中循环播放 16 个图像,给人一种幽灵“漂浮”的错觉。动画通过在 background-position 位置之间移动以显示不同状态的幽灵来实现
我正在创建这个网站的 WebView https://nearxt.com/打开时询问位置但是当我使用此链接在 flutter 中创建 webview 时那么它就无法定位我还在应用程序中定义了位置,但
我正在以编程方式创建一个需要跨越 2 个屏幕的窗口。正在创建的窗口的大小是正确的,但窗口大约从第一个屏幕的一半开始。我可以将它拖回第一个屏幕的开头,NSWindow 非常适合。 我只需要知道在窗口的起
位置“/”的匹配叶路由没有元素。这意味着默认情况下它将呈现一个空值,从而导致一个“空”页面 //App.js File import { BrowserRouter as Router, Routes
我有一个运行 Ubuntu 和 Apache 的 VPS 例如,假设地址是:5.5.5.5 在 VPS 上,我有一个名为 eggdrop 的用户(除了我的 root 用户)。 用户 eggdrop 有
我有一个 JLabel与 ImageIcon ,我使用 setIcon() JLabel中的函数. ImageIcon然后上来,坐在我的JLabel 的文字左侧.是否有可能拥有 ImageIcon在文
我的图中有节点,它们的 xlabels 位于它们的左上方。我怎样才能改变这个位置?我希望 xlabels 正好位于节点本身的旁边。 最佳答案 xlp是你想要的属性,但它没有做任何事情。 你不能改变位置
我对基本的 VIM 功能有疑问:(我尝试谷歌搜索但找不到答案) 如何列出所有自定义功能。(我做了 :function 并且不能找到我的自定义函数) 如何获得自定义函数列表中的函数(或它们的存储位置)。
我是 PHP 的新手,虽然我一直在搜索,但我不知道该怎么做。 我知道可以使用 Location("some page") 进行重定向。我还读到,只要没有向用户显示任何内容,它就可以工作。 我想做的是:
如果在 jgrowl.css 中位置更改为“center”,我如何将其覆盖为默认值,即“top-right” $.jGrowl(data, { header: 'data', an
我需要根据用户是否滑动屏幕顶部、屏幕中间或屏幕底部来触发不同的事件。我正在尝试找出最好/最简单的方法来做到这一点,因为我很确定没有办法从 UISwipeGestureRecognizer 获取位置。
我需要枚举用delphi编写的外部应用程序中使用的类 ,因此我需要访问VMT表以获取该信息,但是我找不到任何有关如何在exe(由delphi生成)文件中找到VMT(虚拟方法表)的位置(地址)的文档。
在 D2010 (unicode) 中是否有像 Pos 这样不区分大小写的类似函数? 我知道我可以使用 Pos(AnsiUpperCase(FindString), AnsiUpperCase(Sou
我正在尝试为我的reveal.js 演示文稿制作一个标题,该标题会粘贴在屏幕顶部。标题中的内容在每张幻灯片的基础上都是动态的,因此我必须将标记放在 section 标记中。 显然,如果标记在 sect
我是一名优秀的程序员,十分优秀!