安卓:旋转整个布局

37

我需要能够在点击按钮时即时旋转整个布局。

我可以使用 layout.setRotation(270.0f) 等方法来旋转布局。但问题是,旋转后,布局的 heightwidth 与其父控件不匹配。

我已经尝试过倒置 heightwidth,像这样:

RelativeLayout layout = (RelativeLayout)findViewById(R.id.rootLayout);
LayoutParams layoutParams = layout.getLayoutParams();
int height = layout.getHeight();
int width = layout.getWidth();
layoutParams.height = width;
layoutParams.width = height;

什么也没做。

我正在使用 sdk 14

下面的第一张图片是应用程序启动时的样子。第二张是旋转后的样子。我希望填充黑色的“空白”区域。任何帮助都将不胜感激。

下面的图像只显示布局中的一个按钮。但实际上,布局要复杂得多。我试图实现“伪造”横向视图。

起始状态 旋转后

编辑:更改了图片并添加了描述。

9个回答

48

不确定这个有什么用处,但它是一个不错的谜题。下面是对我有效的做法:

在旋转点击事件中,执行以下操作:

RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.main);
int w = mainLayout.getWidth();
int h = mainLayout.getHeight();

mainLayout.setRotation(270.0f);
mainLayout.setTranslationX((w - h) / 2);
mainLayout.setTranslationY((h - w) / 2);

ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) mainLayout.getLayoutParams();
lp.height = w;
lp.width = h;
mainLayout.requestLayout();

布局如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:id="@+id/main"
    android:layout_height="match_parent"
    android:background="#ffcc88"
    tools:context=".TestRotateActivity" >

    <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        />

    <Button 
        android:id="@+id/rotate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Rotate"
        android:layout_centerInParent="true"
        />

</RelativeLayout>

没错,这很有效。正是我需要的。现在我只需要添加不同的旋转选项。使用requestLayout即可实现。 - boulaycote
2
谢谢你提供的好解决方案...这个技巧对我也有用,但它会缩放我的子ImageView...我想要防止这种情况发生...请帮帮我。 - H Raval

5
试试这段代码:
btnRotate.setOnClickListener(new OnClickListener()
{
    @SuppressLint("NewApi")
    @Override
    public void onClick(View v) 
    {
        int orientation = getResources().getConfiguration().orientation;
        switch(orientation)
        {
            case Configuration.ORIENTATION_LANDSCAPE:
                llparent.setRotation(270.0f);
                RelativeLayout.LayoutParams layoutParams_LandsScape =
                    new RelativeLayout.LayoutParams(
                        rlRoot.getHeight(), rlRoot.getWidth()); 
                layoutParams_LandsScape.setMargins(
                    rlRoot.getTop(), rlRoot.getRight(),
                    rlRoot.getBottom(), rlRoot.getLeft());
                layoutParams_LandsScape.addRule(RelativeLayout.CENTER_IN_PARENT);
                llparent.setLayoutParams(layoutParams_LandsScape);  
                break;
            case Configuration.ORIENTATION_PORTRAIT:
                llparent.setRotation(270.0f);
                RelativeLayout.LayoutParams layoutParams_Portrait =
                    new RelativeLayout.LayoutParams(
                        rlRoot.getHeight(), rlRoot.getWidth()); 
                layoutParams_Portrait.setMargins(
                    0, 0, rlRoot.getBottom(), rlRoot.getLeft());    
                layoutParams_Portrait.addRule(RelativeLayout.CENTER_IN_PARENT);
                llparent.setLayoutParams(layoutParams_Portrait);
                break;
            }
        }
    });
}

还有XML:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".RotateAnim">

    <RelativeLayout
        android:id="@+id/rlroot"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#090">

        <LinearLayout
            android:id="@+id/llParent"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#900"
            android:gravity="center"
            android:orientation="vertical">

            <Button
                android:id="@+id/button1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:gravity="center"
                android:text="Button"/>
        </LinearLayout>
    </RelativeLayout>
</RelativeLayout>

还没有时间测试它,抱歉。我一定会告诉你的。 - boulaycote

3

简单而巧妙的方法,通过按钮点击实现屏幕方向控制。以下是一个示例。

在此,我使用了sharedPreference(基于方向设置布尔值)。

按钮onClick的方法。

public void rotate(View v) {
    edt = prefs.edit();

    if (!prefs.getBoolean("screen_protrait", true)) {
        edt.putBoolean("screen_protrait", true);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    } else {
        edt.putBoolean("screen_protrait", false);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
    edt.commit();
}

在XML中为旋转按钮设置一个onClick方法。
       <Button
   android:id="@+id/bt_rotate"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_centerInParent="true"
   android:onClick="rotate"
   android:text="Rotate" />

最后一个,在你想从应用中设置首选项的Activity的onCreate方法中进行设置,如下所示:
  prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

继续编码,你可以实现你的目标...如果它适用于你的情况,请告诉我。


2
    // get root layout from activity's XML
    LinearLayout mParentLayout = (LinearLayout) findViewById(R.id.activity_main);

    // get screen size from DisplayMetrics if you need to rotate before the screen is shown
    DisplayMetrics displayMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

    int height = displayMetrics.heightPixels;
    int width = displayMetrics.widthPixels;

    // if you are rotating after the view was shown
    // acquire width and height from the layout's parent's LayoutParams

    // calculate offset to move the view into correct position
    int offset = (width - height) / 2;

    // rotate the layout
    FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(height, width);
    mParentLayout.setLayoutParams(lp);
    // 90° clockwise
    mParentLayout.setRotation(90.0f);
    mParentLayout.setTranslationX(offset);
    mParentLayout.setTranslationY(-offset);

虽然这看起来像是一个建议的答案,但它展示了如何从DisplayMetrics获取尺寸,并计算平移的偏移量略有不同,因为这是唯一正常工作的方式。


最佳答案! - Eddwhis

2
如果你想要直接旋转屏幕,可以强制屏幕方向。否则,没有简单的方法来实现你试图做的事情,因为View.setRotation(float)总是会先渲染View的“真实”边界,然后再将其旋转!我的建议是仔细考虑哪些布局元素应该被旋转,然后具体旋转这些元素。

唯一真正的“自动”实现方式是创建一个自定义布局,本质上测量、布局和绘制子元素时进行旋转...老实说,我只有在真正需要时才会这样做,而且可能不值得麻烦!


1
我建议只旋转按钮,而不是旋转整个布局。
btn_rotate.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) 
{
    rotation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.rotate);
    rotation.setFillAfter(true);
    btn_rotate.startAnimation(rotation);
}
});

rotate.xml

<set>
    <rotate
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:duration="0"
          android:fromDegrees="270"
          android:pivotX="50%"
          android:pivotY="50%"
          android:startOffset="0"
          android:toDegrees="270" />
</set>

谢谢您的建议,我已经尝试过了。问题是我真的需要“伪造”横向方向,而不是在原地旋转视图。实际上,布局会比一个简单的按钮复杂得多。 - boulaycote

0
尝试这段代码:
(RelativeLayoutOuterFrame)是您要旋转的布局的名称。实际上,我们不会旋转布局,只是更改高度和宽度的值。
    int w = RelativeLayoutOuterFrame.getWidth();
    int h = RelativeLayoutOuterFrame.getHeight();
    ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) RelativeLayoutOuterFrame.getLayoutParams();
    lp.height = w;
    lp.width = h;
    RelativeLayoutOuterFrame.setGravity(RelativeLayout.CENTER_IN_PARENT);
    RelativeLayoutOuterFrame.setGravity(RelativeLayout.CENTER_HORIZONTAL);
    RelativeLayoutOuterFrame.requestLayout();

0

尝试在旋转后将您的布局参数设置为match_parent:

layout.setRotation(270.0f)

然后

RelativeLayout layout = (RelativeLayout) findViewById(R.id.rootLayout);     
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

编辑:获取父视图 View parent = layout.getParent(); 并将父视图的宽度和高度设置为所需的布局 - 宽度与高度互换。


我已经尝试过了,但没有成功。似乎在那个特定的时刻(按钮点击)修改layoutparams是行不通的。 - boulaycote
我不确定这有什么不同,但让我试试看。 - boulaycote

0

我需要“伪造”横向布局。这将是真正的方法 :) 感谢提供的链接! - boulaycote

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接