安卓屏幕显示及方向的若干需求与解决方案

有的适合会遇到锁定应用程序为横/竖屏的需求,那么我们如何控制Activity的屏幕方向呢?

废话不多说,我们直接上方法

控制屏幕方向

通过修改配置清单文件实现

  1. 首先打开AndroidManifest.xml
  2. 找到我们需要进行配置的Activity
  3. 找到其<activity>节点
  4. 为其添加android:screenOrientation属性,参数方面portrait为竖屏,landscape为横屏。

下面提供一个landscape横屏的测试:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.a4_1activity">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:screenOrientation="landscape"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

效果如?..由于是模拟器,默认是竖着的,但是可以看到,模拟器的画面已经被强制横屏了。可以在右侧工具栏

将模拟器横过来,效果如?

通过代码实现

主要是?的语句

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
ActivityInfo有SCREEN_ORIENTATION_PORTRAIT和SCREEN_ORIENTATION_LANDSCAPE两种选择

和前面一样,portrait为竖屏,landscape为横屏。

 

我们写一段简单的竖屏测试,但是我们没有去掉之前配置清单的配置。

package com.example.a4_1activity;

import android.content.pm.ActivityInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //同样的portrait为竖屏,landscape为横屏
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setContentView(R.layout.activity_main);
        
    }
}

可以看到一个奇妙的现象,即一开始是横屏,随后变为竖屏。

 

网上有资料说配置清单的优先级高一些?会以清单文件为准,可是实际测试,配置清单似乎只是顺序上先于代码执行,而非等级上高于。可能是版本的原因,有兴趣的同学可以测试下低版本的?看看网上的说法是否正确。

 


有时候,控制方向还不够,可能还需要控制全屏显示。

控制全屏

可以通过下面的代码实现

package com.example.a4_1activity;

import android.content.pm.ActivityInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //同样的portrait为竖屏,landscape为横屏
        //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        
        //控制全屏
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_main);

    }
}

效果如?,仔细观察一下,全屏的效果主要是状态栏没了。

去除标题栏

然后还有发现一个标题栏,如果也想去掉。可以添加如下语句,同时修改继承的父类为Activity

 requestWindowFeature(Window.FEATURE_NO_TITLE);
package com.example.a4_1activity;

import android.content.pm.ActivityInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //同样的portrait为竖屏,landscape为横屏
        //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        //控制全屏
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        //去除标题栏
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        setContentView(R.layout.activity_main);

    }
}

效果如下:

设置主题实现实现无标题全屏

只要加上一句android:theme="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen"即可实现等效的效果

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.a4_1activity">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:screenOrientation="landscape"
            android:theme="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

效果如?,无视颜色...是主题自带的默认效果。

 

窗口模式

有全屏对应的就有窗口模式,只需要如下语句

android:theme="@android:style/Theme.DeviceDefault.Dialog"
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.a4_1activity">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            
            android:theme="@android:style/Theme.DeviceDefault.Dialog"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 注意配置窗口模式不能再在清单文件中配置屏幕方向,否则冲突报错,你也没见过横着的dialog是把← ←


屏幕旋转若干事项

屏幕旋转销毁Activity

首先明确一个关键点:实际上App在进行横竖屏切换的时候会重新创建Activity。

可以通过在onCreate方法加入测试输出语句,然后手动进行横竖屏切换,观察是否多次进行输出来验证。


启动

然后我们横屏

可以看到确实再一次创建了Activity


明确了关键点之后,意味着什么呢?当前Activity内的信息将会被丢失。

可以试着定义一个变量,输出一次,再加一个button,点击使这个变量发生变化,再输出,然后旋转屏幕来观察输出的结果,测试比较简单,就不进行放截图了。


Activity的里的所有信息被丢失可不是一件小事,我们如何解决这个问题呢?

在这之前我们先修改一下我们MainActivity继承的父类,改成Activiy

然后就要提到我们?方法(其实之前打过照面哦)

onSaveInstanceState

← ← 实际上这块应该放再Activity的生命周期里讲,接下来我们详细来讲一讲。

onSaveInstanceState

protected void onSaveInstanceState(Bundle outState)

  • 首先明确调用时机,当Activity被意外回收的时候,onSaveInstanceState就会被调用
  • 然后是参数onSaveInstanceState提供一个Bundle参数。

Bundle在之前的文章已经有过介绍了:  https://blog.csdn.net/nishigesb123/article/details/88877609

总之就是各种能传递数据就对了,get和put来取和存。

  • 我们可以把数据存在这个Bundle里,存了之后有啥用呢?

然后我们默默的看一眼我们的onCreate

是不是有什么似曾相识的东西(其实在之前的文章里也提到过,onCreate参数里的Bundle实际上就是onSaveInstanceState存的Bundle!

话到这里差不多已经基本都清楚了。直接上代码(布局的话比较简单,给一个按钮,然后加个onClick事件就好)

package com.example.a4_1orientation;

import android.app.Activity;
import android.os.PersistableBundle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

    int index=0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        System.out.println("onCreate被调用");

        if (savedInstanceState!=null){
            index = savedInstanceState.getInt("index",0);
        }
    }
    public void onClick(View view){
        index++;
        System.out.println("index的值为:"+index);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        System.out.println("onSaveInstanceState被调用");
        outState.putInt("index",index);

    }


}

首次运行:

点击三次button

旋转屏幕

再次点击button

可以看到,虽然Activity被重建,但是index的值以及保留了下来。


弊端与解决

虽然我们成功的保存了数据,但实际上是一种“治标不治本”的策略,每次都重新创建Activity,就算能通过临时保存,然后还原。但如果需要保存数据量很大怎么办?势必影响用户体验。

这时候我们可以通过AndroidManifest.xml中android:configChanges来解决这个问题。

它可以指定的当某个属性发生变化时,不去重启Activity,转换成通知程序去调用onConfigurationChanged()函数。

常见属性有:

  1. "keyboard'键盘发生了改变 例如用户用了外部的键盘
  2. "keyboardHidden"键盘的可用性发生了改变
  3. "orientation"屏幕方向改变了
  4. "screenSize"屏幕大小改变了

我们修改配置清单文件:

android:configChanges="screenSize|orientation"

并在代码中补上onConfigurationChanged方法

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        System.out.println("onConfigurationChanged被调用");
    }

再看执行效果:

我们还是启动,然后点三次button

旋转屏幕,可以看到onCreate并没有被调用,即Activity并没有被重新创建。

竖屏/横屏布局自定义

有的时候,竖屏切换成横屏,布局也需要进行对应的调整,

首先,在Src文件夹下创建一个目录layout-land,并创建对应的布局文件xml,直接复制一份原来的在基础上进行修改即可。

(系统会自动将这个文件夹作为横屏的布局,Android视图可能会显示不出来,可以切换到Project视图)

可以看到,直接复制原来的布局文件,系统自动的显示成横屏模式了,为了辨识,在button上加上一些提示文字。

运行

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云无心鸟知还

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值