旋转视图层次90度

我正在研究FrameLayout的子类,它应该旋转所有的孩子90度。 我这样做是为了克服Android 2.1及以下版本中的风景相机限制,通过将活动放在横向上,但将相机覆盖放入此框架布局覆盖图中,使其看起来像是人像( 这是如何Layar是这样做的 )为了完成这个,我正在调整Jeff Sharkey的代码来旋转视图。 我的问题是,我可以旋转Framelayout,但我不能调整它来匹配新的尺寸。 所以在我的g1上,而不是320×480的横向480×320照相机视图的纵向视图,我得到一个320×320框在中间显示我的肖像视图与两边砍掉。

这是我的代码到目前为止:

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维度,但一直没有能够得到这个工作。 任何帮助,您可以提供非常感谢。

我有同样的问题,并设法解决它。 我不用手动旋转每个视图或布局,而是使用了一个LayoutAnimationController。

首先,在/ res / anim / called 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> 

然后,在你的活动的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)之上的元素,只需在SurfaceHolder上方放置一个FrameLayout,将所有元素放置在该FrameLayout中,然后调用布局“MyScreen_ContentLayout”。 完成。

希望帮助别人,花了我相当长的时间把所有的东西放在一起。

使用API​​级别11和更高版本,您可以使用方法setRotation(degreesFloat); 以编程方式更改视图的旋转,或者您可以使用XML属性android:rotation=""在XML中对其进行更改。 还有一些方法/属性只能改变视图旋转的X或Y值: Android Docs – View(setRotation) 。

所以现在只要你使用API​​级别11或更高,你应该能够将旋转应用到包装布局节点。 但是,您可能还需要更改顶层布局的尺寸以匹配旋转后所需的尺寸。 也就是说,如果您有一个尺寸为800×1280的纵向视图,您必须将它们更改为1280×800,以便在旋转到横向后排列它们。

使用这个库你可以旋转整个视图层次https://github.com/rongi/rotate-layout

喜欢这个

在这里输入图像描述

一般来说,这对我来说是一种工作。

 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和Y偏移,以便旋转后的视图成为全屏。

以上是一个“风景”旋转的版本。 要实现一个倒转的景观只适用于270度的旋转。 您可以修改代码片段中的代码,也可以以更通用的方式应用外部旋转

 final YourViewOrViewGroup layout = inflater.inflate(...); if (currentOrientation.isInverted()) { layout.setRotation(layout.getRotation + 180f); } 

通过这种方式,您可以在xml定义中embedded旋转的View / ViewGroup,并在屏幕方向更改时对“port”和“land”版本进行充气,但是这似乎超出了本主题。

编辑:实际上延迟偏移设置要好得多,直到至less一个布局过去。 这是因为在我的情况下,在第一次onMeasure()之后,将会绘制视图(在设置偏移之前)。 最终,它可能会被视为一个小问题,因为视图/布局一开始就不会被绘制在最终的范围内。 (更新了片段)

我想你在onMeasure中忘了一行。

 @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(heightMeasureSpec, widthMeasureSpec); setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); } 

从垂直seekbar代码采取在这里: 我怎样才能得到一个工作垂直SeekBar在Android?

您可能需要调整getMeasuredHeight()以使其成为屏幕的正确大小。

尝试closures您的视图根的子剪辑:在您的RotateLayout的父级上调用setClipChildren(false) ,并在您的RotateLayout的onMeasure方法中放置这些行:

 super.onMeasure(heightMeasureSpec, widthMeasureSpec); setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); 

我的问题和你基本上是一样的,而且我还没有testing过我的解决scheme – 我明天就做,并告诉它是否工作正常。