我正在研究FrameLayout的子类,它应该将其所有子节点旋转90度。我这样做是为了克服Android 2.1及以下版本中仅限风景的相机限制,让活动处于风景中,但将我的相机叠加放入此framelayout叠加层,使其看起来像是肖像({{3为了实现这一点,我正在调整this is how Layar does it来旋转视图。我的问题是我可以旋转Framelayout,但我不能调整它以匹配新的尺寸。所以在我的g1上,而不是在横向480x320相机视图上的320x480纵向视图,我在中间看到一个320x320的盒子,显示我的纵向视图,两侧被切断。
到目前为止,这是我的代码:
public class RotateLayout extends FrameLayout {
private Matrix mForward = new Matrix();
private Matrix mReverse = new Matrix();
private float[] mTemp = new float[2];
public RotateLayout(Context context) {
super(context);
}
public RotateLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
/* (non-Javadoc)
* @see android.widget.FrameLayout#onMeasure(int, int)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//This didn't work:
//super.onMeasure(heightMeasureSpec, widthMeasureSpec);
}
/* (non-Javadoc)
* @see android.widget.FrameLayout#onSizeChanged(int, int, int, int)
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.rotate(270, getWidth()/2, getHeight()/2);
//This code will stretch the canvas to accommodate the new screen size. This is not what I want.
//float scaleX=(float)getHeight()/getWidth();
//float scaleY=(float)getWidth()/getHeight();
//canvas.scale(scaleX, scaleY, getWidth()/2, getHeight()/2);
mForward = canvas.getMatrix();
mForward.invert(mReverse);
canvas.save();
canvas.setMatrix(mForward); //This is the matrix we need to use for proper positioning of touch events
super.dispatchDraw(canvas);
canvas.restore();
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
final float[] temp = mTemp;
temp[0] = event.getX();
temp[1] = event.getY();
mReverse.mapPoints(temp);
event.setLocation(temp[0], temp[1]);
return super.dispatchTouchEvent(event);
}
}
我已尝试覆盖OnMeasure
来切换视图的X和Y维度,但无法使其工作。
非常感谢您提供的任何帮助。
答案 0 :(得分:39)
我遇到了同样的问题,并设法解决了这个问题。 我没有手动旋转每个视图或布局,而是使用了LayoutAnimationController。
首先,将文件放在/ res / anim /中,名为rotation.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="-90"
android:pivotX="50%"
android:pivotY="50%"
android:duration="0" android:fillAfter="true">
</rotate>
然后,在您的Activity的onCreate中,执行
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.myscreen);
Animation rotateAnim = AnimationUtils.loadAnimation(this, R.anim.rotation);
LayoutAnimationController animController = new LayoutAnimationController(rotateAnim, 0);
FrameLayout layout = (FrameLayout)findViewById(R.id.MyScreen_ContentLayout);
layout.setLayoutAnimation(animController);
}
如果要旋转位于相机预览视图(SurfaceHolder)上方的元素,只需将FrameLayout放在SurfaceHolder上方,将所有元素放在FrameLayout中,然后调用Layout“MyScreen_ContentLayout”。完成。
希望帮助别人,让我花了很长时间才把所有东西都放在一起。
答案 1 :(得分:7)
使用API级别11及更高版本,您可以使用方法setRotation(degreesFloat);
以编程方式更改视图的旋转,或者您可以使用XML属性android:rotation=""
在XML中更改它。还有一些方法/属性可以仅更改视图旋转的X或Y值:Android Docs - View (setRotation)。
所以现在只要您使用的是API级别11或更高级别,您就应该能够将旋转应用于包装器布局节点。但是,您可能还需要更改顶级布局的尺寸以匹配旋转后所需的尺寸。即如果您有一个尺寸为800x1280的纵向视图,则必须将它们更改为1280x800才能在旋转到横向后排成一行。
答案 2 :(得分:3)
答案 3 :(得分:1)
这一般对我有用。
private void init() {
setRotation(90f);
}
public YourViewOrViewGroup(final Context context) {
super(context);
init();
}
... (all the View/ViewGroup constructors) ...
@Override
protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) {
super.onLayout(changed, l, t, r, b);
final int width = getWidth();
final int height = getHeight();
final int offset = Math.abs(width - height) / 2;
setTranslationX(-offset);
setTranslationY(offset);
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
}
你想要做的是将宽度与高度交换,然后放入X&amp; Y偏移,以便在旋转后视图变为全屏。
以上是'风景'旋转版。要实现倒置景观,只需施加270度旋转即可。您可以修改代码段中的代码,也可以以更通用的方式在外部应用轮换,即
final YourViewOrViewGroup layout = inflater.inflate(...);
if (currentOrientation.isInverted()) {
layout.setRotation(layout.getRotation + 180f);
}
通过这种方式,您可以将旋转的View / ViewGroup嵌入到xml定义中,并在屏幕方向更改时对“port”和“land”版本进行充气,但这似乎超出了此主题。
编辑:实际上,推迟偏移设置直到至少一个布局传递结束为止。 这是因为在我的情况下,在第一次onMeasure()之后,将绘制视图(在设置偏移之前)。最终它可能会出现故障,因为视图/布局最初不会在最终边界内绘制。 (更新了代码段)
答案 4 :(得分:0)
我想你在onMeasure上忘记了一行。
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
取自垂直搜索栏的代码: How can I get a working vertical SeekBar in Android?
您可能需要使用getMeasuredHeight()来调整屏幕大小。
答案 5 :(得分:0)
尝试关闭视图根的子剪辑:在RotateLayout的父级上调用setClipChildren(false)
,并在RotateLayout的onMeasure方法中放置以下行:
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
我和你的问题基本相同,我还没有测试过我的解决方案 - 明天我会做,告诉它是否正常工作。