今天主要做的是启动页的再一次优化,昨天的效果在启动时会有一个白屏的效果出来,这并不我预想的
今天已经解决了这个问题,并且再闪屏后加了一个可以手动跳过的倒计时动画。
我们正常开发中会在Activity的onCreate()方法中调用setContentView(View)设置该Activity的显示布局,那么问题就来了,既然我们设置了布局,为什么启动的时候还会白屏或者黑屏而不是显示我set的布局呢?下面就带领大家一起来剖析一下原因。当打开一个Activity时,如果这个Activity所属Application还没有在运行,系统会为这个Activity的创建一个进程(每开启一个进程都会有一个Application,所以Application的onCreate()可能会被调用多次),但进程的创建与初始化都需要时间,在这个动作完成之前,如果初始化的时间过长,屏幕上可能没有任何动静,用户会以为没有点到按钮。所以既不能停在原来的地方又没到显示新的界面,怎么办呢?这就有了StartingWindow(也称之为PreviewWindow)的出现,这样看起来就像Activity已经启动起来了,只是数据内容还没有初始化好。StartingWindow一般出现在应用程序进程创建并初始化成功前,所以它是个临时窗口,对应的WindowType是TYPE_APPLICATION_STARTING。目的是告诉用户,系统已经接受到操作,正在响应,在程序初始化完成后实现目的UI,同时移除这个窗口。这个StartingWindow就是我们要讨论的白屏和黑屏的“元凶”,一般情况下我们会对Application和Activity设置Theme,系统会根据设置的Theme初始化StartingWindow。Window布局的顶层是DecorView,StartingWindow显示一个空DecorView,但是会给这个DecorView应用这个Activity指定的Theme,如果这个Activity没有指定Theme就用Application的(Application系统要求必须设置Theme)。在Theme中可以指定窗口的背景,Activity的ICON,APP整体文字颜色等,如果说没有指定任何属性,就会用默认的属性,也就是上文中提到的空DecorView,所以我们的白屏和黑屏和空DecorView息息相关,我们给APP设置的Style就决定了是白屏还是黑屏。
解决方法,在上一篇冲刺的博客中闪屏动画用的是在一个setContentView(View)来实现的,虽然这不是主要原因,但为保证启动速度,不要调用setContentView()方法。因为Activity设置了layout,它在App完全初始化完成后才会显示,也会耗时。看到上面的解释,我们得知theme的设置才是这个白屏的原因,所以要改进这个问题要在theme上动手。
setContentView(R.layout.activity_splash);
一、修改上次的bug
现在的项目文件目录,箭头是改动的地方,话不多说上步骤
1.drawable下面放一张图片,作为开头的闪屏
2.values下面的styles定义一个新的theme背景为设置的闪屏图片 >>>> SplashActivityTheme
3.修改AndroidManifest.xml,把闪屏StartPageActivity作为初始界面
<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"> </activity> <activity android:name=".StartPageActivity" android:theme="@style/SplashActivityTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
可以看到这个里面用的theme就是刚刚定义的
4.StartPageActivity
import com.example.qidongdemo2.R; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.widget.ImageView; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.WindowManager; import androidx.appcompat.app.AppCompatActivity; public class StartPageActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏 super.onCreate(savedInstanceState); Thread myThread = new Thread() {//创建子线程 @Override public void run() { try { sleep(5000);//使程序休眠一秒 Intent it = new Intent(getApplicationContext(), MainActivity.class); startActivity(it); finish();//关闭当前活动 } catch (Exception e) { e.printStackTrace(); } } }; myThread.start();//启动线程 } }
二、可跳过的倒计时动画
1.修改AndroidManifest.xml,注册一个新的activity InitAdvActivity
<activity android:name=".InitAdvActivity"/>
2.修改之前的闪屏activity使闪屏后页面跳转到新建的activity
Intent it=new Intent(getApplicationContext(),InitAdvActivity.class);//启动InitAdvActivity
3.新建activity InitAdvActivity
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import java.util.Random;
public class InitAdvActivity extends BaseActivity {
private int[] picsLayout = {R.layout.layout_hello, R.layout.layout_hello2,
R.layout.layout_hello3, R.layout.layout_hello4, R.layout.layout_hello5};
private int i;
private int count = 5;
private Button mBtnSkip;
@SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (msg.what == 0) {
mBtnSkip.setText("跳过 (" + getCount() + ")");
handler.sendEmptyMessageDelayed(0, 1000);
}
}
};
private LinearLayout linearLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Random r = new Random();
i = r.nextInt(5);
Log.i("test", "随机数是:" + i);
if (i < 5) {
//随机概率会出现广告页
setContentView(R.layout.activity_adv);
initView2();
} else {
startActivity(new Intent(InitAdvActivity.this, MainActivity.class));
finish();
}
}
private void initView2() {
linearLayout = findViewById(R.id.advLine);
View view = View.inflate(InitAdvActivity.this, picsLayout[i], null);
linearLayout.addView(view);
mBtnSkip = view.findViewById(R.id.btn_skip);
mBtnSkip.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(InitAdvActivity.this, MainActivity.class));
handler.removeMessages(0);
finish();
}
});
handler.sendEmptyMessageDelayed(0, 1000);
}
public int getCount() {
count--;
if (count == 0) {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
}
return count;
}
}
4.新建BaseActivity
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.Nullable;
import android.view.WindowManager;
public class BaseActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTranslucent(this);
}
public static void setTranslucent(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 设置状态栏透明
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
}
注:学习了别人的代码 地址:https://www.jianshu.com/p/96f0b9a971ac