GVKun编程网logo

Android应用程序窗口(Activity)窗口对象(Window)创建指南(android 窗口创建的流程)

23

在这篇文章中,我们将为您详细介绍Android应用程序窗口(Activity)窗口对象(Window)创建指南的内容,并且讨论关于android窗口创建的流程的相关问题。此外,我们还会涉及一些关于An

在这篇文章中,我们将为您详细介绍Android应用程序窗口(Activity)窗口对象(Window)创建指南的内容,并且讨论关于android 窗口创建的流程的相关问题。此外,我们还会涉及一些关于Android 1.6:“android.view.WindowManager$BadTokenException:无法添加窗口——令牌 null 不适用于应用程序”、android PopupWindow 和 Activity弹出窗口实现方式、android popupwindow跳转activity、Android styles.xml windowNoTitle(ActionBarActivity)的知识,以帮助您更全面地了解这个主题。

本文目录一览:

Android应用程序窗口(Activity)窗口对象(Window)创建指南(android 窗口创建的流程)

Android应用程序窗口(Activity)窗口对象(Window)创建指南(android 窗口创建的流程)

       在前文中,我们分析了Android应用程序窗口的运行上下文环境的创建过程。由此可知,每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一个具体的应用程序窗口。由此又可知,Activity只不过是一个高度抽象的UI组件,它的具体UI实现其实是由其它的一系列对象来实现的。在本文中,我们就将详细分析Android应用程序窗口对象的创建过程。

       从前面Android应用程序窗口(Activity)实现框架简要介绍和学习计划一文可以知道,在PHONE平台上,与Activity组件所关联的窗口对象的实际类型为PhoneWindow,后者是从Window类继承下来的。Activity、Window和PhonwWindow三个类的关系可以参考Android应用程序窗口(Activity)实现框架简要介绍和学习计划一文中的图3和图5。为了方便接下来描述类型为PhoneWindow的应用程序窗口的创建过程,我们将这两个图拿过来,如以下的图1和图2所示:


图1 Activity和Window的类关系图


图2 Window和PhoneWindow的类关系图

       上述两个图中所涉及到的类的描述可以参考Android应用程序窗口(Activity)实现框架简要介绍和学习计划一文,本文主要从Android应用程序窗口的创建过程来理解Activity、Window和PhonwWindow三个类的关系。

       从Android应用程序窗口(Activity)的运行上下文环境(Context)的创建过程分析一文又可以知道,与Activity组件所关联的一个PhoneWindow对象是从Activity类的成员函数attach中创建的,如图3所示:


图3 Android应用程序窗口的创建过程

       这个过程可以分为9个步骤,接下来我们就详细分析每一个步骤。

       Step 1. Activity.attach

复制代码 代码如下:

public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory,
Window.Callback,KeyEvent.Callback,
OnCreateContextMenuListener,ComponentCallbacks {
......

private Window mWindow;
......

final void attach(Context context,ActivityThread aThread,
Instrumentation instr,IBinder token,int ident,
Application application,Intent intent,ActivityInfo info,
CharSequence title,Activity parent,String id,
Object lastNonConfigurationInstance,
HashMap<String,Object> lastNonConfigurationChildInstances,
Configuration config) {
......

mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
if (info.softInputMode != WindowManager.LayoutParams.soFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
......

mWindow.setwindowManager(null,mToken,mComponent.flattenToString());
......

}

......
}

        这个函数定义在文件frameworks/base/core/java/android/app/Activity.java中。

        在前面Android应用程序窗口(Activity)的运行上下文环境(Context)的创建过程分析一文中,我们已经分析过这个函数的实现了,这里我们只关注与应用程序窗口创建相关的代码。

        函数首先调用PolicyManager类的静态成员函数makeNewWindow来创建一个类型为PhoneWindow的应用程序窗口,并且保存在Activity类的成员变量mWindow中。有了这个类型为PhoneWindow的应用程序窗口,函数接下来还会调用它的成员函数setCallback、setSoftInputMode和setwindowManager来设置窗口回调接口、软键盘输入区域的显示模式和本地窗口管理器。

        PhoneWindow类的成员函数setCallback、setSoftInputMode和setwindowManager都是从父类Window继承下来的,因此,接下来我们就继续分析PolicyManager类的静态成员函数makeNewWindow,以及Window类的成员函数setCallback、setSoftInputMode和setwindowManager的实现。

        Step 2. PolicyManager.makeNewWindow

复制代码 代码如下:

public final class PolicyManager {
private static final String POLICY_IMPL_CLASS_NAME =
"com.android.internal.policy.impl.Policy";

private static final IPolicy sPolicy;

static {
// Pull in the actual implementation of the policy at run-time
try {
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
POLICY_IMPL_CLASS_NAME + " Could not be loaded",ex);
} catch (InstantiationException ex) {
throw new RuntimeException(
POLICY_IMPL_CLASS_NAME + " Could not be instantiated",ex);
} catch (illegalaccessexception ex) {
throw new RuntimeException(
POLICY_IMPL_CLASS_NAME + " Could not be instantiated",ex);
}
}

......

// The static methods to spawn new policy-specific objects
public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context);
}

......
}

       这个函数定义在文件frameworks/base/core/java/com/android/internal/policy/PolicyManager.java中。

       PolicyManager是一个窗口管理策略类,它在第一次被使用的时候,就会创建一个Policy类实例,并且保存在静态成员变量sPolicy中,以后PolicyManager类的窗口管理策略就是通过这个Policy类实例来实现的,例如,PolicyManager类的静态成员函数makeNewWindow就是通过调用这个Policy类实例的成员函数makeNewWindow来创建一个具体的应用程序窗口的。

       接下来,我们就继续分析Policy类的成员函数makeNewWindow的实现。

       Step 3. Policy.makeNewWindow

复制代码 代码如下:

public class Policy implements IPolicy {
......

public PhoneWindow makeNewWindow(Context context) {
return new PhoneWindow(context);
}

......
}

        这个函数定义在文件frameworks/base/policy/src/com/android/internal/policy/impl/Policy.java中。

        Policy类的成员函数makeNewWindow的实现很简单,它只是创建了一个PhoneWindow对象,然后返回给调用者。

        接下来,我们就继续分析PhoneWindow类的构造函数的实现,以便可以了解一个类型为PhoneWindow的应用程序窗口的创建过程。

        Step 4. new PhoneWindow

复制代码 代码如下:

public class PhoneWindow extends Window implements MenuBuilder.Callback {
......

// This is the top-level view of the window,containing the window decor.
private DecorView mDecor;

// This is the view in which the window contents are placed. It is either
// mDecor itself,or a child of mDecor where the contents go.
private ViewGroup mContentParent;
......

private LayoutInflater mLayoutInflater;
......

public PhoneWindow(Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
}

......
}

       这个函数定义在文件frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中。

       PhoneWindow类的构造函数很简单,它首先调用父类Window的构造函数来执行一些初始化操作,接着再调用LayoutInflater的静态成员函数from创建一个LayoutInflater实例,并且保存在成员变量mLayoutInflater中。这样,PhoneWindow类以后就可以通过成员变量mLayoutInflater来创建应用程序窗口的视图,这个视图使用类型为DecorView的成员变量mDecor来描述。PhoneWindow类还有另外一个类型为ViewGroup的成员变量mContentParent,用来描述一个视图容器,这个容器存放的就是成员变量mDecor所描述的视图的内容,不过这个容器也有可能指向的是mDecor本身。在后面的文章中,我们再详细分析类型为PhoneWindow的应用程序窗口的视图的创建过程。

      Window的构造函数定义在文件frameworks/base/core/java/android/view/Window.java中,它的实现很简单,只是初始化了其成员变量mContext,如下所示:

复制代码 代码如下:

public abstract class Window {
......

private final Context mContext;
......

public Window(Context context) {
mContext = context;
}

......
}

       从前面的调用过程可以知道,参数context描述的是正在启动的Activity组件,将它保存在Window类的成员变量mContext之后,Window类就可以通过它来访问与Activity组件相关的资源了。

       这一步执行完成之后,回到前面的Step 1中,即Activity类的成员函数attach中,接下来就会继续调用前面所创建的PhoneWindow对象从父类Window继承下来的成员函数setCallback来设置窗口回调接口,因此,接下来我们就继续分析Window类的成员函数setCallback的实现。

       Step 5. Window.setCallback

复制代码 代码如下:
public abstract class Window {
......

private Callback mCallback;
......

/**
* Set the Callback interface for this window,used to intercept key
* events and other dynamic operations in the window.
*
* @param callback The desired Callback interface.
*/
public void setCallback(Callback callback) {
mCallback = callback;
}

......
}
        这个函数定义在文件frameworks/base/core/java/android/view/Window.java中。

        正在启动的Activity组件会将它所实现的一个Callback接口设置到与它所关联的一个PhoneWindow对象的父类Window的成员变量mCallback中去,这样当这个PhoneWindow对象接收到系统给它分发的IO输入事件,例如,键盘和触摸屏事件,转发给与它所关联的Activity组件处理,这一点可以参考前面Android应用程序键盘(Keyboard)消息处理机制分析一文。

        这一步执行完成之后,回到前面的Step 1中,即Activity类的成员函数attach中,接下来就会继续调用前面所创建的PhoneWindow对象从父类Window继承下来的成员函数setSoftInputMode来设置应用程序窗口的软键盘输入区域的显示模式,因此,接下来我们就继续分析Window类的成员函数setSoftInputMode的实现。

        Step 6. Window.setSoftInputMode

复制代码 代码如下:

public abstract class Window {
......

private boolean mHasSoftInputMode = false;
......

public void setSoftInputMode(int mode) {
final WindowManager.LayoutParams attrs = getAttributes();
if (mode != WindowManager.LayoutParams.soFT_INPUT_STATE_UNSPECIFIED) {
attrs.softInputMode = mode;
mHasSoftInputMode = true;
} else {
mHasSoftInputMode = false;
}
if (mCallback != null) {
mCallback.onWindowAttributesChanged(attrs);
}
}

......
}

       这个函数定义在文件frameworks/base/core/java/android/view/Window.java中。

       参数mode有SOFT_INPUT_STATE_UNSPECIFIED、SOFT_INPUT_STATE_UNCHANGED、SOFT_INPUT_STATE_HIDDEN、SOFT_INPUT_STATE_ALWAYS_HIDDEN、SOFT_INPUT_STATE_VISIBLE和SOFT_INPUT_STATE_ALWAYS_VISIBLE一共六个取值,用来描述窗口的软键盘输入区域的显示模式,它们的含义如下所示:

      1. SOFT_INPUT_STATE_UNSPECIFIED:没有指定软键盘输入区域的显示状态。

      2. SOFT_INPUT_STATE_UNCHANGED:不要改变软键盘输入区域的显示状态。

      3. SOFT_INPUT_STATE_HIDDEN:在合适的时候隐藏软键盘输入区域,例如,当用户导航到当前窗口时。

      4. SOFT_INPUT_STATE_ALWAYS_HIDDEN:当窗口获得焦点时,总是隐藏软键盘输入区域。

      5. SOFT_INPUT_STATE_VISIBLE:在合适的时候显示软键盘输入区域,例如,当用户导航到当前窗口时。

      6. SOFT_INPUT_STATE_ALWAYS_VISIBLE:当窗口获得焦点时,总是显示软键盘输入区域。

      当参数mode的值不等于SOFT_INPUT_STATE_UNSPECIFIED时,就表示当前窗口被指定软键盘输入区域的显示模式,这时候Window类的成员函数setSoftInputMode就会将成员变量mHasSoftInputMode的值设置为true,并且将这个显示模式保存在用来描述窗口布局属性的一个WindowManager.LayoutParams对象的成员变量softInputMode中,否则的话,就会将成员变量mHasSoftInputMode的值设置为false。

      设置完成窗口的软键盘输入区域的显示模式之后,如果Window类的成员变量mCallback指向了一个窗口回调接口,那么Window类的成员函数setSoftInputMode还会调用它的成员函数onWindowAttributesChanged来通知与窗口所关联的Activity组件,它的窗口布局属性发生了变化。

       这一步执行完成之后,回到前面的Step 1中,即Activity类的成员函数attach中,接下来就会继续调用前面所创建的PhoneWindow对象从父类Window继承下来的成员函数setwindowManager来设置应用程序窗口的本地窗口管理器,因此,接下来我们就继续分析Window类的成员函数setwindowManager的实现。

       Step 7. Window.setwindowManager

复制代码 代码如下:

public abstract class Window {
......

private WindowManager mWindowManager;
private IBinder mAppToken;
private String mAppName;
......

public void setwindowManager(WindowManager wm,
IBinder appToken,String appName) {
mAppToken = appToken;
mAppName = appName;
if (wm == null) {
wm = WindowManagerImpl.getDefault();
}
mWindowManager = new LocalWindowManager(wm);
}

......
}

       这个函数定义在文件frameworks/base/core/java/android/view/Window.java中。

       参数appToken用来描述当前正在处理的窗口是与哪一个Activity组件关联的,它是一个Binder代理对象,引用了在ActivityManagerService这一侧所创建的一个类型为ActivityRecord的Binder本地对象。从前面Android应用程序的Activity启动过程简要介绍和学习计划一系列文章可以知道,每一个启动起来了的Activity组件在ActivityManagerService这一侧,都有一个对应的ActivityRecord对象,用来描述该Activity组件的运行状态。这个Binder代理对象会被保存在Window类的成员变量mAppToken中,这样当前正在处理的窗口就可以知道与它所关联的Activity组件是什么。

       参数appName用来描述当前正在处理的窗口所关联的Activity组件的名称,这个名称会被保存在Window类的成员变量mAppName中。

       参数wm用来描述一个窗口管理器。从前面的调用过程可以知道, 这里传进来的参数wm的值等于null,因此,函数首先会调用WindowManagerImpl类的静态成员函数getDefault来获得一个默认的窗口管理器。有了这个窗口管理器之后,函数接着再使用它来创建一个本地窗口管理器,即一个LocalWindowManager对象,用来维护当前正在处理的应用程序窗口。

       接下来,我们首先分析WindowManagerImpl类的静态成员函数getDefault的实现,接着再分析本地窗口管理器的创建过程,即LocalWindowManager类的构造函数的实现。

       Step 8. WindowManagerImpl.getDefault

复制代码 代码如下:

public class WindowManagerImpl implements WindowManager {
......

public static WindowManagerImpl getDefault()
{
return mWindowManager;
}

......

private static WindowManagerImpl mWindowManager = new WindowManagerImpl();
}

       这个函数定义在文件frameworks/base/core/java/android/view/WindowManagerImpl.java中。

       WindowManagerImpl类的静态成员函数getDefault的实现很简单,它只是将静态成员变量mWindowManager所指向的一个WindowManagerImpl对象返回给调用者,这个WindowManagerImpl对象实现了WindowManager接口,因此,它就可以用来管理应用程序窗口。

      这一步执行完成之后,回到前面的Step 7中,即Window类的成员函数setwindowManager中,接下来就会使用前面所获得一个WindowManagerImpl对象来创建一个本地窗口管理器,即一个LocalWindowManager对象。

      Step 9. new LocalWindowManager

复制代码 代码如下:

public abstract class Window {
......

private final Context mContext;
......

private class LocalWindowManager implements WindowManager {
LocalWindowManager(WindowManager wm) {
mWindowManager = wm;
mDefaultdisplay = mContext.getResources().getDefaultdisplay(
mWindowManager.getDefaultdisplay());
}

......

private final WindowManager mWindowManager;

private final display mDefaultdisplay;
}

......
}

       这个函数定义在文件frameworks/base/core/java/android/view/Window.java中。

       LocalWindowManager类的构造函数首先将参数wm所描述的一个WindowManagerImpl对象保存它的成员变量mWindowManager中,这样以后就将窗口管理工作交给它来处理。

       LocalWindowManager类的构造函数接着又通过成员变量mWindowManager所描述的一个WindowManagerImpl对象的成员函数getDefaultdisplay来获得一个display对象,用来描述系统屏幕属性。

       由于前面所获得的display对象描述的是全局的屏幕属性,而当前正在处理的窗口可能配置了一些可自定义的屏幕属性,因此,LocalWindowManager类的构造函数需要进一步地调整前面所获得的display对象所描述的屏幕属性,以便可以适合当前正在处理的窗口使用。LocalWindowManager类的构造函数首先通过外部类Window的成员变量mContext的成员函数getResources来获得一个Resources对象,接着再调用这个Resources对象的成员函数getDefaultdisplay来调整前面所获得的display对象所描述的屏幕属性。最终调整完成的display对象就保存在LocalWindowManager类的成员变量mDefaultdisplay中。

       从前面的Step 4可以知道,类Window的成员变量mContext描述的是与当前窗口所关联的一个Activity组件。Activity类的成员函数getResources是从父类Contextwrapper继续下来的,它实现在文件frameworks/base/core/java/android/content/Contextwrapper.java中,如下所示:

复制代码 代码如下:

public class Contextwrapper extends Context {
Context mBase;
......

@Override
public Resources getResources()
{
return mBase.getResources();
}

......
}

       从前面Android应用程序窗口(Activity)的运行上下文环境(Context)的创建过程分析一文可以知道,Contextwrapper类的成员变量mBase指向的是一个ContextImpl对象,用来描述一个Activity组件的运行上下文环境。通过调用这个ContextImpl对象的成员函数getResources,就可以获得与一个Resources对象,而通过这个Resources对象,就可以访问一个Activity组件的资源信息,从而可以获得它所配置的屏幕属性。

       至此,我们就分析完成一个Activity组件所关联的应用程序窗口对象的创建过程了。从分析的过程可以知道:

      1. 一个Activity组件所关联的应用程序窗口对象的类型为PhoneWindow。

      2. 这个类型为PhoneWindow的应用程序窗口是通过一个类型为LocalWindowManager的本地窗口管理器来维护的。

      3. 这个类型为LocalWindowManager的本地窗口管理器又是通过一个类型为WindowManagerImpl的窗口管理器来维护应用程序窗口的。

      4. 这个类型为PhoneWindow的应用程序窗口内部有一个类型为DecorView的视图对象,这个视图对象才是真正用来描述一个Activity组件的UI的。

      在接下来的一篇文章中,我们将继续分析应用程序窗口内部的视图对象的创建过程,敬请关注!

Android 1.6:“android.view.WindowManager$BadTokenException:无法添加窗口——令牌 null 不适用于应用程序”

Android 1.6:“android.view.WindowManager$BadTokenException:无法添加窗口——令牌 null 不适用于应用程序”

我正在尝试打开一个对话框窗口,但每次我尝试打开它时都会引发此异常:

Uncaught handler: thread main exiting due to uncaught exceptionandroid.view.WindowManager$BadTokenException:      Unable to add window -- token null is not for an application  at android.view.ViewRoot.setView(ViewRoot.java:460)  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)  at android.app.Dialog.show(Dialog.java:238)  at android.app.Activity.showDialog(Activity.java:2413)

我通过showDialog使用显示器的 ID
调用来创建它。处理程序记录正常,onCreateDialog我可以毫无问题地逐步完成它,但我已经附加了它,因为我似乎遗漏了一些东西:

@Overridepublic Dialog onCreateDialog(int id){    Dialog dialog;    Context appContext = this.getApplicationContext();    switch(id)    {        case RENAME_DIALOG_ID:            Log.i("Edit", "Creating rename dialog...");            dialog = new Dialog(appContext);            dialog.setContentView(R.layout.rename);            dialog.setTitle("Rename " + noteName);            break;        default:            dialog = null;            break;    }    return dialog;      }

这有什么遗漏吗?一些问题谈到了在创建对话框时遇到此问题onCreate,这是因为尚未创建活动,但这是来自菜单对象的调用,并且该appContext变量似乎已正确填充在调试器中。

答案1

小编典典

而不是 : Context appContext = this.getApplicationContext();
您应该使用指向您所在活动的指针(可能this)。

我今天也被这个咬了,烦人的部分是getApplicationContext()来自 developer.android.com 的逐字记录 :(

android PopupWindow 和 Activity弹出窗口实现方式

本人小菜一个。目前只见过两种弹出框的实现方式,第一种是最常见的PopupWindow,第二种也就是Activity的方式是前几天才见识过。感觉很霸气哦。没想到,activity也可以做伪窗口。
先贴上最常见的方法,主要讲activity的方法。
一、弹出PopupWindow


复制代码 代码如下:

/**
* 弹出menu菜单
*/
public void menu_press(){
if(!menu_display){
//获取LayoutInflater实例
inflater = (LayoutInflater)this.getSystemService(LAYOUT_INFLATER_SERVICE);
//这里的main布局是在inflate中加入的哦,以前都是直接this.setContentView()的吧?呵呵
//该方法返回的是一个View的对象,是布局中的根
layout = inflater.inflate(R.layout.main_menu,null);
//下面我们要考虑了,我怎样将我的layout加入到PopupWindow中呢???很简单
menuWindow = new PopupWindow(layout,LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT); //后两个参数是width和height
//menuWindow.showAsDropDown(layout); //设置弹出效果
//menuWindow.showAsDropDown(null,layout.getHeight());
//设置如下四条信息,当点击其他区域使其隐藏,要在show之前配置
menuWindow.setFocusable(true);
menuWindow.setoutsidetouchable(true);
menuWindow.update();
menuWindow.setBackgroundDrawable(new BitmapDrawable());
mClose = (LinearLayout)layout.findViewById(R.id.menu_close);
menuWindow.showAtLocation(this.findViewById(R.id.schoolmain),Gravity.BottOM|Gravity.CENTER_HORIZONTAL,50); //设置layout在PopupWindow中显示的位置
//如何获取我们main中的控件呢?也很简单
mMainbtn = (LinearLayout)layout.findViewById(R.id.menu_main_btn);
mHistorybtn = (LinearLayout) layout.findViewById(R.id.menu_history_btn);
mHelpbtn = (LinearLayout) layout.findViewById(R.id.menu_help_btn);
//下面对每一个Layout进行单击事件的注册吧。。。
//比如单击某个MenuItem的时候,他的背景色改变
//事先准备好一些背景图片或者颜色
mMainbtn.setonClickListener (new View.OnClickListener() {
@Override
public void onClick(View arg0) {
mywebView.loadUrl(URL);
menuWindow.dismiss(); //响应点击事件之后关闭Menu
}
});
mHelpbtn.setonClickListener (new View.OnClickListener() {
@Override
public void onClick(View arg0) {
mywebView.loadUrl(URL);
menuWindow.dismiss(); //响应点击事件
}
});
mHistorybtn.setonClickListener (new View.OnClickListener() {
@Override
public void onClick(View arg0) {
mywebView.loadUrl(URL);
menuWindow.dismiss(); //响应点击事件
}
});
menu_display = true;
}else{
//如果当前已经为显示状态,则隐藏起来
menuWindow.dismiss();
menu_display = false;
}
}
public void back_press(){
if(menu_display){ //如果 Menu已经打开 ,先关闭Menu
menuWindow.dismiss();
menu_display = false;
}
else {
Intent intent = new Intent();
intent.setClass(MainActivity.this,Exit.class);
startActivity(intent);
}
}

这种方法很简单,要注意的是如果要想点击其他地方使其隐藏,要在show设置四条属性如下:
// 使其聚焦
mPopupWindow.setFocusable(true);
// 设置允许在外点击消失
mPopupWindow.setoutsidetouchable(true);
//刷新状态
mPopupWindow.update();
//点back键和其他地方使其消失,设置了这个才能触发Ondismisslistener ,设置其他控件变化等操作
mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
二、Activity做伪弹窗

 

本人感觉这个很先进啊。恕我冒犯,我只这里直接写上牛人的代码。此牛人写的是防微信的demo。做的相当好,我在后面附上CSDN免费下载链接。
先贴上java代码――Exit.java
package cn.buaa.myweixin;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.Toast;
public class Exit extends Activity {
private LinearLayout layout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.exit_dialog);
layout=(LinearLayout)findViewById(R.id.exit_layout);
layout.setonClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Todo Auto-generated method stub
Toast.makeText(getApplicationContext(),"提示:点击窗口外部关闭窗口!",
Toast.LENGTH_SHORT).show();
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event){
finish();
return true;
}
public void exitbutton1(View v) {
this.finish();
}
public void exitbutton0(View v) {
this.finish();
MainWeixin.instance.finish();//关闭Main 这个Activity
}
}
附上布局文件:exit_dialog.xml
复制代码 代码如下:

View Code
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/exit_layout"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:background="@drawable/confirm_dialog_bg2" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:padding="5dp"
android:textColor="#333"
android:textSize="20sp"
android:text="退出微信" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#333"
android:layout_marginTop="1dp"
android:padding="10dp"
android:textSize="16sp"
android:gravity="center_horizontal"
android:text="退出后,你将收不到新的消\n息.确定要退出?" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="33dp"
android:layout_marginBottom="8dp"
>
<Button
android:id="@+id/exitBtn0"
android:layout_width="110dp"
android:layout_height="wrap_content"
android:text="是"
android:textSize="16sp"
android:textColor="#fff"
android:background="@drawable/btn_style_green"
android:gravity="center"
android:onClick="exitbutton0"
/>
<Button
android:id="@+id/exitBtn1"
android:layout_width="110dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="否"
android:textSize="16sp"
android:textColor="#333"
android:background="@drawable/btn_style_white"
android:gravity="center"
android:onClick="exitbutton1"
/>
</LinearLayout>
</LinearLayout>

分析,弹出exit这个框很简单,本身就是activity,在主界面用startavtivity等方法像普通activity启动。
关键是如何做到点击其他地方退出和如何关闭程序。
、点击其他地方退出,只要监听OnClickListener让所有的点击都退出就行了(除了xml中指定按钮事件之外)。
、退出主程序。只要在出程序中将主程序自己设置成静态对象,在外部调用即可 public static MainWeixin instance=null;
上面的布局和activity并不能将activity的窗体展现在主界面之上,看起来像个弹出框。下面是弹出框的styles配置:
复制代码 代码如下:

<style name="MyDialogStyle">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<item name="android:backgroundDimEnabled">true</item>
</style>

下面我们来分析一下这个布局的含义及重点:
重点1、<item name="android:windowBackground">@android:color/transparent</item>窗口背景色
重点2、<item name="android:windowFrame">@null</item>Dialog的windowFrame框为无
重点4、<item name="android:windowIsFloating">true</item>是否浮现在activity之上
重点5、<item name="android:windowIsTranslucent">true</item>窗口是否半透明――是(与第一条配合使用)
重点6、<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>窗口弹出效果
重点7、<item name="android:backgroundDimEnabled">true</item> 是否允许背景模糊
重点8、<item name="android:windowContentOverlay">@null</item>这个不设置的话,可能会出现边框黑线
以上代码都是牛人们的功劳,我拿来做一分析,给更多需要的朋友。
我在众多牛人的指引下一步步成长,感谢牛人们。

android popupwindow跳转activity

android popupwindow跳转activity

view.getContext().startActivity(i);

Android styles.xml windowNoTitle(ActionBarActivity)

Android styles.xml windowNoTitle(ActionBarActivity)

我想在我的应用程序中隐藏标题栏(显示活动磁贴的位置).我这样做是通过将 android:windowNoTitle项设置为true.这适用于API级别为19的设备.我使用运行API级别10的设备对其进行了测试,它只隐藏了通知栏.瓷砖栏仍然显示.

这是我的res / values / styles.xml

<resources>
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowFullscreen">true</item>
    </style>

</resources>

编辑:我在我的清单中使用AppBaseTheme作为主题.任何其他value-vXX文件夹中没有其他styles.xml文件.

编辑#2:我正在为我的活动扩展ActionBaractivity.

解决方法

我为所有设备使用了1个主题,它在API级别8到16上完美运行(因为我只有5个物理设备).我确信它也在17-19设备上工作.

确保在你的清单文件中(在应用程序部分),有一行像android:theme =“@ style / AppTheme”

尝试将此用作主题:

<style
    name="AppBaseTheme"
    parent="android:style/Theme.NoTitleBar.Fullscreen"
    >
    <item name="android:windowNoTitle">true</item>

    ...

</style>

并删除values-xy文件夹中的样式/主题

[编辑]

由于AppCompat主题不是全屏,因此根据定义,StatusBar将会消失,而不是TitleBar

如果您不需要AppCompat提供的ActionBar,那么您应该尽快摆脱AppCompat:不要使用不需要的和不需要的东西来破坏您的应用程序

例如,我有一个Header Bar和一个Footer Bar,但这些只是我实现自己的RelativeLayouts.并且仍然可以自由地使用整个屏幕表面.

关于Android应用程序窗口(Activity)窗口对象(Window)创建指南android 窗口创建的流程的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于Android 1.6:“android.view.WindowManager$BadTokenException:无法添加窗口——令牌 null 不适用于应用程序”、android PopupWindow 和 Activity弹出窗口实现方式、android popupwindow跳转activity、Android styles.xml windowNoTitle(ActionBarActivity)等相关内容,可以在本站寻找。

本文标签: