android启动页面

1.使用Activity的方式,

缺点:沉重,容易造成动画捕捉间隙,当然可以特殊处理了,

但是它还有个最致命的缺陷.由于国内部分APP越来越流氓,6.0之下的Android一直受到无限后台重启的困扰,所以当手机内存不足,遇上GC的时候,你就会发现,你退出了启动页Activity,但是,却并未进入主页面,又或者用户会看当很长时间的App黑屏或者上一个APP的界面,又甚至在某些处理不当的App上,主页面首先运行,而当用户退出之后,启动页依然存在,又在去启动主页面,更甚者可能造成手机重启,(这个问题是无法避免的,尽管你设置了透明主题也无用),现在普遍国内的APP都采用这种启动页模式,总体而言,以我使用的经验而言内存不足必出黑屏.

优点:出Bug也不至于搞死APP,相对来说比较安全

推荐用于快速开发的APP,因为一般这类APP,没有那么多的时间,不要求很细心的设计

2.使用WindowManager,

优点:能够在Application环境启动(WindowManager.Toast),中等轻量,(但是,如果启动也需要与用户交互,需要版本匹配)

缺点:双页面(有时候这也会成为其优点)

推荐适合于小区域,高版本API标准的APP.

3.使用ViewRootImpl,也就是传说中的根View,(findView(android.R.id.content).getRootView)

优点:极其轻量,不会造成双页面(一体化视觉效果),也不会GC黑屏,并且你可以在每个Activity启动时插入启动页,而不必担心,GC黑屏的风险

缺点,容易触发hwui(硬件加速)中的BUG,会导致本地泄漏(可能是我测试机为4.4.2版本对硬件加速支持不是很好的原因),为什么说可能呢,这家伙就像是个孩子,一点代码让它不爽,就会搞死你APP并且不会出现Log信息,很操蛋.我发现一个.就是你在使用该启动页的时候,底层的View,也就是被它覆盖的视图,通常是我们通过Activity.setContentView的那个视图,绝对不能进行大量的绘制工作,也就是说,绝对不能不断的postInvaild(10)等,如果你有特效在哪里,必须要在remove了该启动页的View之后再来进行Post,否则,很操蛋.这东西绝对在不确定的时间直接搞死你的App

推荐用于重视软件设计与交互的App


4.自己定义顶层ContentView,自己搞定,


其实以上四种,最好用的还是第三种,但是,对你的代码水平要求很高


下面仅仅介绍第二种方式>

	private void initLaunchPage() {
		LaunchPage page = onNewLaunchPage();
		if (page != null) {
			ViewGroup root = getRootParent();
			if (root == null) {
				Log.e(TAG, "parent no found !");
				return;
			}
			View view = page.onPageCreate(this);
			if (view != null) {
				if (page.hasFullScreen()) {
					if (VERSION.SDK_INT >= 16) {
						mLauchViewFlag = View.SYSTEM_UI_FLAG_FULLSCREEN;
					}
					mLauchViewFlag |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
					mLauchWindowFlags = WindowManager.LayoutParams.FLAG_FULLSCREEN
							| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
							| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
					view.setSystemUiVisibility(mLauchViewFlag);
				}

				WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
				if (wm == null) {
					throw new NullPointerException("WindowManager Null !");
				}
				LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,LayoutParams.APPLICATION, mLauchWindowFlags, android.graphics.PixelFormat.RGBA_8888);
				if (page.getAnimationId() > 0) {
					params.windowAnimations = page.getAnimationId();
				}
				wm.addView(view, params);
				mLaunchView = view;
			}
		}
	}


Node>这篇文章修改了挺多,我也是为了证明这种启动页的可用性,

- 在Application环境下的该类型启动页.必须使用Toast类型,因为我们的Application Root Window 在调用Applcaition OnCreate 时并没有创建,所以我们不能使用任何Applcaition级别的类型,说实话,在Application环境下使用Toast窗体,启动速度要比Activity环境下快的多,

_在Activity环境下,可以设置Application类型,你可以在呼叫super.OnCreate的时候,初始化起始页.类似这样

@Override
protected final void onCreate(Bundle savedInstanceState) {
startLaunchPage();

setContentView(R.id.content);

super.onCreate(savedInstanceState);

}

public class PageLauncher {

	private int mLauchViewFlag;

	private LaunchPager mLaunchPage;
	private View mLaunchView;
	private Context mContext;

	public PageLauncher(Context context, LaunchPager mPager) {
		if (context == null) {
			throw new NullPointerException("Context Can Not Null !");
		}
		if (mPager == null) {
			throw new NullPointerException("LaunchPager Can Not Null !");
		}
		mContext = context;
		mLaunchPage = mPager;
	}

	public static LaunchPager reloveLaunchPager(Context context) {
		try {
			Bundle bundle = null;
			if (context instanceof Application) {
				ApplicationInfo info = context.getPackageManager().getApplicationInfo(context.getPackageName(),
						PackageManager.GET_META_DATA);
				bundle = info.metaData;
			} else if (context instanceof Activity) {
				ActivityInfo info = context.getPackageManager().getActivityInfo(((Activity) context).getComponentName(),
						PackageManager.GET_META_DATA);
				bundle = info.metaData;
			} else if (context instanceof Service) {
				ComponentName mName = new ComponentName(context, context.getClass());
				ServiceInfo info = context.getPackageManager().getServiceInfo(mName, PackageManager.GET_META_DATA);
				bundle = info.metaData;
			}
			if (bundle != null) {
				Object obj = bundle.get(LaunchPager.METE_NAME);
				if (obj instanceof String) {
					try {
						return ((Class<LaunchPager>) context.getClassLoader().loadClass((String) obj)).newInstance();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static PageLauncher relovePageLauncher(Context context) {
		LaunchPager mLaunchPager = reloveLaunchPager(context);
		if (mLaunchPager != null) {
			return new PageLauncher(context, mLaunchPager);
		}
		return null;
	}

	public static PageLauncher relovePageLauncher(Context context, LaunchPager pager) {
		try {
			if (pager != null) {
				return new PageLauncher(context, pager);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		LaunchPager mLaunchPager = reloveLaunchPager(context);
		if (mLaunchPager != null) {
			return new PageLauncher(context, mLaunchPager);
		}
		return null;
	}

	public static PageLauncher relovePageLauncherCreate(Context context, LaunchPager pager) {
		PageLauncher launcher = null;
		try {
			if (pager != null) {
				launcher = new PageLauncher(context, pager);
				launcher.startLaunchPage();
				return launcher;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		LaunchPager mLaunchPager = reloveLaunchPager(context);
		if (mLaunchPager != null) {
			launcher = new PageLauncher(context, mLaunchPager);
			launcher.startLaunchPage();
		}
		return launcher;
	}

	public synchronized void startLaunchPage() {
		LaunchPager page = mLaunchPage;
		if (page != null && mLaunchView == null) {
			View view = page.onPageCreate(mContext);
			if (view != null) {
				int mLauchWindowFlags = 0;
				if (page.hasFullScreen()) {
					if (VERSION.SDK_INT >= 16) {
						mLauchViewFlag = View.SYSTEM_UI_FLAG_FULLSCREEN;
					}
					if (VERSION.SDK_INT >= 14) {
						mLauchViewFlag |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
					}
					mLauchWindowFlags = WindowManager.LayoutParams.FLAG_FULLSCREEN
							| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
							| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
					try {
						view.setSystemUiVisibility(mLauchViewFlag);
					} catch (Throwable t) {
						t.printStackTrace();
					}
				}

				WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
				if (wm == null) {
					throw new NullPointerException("WindowManager Null !");
				}
                                
  				int type = LayoutParams.LAST_APPLICATION_WINDOW;
				//如果是Applcation环境,你必须处理用户的按键状态,否则Toast将遮掩其他应用窗体
				if (mContext instanceof Application) {
					type = LayoutParams.TYPE_TOAST;
				}
				LayoutParams params = new LayoutParams(WindowManager.LayoutParams.MATCH_PARENT,
						WindowManager.LayoutParams.MATCH_PARENT, type, mLauchWindowFlags,
						android.graphics.PixelFormat.RGBA_8888);
				if (page.getAnimationId() > 0) {
					params.windowAnimations = page.getAnimationId();
				}
				try {
					wm.addView(view, params);
				} catch (Exception e) {
					e.printStackTrace();
				}
				mLaunchView = view;
			}
		}
	}

	public synchronized void removeLaunchPage() {
		if (mLaunchView == null) {
			return;
		}
		if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
			if (mLaunchView != null) {
				WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
				if (wm == null) {
					throw new NullPointerException("WindowManager Null !");
				}
				mLaunchPage.onPageDestory(mContext);
				if (mLauchViewFlag > 0) {
					mLaunchView.setSystemUiVisibility(0);
				}
				wm.removeViewImmediate(mLaunchView);
				mLaunchView = null;
			}
		} else {
			mLaunchView.post(new Runnable() {

				@Override
				public void run() {
					removeLaunchPage();
				}
			});
		}
	}
}


	public interface LaunchPager {
<span style="white-space:pre">		</span>public static final String PAGELAUNCHER = "Page_Launcher";
		public static final String METE_NAME = "LaunchPager";
//可以加入onPageStart onPageResume 等方法
		View onPageCreate(Context acter);

		View onPageDestory(Context acter);

		boolean hasFullScreen();

		int getAnimationId();
	}


	private void initLaunchPage() {
		if (mPageLauncher == null) {
			mPageLauncher = PageLauncher.relovePageLauncherCreate(this, onNewLaunchPage());
		}
	}
	@Override
	public Object getSystemService(String name) {
		if (ConfigPreferences.CONFIGPREFERENCE.equals(name)) {
			return mConfigPreferences;
		} else if (LaunchPager.PAGELAUNCHER.equals(name)) {
			return mPageLauncher;
		}
		return super.getSystemService(name);
	}

	protected LaunchPager onNewLaunchPage() {
		return null;
	}


我修改了代码只需要在Application或者Activity中引用就可以,不过我建议在Activity或者Application中的Manifest中配置相关的LaunchPager类,并且完全可以在重写getSystenService(String name)方法,通过该方法获取上级的PageLauncher对象,这样配置的优点我感觉要比使用Activity具有更多的可扩展性,因为使用Activity总而言之太重


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Studio中创建启动界面有多种方法,以下是其中两种常用的方法: 1. 使用ImageView显示启动界面图片: 在res目录下创建文件夹drawable-hdpi,并将启动界面图片放入该文件夹中。然后在启动界面的布局文件中使用ImageView来显示该图片。例如,创建一个名为activity_splash.xml的布局文件,内容如下: ```xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/splash_image" android:scaleType="centerCrop" /> </RelativeLayout> ``` 其中,@drawable/splash_image是启动界面图片的资源ID。 2. 使用Theme设置启动界面样式: 在res/values/styles.xml文件中定义一个启动界面的主题样式,例如: ```xml <style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@drawable/splash_image</item> </style> ``` 其中,@drawable/splash_image是启动界面图片的资源ID。 然后,在AndroidManifest.xml文件中将启动界面的主题样式应用到启动的Activity上,例如: ```xml <activity android:name=".SplashActivity" android:theme="@style/SplashTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> ``` 其中,SplashActivity是启动界面的Activity类名。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值