当前位置:首页 » 安卓系统 » android窗体

android窗体

发布时间: 2023-03-16 01:05:38

⑴ Android四大组件 —— Activity(窗口)

Activity是一个 界面 的载体,可以把它与html页面进行类比,html页面由各种各样的标签组成,而Activity则可以由 各种控件 组成。

Activity的掌握重点主要在于:

     a.Activity的生命周期 

     b.Activity的启动模式

              onCreate() : 

            当Activity第一次被创建的时候调用此方法.一般在此方法中 进行控件的声明,添加事件等初始化工作 .

            onStart():

            当Activity被显示到屏幕上的时候调用此方法,执行完此方法后 界面可见

            onResume():

            当此Activity能够被操作之前,也就是能够获得用户的焦点之前调用此方法.

            onRestart():

            当Activity被停止后又被再次启动之前调用此方法.接着将调用onStart()方法.

            onPause():

            当第一个Activity通过Intent启动第二个Activity的时候,将调用第一个Activity的onPause()方法.然后调用第二个Activity的onCreate(),onStart(),onResume()方法,接着调用第一个Activity的onStop()方法.如果Activity重新获得焦点,则将调用onResume()方法;如果此Activity进入用户不可见状态,那么将调用onStop()方法.

            onStop():

            当第一个Activity被第二个Activity完全覆盖,或者被销毁的时候回调用此方法.如果此Activity还会与用户进行交互,将调用onRestart方法();如果此Activity将被销毁,那么将调用onDestroy()方法.

            注意:

              a.home键返回,锁屏,关闭界面肯定会调用onStop方法

              b.但是开启另一个Activity并不一定会调用onStop方法

            onDestroy():

               Activity被销毁之前调用此方法.或者是调用finish()方法结束Activity的时候调用此方法.可以在此方法中进行收尾工作,比如释放资源等.

             Active/Runing 一个新 Activity 启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态。

             Paused  当 Activity 被另一个透明或者 Dialog 样式的 Activity 覆盖时的状态。此时它依然与窗口管理器保持连接,系统继续维护其内部状态,所以它仍然可见,但它已经失去了焦点故不可与用户交互。

             Stoped  当 Activity 被另外一个 Activity 覆盖、失去焦点并不可见时处于  Stop ed 状态。

             Killed  Activity 被系统杀死回收或者没有被启动时处于  Killed 状态。

            在 manifest 文件中声明 activity 时,利用activity元素的 launchMode 属性来设定 activity 与 task 的关系。

launchMode 属性 指明了 activity 启动 task 的方式,默认 standard方式

             standard(默认模式):

          系统在启动 activity 的 task 中创建一个新的 activity 实例,并把 intent 传送路径指向它。 该 activity 可以被实例化多次,各个实例可以属于不同的 task,一个 task 中也可以存在多个实例。

             singleTop:

           如果 activity 已经存在一个实例并位于当前 task 的 栈顶 ,则系统会调用已有实例的 onNewIntent() 方法把 intent 传递给已有实例,而不是创建一个新的 activity 实例。activity 可以被实例化多次,各个实例可以属于不同的 task,一个 task 中可以存在多个实例(但仅当 back stack 顶的 activity 实例不是该 activity 的)。

               singleTask:

            系统将创建一个新的 task,并把 activity 实例 作为根 放入其中。但是,如果 activity 已经在其它 task 中存在实例,则系统会通过调用其实例的onNewIntent() 方法把 intent 传给已有实例,而不是再创建一个新实例。 此 activity 同一时刻只能存在一个实例。

            例如:可以用于关闭所有Activity或重新登录等

             singleInstance:

            除了系统不会把其它 activity 放入当前实例所在的 task 之外,其它均与"singleTask"相同。activity 总是它所在 task 的唯一成员;它所启动的任何 activity 都会放入其它 task 中

            主要是startActivity(intent),或者带值返回startActivityForResult(intent) , Activity的跳转方式  。

⑵ 如何在Android中打开一个窗口

1、 首先在默认工程中新建一个Activity

2、添加动作属性
在activity_main.xml文件中添加动作动作属性
android:onClick="OpenNewWindow"

OpenNewWindow是自己取的名字
3、添加动作函数
在MainActivity.java文件中添加:
import android.view.View;
然后在添加:
public void OpenNewWindow(View view){
//打开一个新的窗口

Intent intent = new Intent(this,MainActivity2.class);
startActivity(intent);
Toast.makeText(this, "Toast", Toast.LENGTH_SHORT).show();
}
其中:
Intent intent = new Intent(this,MainActivity2.class);
是定义一个意图,MainActivity2.class是要打开的窗口
startActivity(intent);
是激活这个意图
Toast.makeText(this, "Toast", Toast.LENGTH_SHORT).show();
作为调试的时候看的,可以删除,作用是在屏幕是显示有没有启动这个动作。

请注意,为了让系统能够将这个方法与在android:onClick属性中提供的方法名字匹配,它们的名字必须一致,特别是,这个方法必须满足以下条件:
公共的
没有返回值
有一个唯一的视图(View)参数

使用上述方法添加Activity,在调试的时候需要用Andriod4,在此说明另外一种添加Activity的方法。
双击Manifest.xml文件,选中Application选项卡,向下拉,找到Application Nodes,点击添加,跳出以下对话框:

选择Activity选项,点击OK。
然后选中新建的Activity,点击右边Name,在弹出的对话框中填入名字就可以了。然后,添加xml文件,名字任意取,当然,最好是同名文件,以后好找,填写相应文档既可。
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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity3" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/AText1" />

</RelativeLayout>
其中RelativeLayout说明是相对布局。

⑶ 如何实现android中监听来电并生成悬浮窗体提示

android.permission.READ_PHONE_STATE"权限
Xml代码
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

还需要注册来电监听,目前我的处理方式是接收开机广播,然后在接收到广播后注册来电监听。接收开机广播需要有“android.permission.RECEIVE_BOOT_COMPLETED”权限,manifest中申明如下
Java代码
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

然后注册广播接收类

Xml代码
<receiver android:name=".PhoneBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
PhoneBootReceiver中注册监听来电,首先得获取系统服务“TELEPHONY_SERVICE”

Java代码
TelephonyManager telM = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
然后添加监听

Java代码
telM.listen(new TelListener(context), PhoneStateListener.LISTEN_CALL_STATE);
TelListener是自己定义的电话状态监听类,继承自PhoneStateListener,监听来电只需要实现onCallStateChanged(int

state, String incomingNumber)方法。
咳咳...标题上说了弹出悬浮窗口,其实悬浮窗口就是在WindowManager中添加一个View,这个功能我也是在TelListener实现的。要想实现悬浮窗口,首先得有“android.permission.SYSTEM_ALERT_WINDOW”的权限,在manifest中申明如下:
Xml代码
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
WindowManager需要通过context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
来获取。
先把TelListener源码放出来,再详解
Xml代码
public class TelListener extends PhoneStateListener {
private Context context;

private WindowManager wm;
private TextView tv;
public TelListener(Context context){
this.context = context;
}
@Override
public void onCallStateChanged(int state, String incomingNumber) {
// TODO Auto-generated method stub
super.onCallStateChanged(state, incomingNumber);
if(state == TelephonyManager.CALL_STATE_RINGING){
wm = (WindowManager)context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
<span style="white-space: pre;"> </span>params.format = PixelFormat.RGBA_8888;
tv = new TextView(context);
tv.setText("这是悬浮窗口,来电号码:" + incomingNumber);
wm.addView(tv, params);

}else if(state == TelephonyManager.CALL_STATE_IDLE){
if(wm != null){
wm.removeView(tv);
}
}
}
}
state

= TelephonyManager.CALL_STATE_RINGING表示有新的来电,state =
TelephonyManager.CALL_STATE_IDLE表示电话中断(可能理解不是很准确,电话挂断的时候state会和TelephonyManager.CALL_STATE_IDLE相等)
定义窗口布局

Java代码
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
设置窗口类型在所有窗口之上
Java代码
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
别忘了
Java代码
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
如果没有这句话的话,在生成悬浮窗口后,悬浮窗口后的界面上东西都不能点。这句话的目的是让悬浮窗口失去焦点。
背景透明
Java代码
params.format = PixelFormat.RGBA_8888;
本例中悬浮窗口只是显示一个TextView其内容为“这是悬浮窗口,来电号码:xxxxxx”,最后将TextView添加到窗体中
Java代码
wm.addView(tv, params);
在电话中断后将TextView移除,否则会一直显示的...
Java代码
wm.removeView(tv);
啦..本文就到这儿了...
“啥?要可移动的?”
要想可以拖动的话,那给TextView添加setOnTouchListener,实现OnTouchListener的onTouchListener方法。
Java代码
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
修改为
Java代码
params.type = WindowManager.LayoutParams.TYPE_PHONE;
因为TYPE_SYSTEM_OVERLAY的话是TextView获取不到输入焦点,也就没法拖动了哈。

⑷ Android 重学系列 WMS在Activity启动中的职责 计算窗体的大小(四)

通过启动窗口为例子,大致上明白了WMS是如何添加,更新,移除窗口的工作原理。本文将会重点聊一聊窗口的大小计算逻辑。

下面的源码都是来自Android 9.0

计算窗口的大小和Android 4.4相比变化很大。花了一点心思去重新学习了。在Android 4.4中,窗体的计算在onResume中调用了ViewRootImpl调用relayoutWindow对整个Window重新测量窗口大小以及边距。

relayoutWindow这个方法是做什么的呢?当我们在Activity的生命周期到达了onResume的阶段,此时ViewRootImpl的setView,开始走渲染的View的流程,并且调用requestLayout开始测量渲染。其中有一个核心的逻辑就是调用WMS的relayoutWindow,重新测量Window。

在Android 9.0中把这个流程和DisplayContent绑定起来。让我们稍微解剖一下这个方法。

relayout大致上要做了以下的事情:

relayout的方法有点长,本次我们将关注这一部分核心的逻辑。分别是两个方法:

能看到在这里面对performSurfacePlacementLoop做最多为6次的循环,这六次循环做什么呢?

能看到这里面的核心逻辑,首先会检查WMS下mForceRemoves集合中是否还有对象。有则调用removeImmediately清空WindowState的中SurfaceControl和WindowContainer之间的绑定和Surface对象,以及销毁WindowAnimator中的Surface。

做这个得到目的很简单,因为下一个步骤将会申请一个Surface对象,而此时如果Android系统内存过大了(OOM),mForceRemoves就存在对象,就可以销毁不需要的Surface。这一点的设计和Davlik虚拟机申请对象时候的思路倒是一致的。

销毁需要一点时间,因此就需要做一个250毫秒的的等待。接着会调用RootWindowContainer的performSurfacePlacement做真正的执行。最后会通过handler通过ViewServer通知事件给DebugBridge调试类中。

每一次loop的最后,如果发现RootWindowContainer需要重新测量皮空,就会把当前这个方法,放入Handler中,等待下次的调用,也是调用6次。这样就能最大限度的保证在这段时间内Window能够测量每一次的窗体参数。

下面这个方法十分长,我们只看核心;

我在上面划分了9个部分:

这里只给总览,之后有机会再进去里面抓细节。

我们能够看到无论是在哪里,如果窗口发生了变化,都会调用updateFocusedWindowLocked方法。实际上这个方法才是真正的核心测量窗口大小逻辑。

这里注意一下isWindowChange是判断输入法焦点是否一致,而窗体焦点则是通过不同的WindowState来判断。

实际上核心测量的真正动作是DisplayContent.performLayout。我们仔细一想也就知道,在Android 9.0的时候,DisplayContent象征着逻辑屏幕,我们讨论无分屏的情况,实际上就是指我们当前窗体铺满逻辑显示屏各个边距的大小。

在正式开始聊窗体大小的测量之前,实际上,在Android系统中,为了把Window各个边界标记出来,实际上随着时代和慧握颤审美潮流的演进,诞生越来越多的边距类型,我们往往可以通过这些边距来测定窗体的大小。

在DisplayFrame中有了大致的分区,如下:

可以看到,这些窗体的边距实际上是跟着这些年潮流走的。如Android 7.0的自由窗体模式,嵌套窗体模式,刘海屏等等,这些边距的共同作用,才会诞生一个真正的Window大小。有了这些基础知识之后,我们去看看测量大小的逻辑。

我前败们这里把这个方法拆成如下几个部分:

能看到,此时会设置当前显示屏幕的大小,以及获取过扫描区域,还会判断当前手机屏幕是否支持刘海屏。这一切实际上都是由硬件回馈到DisplayService,我们再从中获取的信息。

实际上如果有读者注意到我写的WMS第一篇就会看到实际上WMS初始化的时候,我们能够看到WMS会初始化一个WindowManagerPolicy的策略,而这个策略就是PhoneWindowManager。实际上这也支持了系统开发自定义策略,从而办到自己想要的窗体计算结果。

首先初始化几个参数,父窗体,屏幕,过扫描,可见区域,输入法区域为当前逻辑显示屏的大小,等到后面做裁剪。

能看到所有的事情实际上是关注的是系统UI上的判断,检测NavBar,StatusBar大小。最后再判断当前刘海屏的不允许交叉的区域顶部和显示屏顶部哪个大。如果mDisplayCutoutSafe的top大于mUnrestricted的top,说明mDisplayCutoutSafe在mUnrestricted下面,也就是我上面那个包含一段黑色的区域。此时会拿稳定的应用区域和刘海区域顶部的最大值,作为刘海屏幕的区域。这样就能保证刘海屏的顶部就是状态栏。

提一句如果NavigationBar隐藏,则会创建一个虚假的区域把输入事件都捕捉起来。

里面有四个关键函数:

可以看到所有的所有的间距将会设置为mUnrestricted的初始宽高,也就是不包含OverScan区域。如果是遇到刘海屏,则会根据设置的SafeInset区域来设置mDisplayCutoutSafe的安全区域。也就是我上面那种情况。比如设置了LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT这种情况,显示区域将不会超过刘海屏的底部。

我们关注到mTmpNavigationFrame这个对象的赋值,在正常的情况下的范围是如下:

此时mStable和mStableFullscreen区域的底部都是对应着top,也就是对应着Navigation顶部。System系统元素的底部也是Navigation顶部。

最后经过computeFrameLw重新计算这个区域的值。这个方法稍后会聊到,但是在正常手机开发中,其实是没有变化的。也就说,实际上对于mNavigationBar来说:

同理对于statusBar来说:

注意,此时如果statusBar可见,则做如下计算:

这种情况挺常见的,我们从一个隐藏状态栏的页面跳转到有状态栏的页面,国有有个PopupWindow,你能看到这个popwindow会明显向下移动。

在这个方法中mScreenDecorWindows这个集合实际上是在adjustWindowParamsLw以及prepareAddWindowLw这两个方法中加入。加入的条件是,每当有新的Window加入(WMS的addView)或者Window需要重新调整(WMS的relayoutWindow),当前新增得到Window或者需要重新relayout的Window有StatusBar有权限,且显示则会添加到mScreenDecorWindows集合。

mScreenDecorWindows从上面的描述,能得知实际上这个步骤还没有根据层级作区分。但是没关系,此时仅仅只是初步的测量。

明白了mScreenDecorWindows之后,我们阅读上面这个方法就很简单了。

layoutScreenDecorWindows做的事情就如名字一样,要测量Window上装饰部分,如StatusBar,如输入法。此时经过循环,自尾部往头部调用所有的WindowState的computeFrameLw计算每一个WindowState的对应Window的窗体大小。

当计算出每一个窗体大小之后,将会把事件分成两个情况,当计算出来的当前的Window的left和top都小于等于0,也就是说,当前的Window的顶部边缘并且左边缘超过了当前的屏幕。

说明了有什么东西在右下侧把整个Window定上去了。因此dockFrame的计算就很简单了:

如果计算出来的bottom大于等于屏幕高度且right大于等于屏幕宽度。说明有什么东西在左上方把整个Window顶下去了。

最后再设置这个把displayFrames的可见等区域都设置为dockFrame。联合上下文,实际上这里就是把整个区域的顶部移动到了statusBar之下。

⑸ android 中如何让控件一直在窗体底部

android让一个控件按钮居于底部的几种方法
1.采用linearlayout布局:
android:layout_height="0dp"<!--这里不能设置fill_parent-->
android:layout_weight="1"<!--这里设置layout_weight=1是最关键的,否则底部的LinearLayout无法到底部-->
2.采用relativelayout布局:
android:layout_alignParentBottom="true"<!--这里设置layout_alignParentBottom=true是最关键的,这个属性上级必须是RelativeLayout-->
3.采用fragment布局(activitygroup已经被弃用不建议使用)
=====================================
1.采用linearlayout布局:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">

<LinearLayout
android:id="@+id/content"
android:layout_width="fill_parent"
android:layout_height="0dp"<!--这里不能设置fill_parent-->
android:layout_weight="1"<!--这里设置layout_weight=1是最关键的,否则底部的LinearLayout无法到底部-->
android:orientation="vertical">

</LinearLayout>

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/runbackground"
android:focusable="false"/>
</LinearLayout>
</LinearLayout>
2.采用relativelayout布局:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">

</LinearLayout>

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"<!--这里设置layout_alignParentBottom=true是最关键的,这个属性上级必须是RelativeLayout-->
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/runbackground"
android:focusable="false"/>
</LinearLayout>
</RelativeLayout>
3.采用fragment布局(activitygroup已经被弃用不建议使用)
<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<fragmentclass="com.xu.fragment.FragmentDemoActivity$TitlesFragment"android:id="@+id/titles"android:layout_weight="1"
android:layout_width="0px"android:layout_height="match_parent"
/>

<FrameLayoutandroid:id="@+id/details"android:layout_weight="1"android:layout_width="0px"android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground"
></FrameLayout>
</LinearLayout>
==============================================

⑹ Android 多窗口模式(分屏模式)

1: 分屏模式:
该模式可以在手机上使用, 该模式将屏幕一分为二, 同时显示两个应用界面

2: 画中画模式:
该模式主要用于TV, 在该模式下视频播放的窗口可以一直在最顶端显示。(视频小窗口)

3: Freeform模式:
该模式类似于常见的桌面操作系统, 应用界面的窗口可以自由的拖动和修改大小

1:Manifest 新增属性:

2: layout 新增属性:

在freeform模式下定义的默认高度和宽度defaultWidth&&defaultHeight, freeform模式下的初始Gravity, freeform模式下最小高度和宽度minWidth&&defaultHeight。

3: 多窗口的API:

4: 分屏模式的生命周期:

很明显, 从上图的生命周期显示, 在后台将应用进入分屏模式的时候, 先执行destroy()的方法, 即在进入分屏之前, activity会被先销毁,再调用onRestoreInstanceState方法恢复数据, 回调onMultiWindowModeChanged()

我们的 APP 进入分屏模式时,在 onMultiWindowModeChanged 方法中如果有对 UI 等的操作,经过之后的自动重建就没有效果了。为了防止这种情况,需要在 AndroidManifest.xml 的 Activity 节点设置以下属性:android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
设置了这个属性,在进入分屏模式时,Activity 就不会自动重建了。

5 跨Activity对View的拖拽:
Android 4.0 开始支持activity内容的拖拽, 在多窗口的模式下,Android也实现了activity间 实现内容的拖拽。在activity间仅限于内容的拖拽, 对view的拖拽也是没办法实现的 。

热点内容
编译器的结果是什么语言 发布:2025-05-10 11:10:32 浏览:146
快手跑金脚本 发布:2025-05-10 11:10:29 浏览:360
pl0语言编译器分析实验 发布:2025-05-10 11:10:22 浏览:25
湖南外网ftp服务器租用云主机 发布:2025-05-10 10:59:19 浏览:760
入门编程教学视频 发布:2025-05-10 10:56:41 浏览:915
php开发php开发 发布:2025-05-10 10:37:49 浏览:863
服务器地址s开头 发布:2025-05-10 10:36:59 浏览:841
为什么账号风险不能修改密码 发布:2025-05-10 10:31:23 浏览:69
sql与in相对 发布:2025-05-10 10:31:15 浏览:227
c语言led灯闪烁 发布:2025-05-10 10:26:54 浏览:814