/Users/yangyangzi/Desktop/YangZi2/android/Android12/2019/视频学习.rtfd (公司电脑)
视频
一、控件:TextView:标签,用于显示内容,内容不可编辑;Plain Text:内容可编辑;Button; imageView;imageButton:带有点击功能的图片;checkBox复选框;RadioButton单选按钮;radioGroup只能选一个
layout_width
一查看注释方法:选中-》View-》Quick Documentation 快捷键F1
格式化代码:Option + cmd +L
删除整行:cmd + delete
光标到行首:cmd + <—
查找类:cmd+o
查看文件结构:cmd + F12
textStyle
textColor:安卓是十六进制颜色,需以#开头
#RGB #F00(纯红)
#ARGB #FF00(纯红)
#RRGGBB #FF0000
#AARRGGBB #FFFF0000
二、Button继承自TextView
响应点击事件:在代码里注册View.OnClickListener监听器
注册View.OnClickLister方法分以下三种:
内部类
匿名类
XML设置android:onClick
在activity中实现???
外部类的方式来实现???
三、EditText 继承自TextView
inputType 输入类型,小数点等
hint 即placeholder,输入提示
android:singleLine="true" 单行输入
android:background="@color/colorAlpha" 设为透明,下划线几小时
四、imageView及ImageButton(ImageButton是ImageView的子类)
设置图片:
1、在xml文件中设置是android:src
2、在代码中设置是testIMV.setImageResource(R.mipmap.teacher_dev);
图片与button小demo练习
android:scaleType="fitXY" 图片的mode
五、选项控件
单选框:
RadioButton继承自CompoundButton
isChecked();确定是否被选中
setChecked();强制选中或取消选中复选框
setOnCheckedChangeListener事件监听
OnCheckedChangeListener事件回调
六、复选框
CheckBox
StringBuilder 可变字符串
七、资源的使用
1、字符串资源 工程ResourceString
字符串本地化或国际化
支持中文本地化:
在res/文件夹下创建名为values-zh的文件夹,将res/values文件夹下的string.xml文件复制到新建的values-zh文件夹下。注意在values与values-zh文件夹下的string.xml文件里的键必须是共同存在的,即前者有哪个键值对,后者也必须有相应的键值对,否则会报错;注意:键不能重复,值能重复;注意键值对要放在reasource下
xml中取string.xml中字符串值:android:text="@string/yh_world"
代码中取string.xml中的字符串值:buttonYh.setText(R.string.yh_world);
获取resource资源:
Resources res = getResources();
通过resource资源获取具体资源:
String fdd = res.getString(R.string.yh_world);
键值对放在string下:<string name="yh_world">YH_WORLDstring>
在string.xml中添加键值对;也可以在调用的地方添加,例如按钮在Attributes的text属性右侧有三个点,点击此三个点即可选择已有键值对或添加新的键值对
name要小写
2、颜色资源 工程ResourceString
键值对放在color下:<color name="yhred">#FF0000color>
3、图片资源 工程ResourceString
drawable文件夹下:buttonYh.setBackgroundResource(R.drawable.tefreshing01);
mipmap文件夹下:imageBtns.setImageResource(R.mipmap.tefreshing02);
在xml中引用图片:android:roundIcon="@mipmap/ic_launcher_round"
图片放在相应资源下
4、尺寸资源 工程ResourceString
一般用dp或sp做长度单位,与屏幕的物理长度无关
Xml中引用:android:layout_marginBottom="@dimen/yh_width"
键值对放在dimen下:<dimen name="yh_height">50dimen>
八、触屏事件:
工程TouchScreen
重写方法的快捷键 ctrl + o
on开头的方法一般都是回调方法:
1、触摸屏幕
重写onTouchEvent方法
2、触摸屏幕上的某个控件
安卓事件分发机制详解:Android事件分发机制详解:史上最全面、最易懂太长了
九、线性与相对布局
《一》线性布局
LinearLayout:在一个方向上布局
1、orientation:方向:orientation 水平or竖直
2、layout_gravity:对齐方式:layout_gravity 左 右 中间 上 下对齐 默认左上对齐
3、layout_weight权重:占父控件的百分比;eg:两个按钮,各占屏幕的50%,则两个按钮设置如下属性值为:layout_width=“0dp” layout_weight=”1“;
方式:gravity 文字对齐android:gravity="left"
当有layout_weight用法
orientation 为 vertical时,则竖直方向的layout_height取值不起作用
orientation 为 horizontal时,则水平方向的layout_width取值不起作用
java将int转变为string方法:
1、buttonView.getId() + ""
2、String.valueOf(buttonView.getId())
LinearLayoutTest工程有问题???,待解决
java中的 a |= b 即 a = a || b
CheckBox的setChecked的方法中调用了onCheckedChanged方法
2019.2.15
《二》相对布局RelativeLayout:
1、相对于容器; 工程RelativeLayout
layout_alignParentTop = "true"
layout_alignParentBottom = "true"
layout_alignParentLeft = "true"
layout_alignParentRight = "true”
layout_centerInParent = "true"
2、相对于控件; 工程RelativeLayout
根据id做控件对齐依据
layout_above="@id/button1" 其下边与button1的上边挨着
layout_below="@id/button1" 其上边与button1的下边挨着
layout_alignLeft="@id/button1" 其与button1的左边对齐
layout_alignTop="@id/button1" 其与button1的上边对齐
layout_toLeftOf="@id/button1" 其右边与button1的左边挨着
layout_toRightOf="@id/button1" 其左边与button1的右边挨着
3、基线对齐 工程RelativeLayout2
layout_alignBaseline="@id/rightET" 与rightET的底部基线对齐
2019.2.18
布局公有属性
Padding:控件的内容与控件边缘的距离;
Margin:控件与控件的相对距离;包括子控件与父控件边缘距离
线性与相对布局的嵌套使用:工程LinearAndRelative
字体大小:textSize
子视图在俯视图的布局:margin
LayOut文件出问题,不报错,却运行不了,太坑了,写错了也不知道,太坑
嵌套原则:层数越少约好,越简单约好
《三》表格布局:TableLayout
1》、在行中添加单元格TableRow:
android:layout_column="2" 指明列数
android:layout_span="2" 横向合并列
没有添加tableRow的情况,则一个控件占一行
注意:一个TableviewLayout有几行是根据TableRow的个数决定的
而有每个TableRow有几列不是其本身的TableRow上控件个数决定的,而是由其上下文决定的,即看此TableLayout中哪个TableRow的控件个数最多,按这个最多的TbaleRow的控件个数决定
2》、扩展、收缩和折叠
扩展:android:stretchColumns="1" 第一列可以扩张,占tableRow剩下的所有宽度
收缩:android:shrinkColumns="1" 内容长时第一列可以收缩自动换行
折叠:android:collapseColumns="1" 隐藏第一列
只能合并列,不能合并行
《四》网格布局:GridLayout
可以设置
组件的排列方式:android:orientation="vertical”默认是horizontal
行数:android:rowCount="6"
列数:android:columnCount="4"
合并两行:android:layout_rowSpan="2"
合并三列:android:layout_columnSpan=“3”
填充合并的行或列:android:layout_gravity="fill”(layout_gravity还可以取值center/left/right/buttom及相应的_horizontal和_vertical)
《五》帧布局:FrameLayout 三星
显示的控件都会放在屏幕左上角,不能指定位置
当有多个显示对象,后一个将会遮盖住前一个
《六》布局:DrawerLayout 一星
能实现DrawerLayout效果的关键是:android:layout_gravity = "start"
android:gravity:是对view控件本身来说的,是用来设置view本身的内容应该显示在view的什么位置,默认值是左侧。也可以用来设置布局中的控件位置;
表示当前View,即控件,内部的东西的,对齐方式
.android:layout_gravity:是相对于包含该元素的父元素来说的,设置该元素在父元素的什么位置;
表示当前View,即控件本身,在父一级内的对齐方式
gravity与layout_gravity的区别:https://www.cnblogs.com/fuck1/p/5461952.html
《七》布局:ScrollVIew 一星 extens FrameLayout
ScrollView和HorizontalScrollView只能有一个子控件,一般会放个LinearLayout
ScrollView用于设置垂直滚动条;HorizontalScrollView用于设置水平滚动条
随意
2019.2.19
消息处理机制
主线程超过5秒为响应,则系统会弹ANR框报错 Sorry 。。。is not
responding
一、消息队列
消息循环产生消息队列
Activity用消息队列(Message Queue)机制保证线程间通信
消息队列用来存放Handler发布的消息
安卓在程序第一次启动时会默认为UI线程(主线程)创建一个关联消息队列,用来管理程序的组件,如Activity,Service,Broatcast Receiver等
不同线程用Handler来使子线程和主线程通信
可以在子线程(工作线程中)创建Handler与主线程通信
主线程创建looper,looper里存放消息队列,消息队列里存message
二、Handler的消息传递机制 工程MessageRules
1、子线程通过Handler与主线程通讯
2、Handler对象的所有工作将在主线程中执行
3、Handler需要实现handleMessage()方法,来处理消息队列中去除的Message对象
4、handleMessage()方法由主线程调用,可以在需要的时候更新UI界面。但是,必须确保此方法快速完成,因为其他UI操作会等待它完成才能执行
5、可以在Message中附加不同参数 water标示;avg1,avg2传递int类型数据;obj传递对象类型的数据
三、Handler的编程接口
方法
void handleMessage(Message message) 在主线程处理消息
boolean sendEmptyMessage(int what) 发送空消息,此参数是一个消息标示
boolean sendMessage(Message message) 发送消息到Handler中,在handleMessage中处理
boolean hasMessage(int what) 判断是否有what消息
boolean post(Runnable r) 将一个Runnable添加到消息队列
XML的解析:
1、xml文件放在res/xml目录下,注意res下默认没有xml文件夹,需要手动创建该文件夹,若果单纯放在res文件夹下回报错
2、xml文件在部署时将被编译为有效的二进制文件
3、根据需要可以自定义xml结构
4、安卓使用pull方式解析xml,本事是SAX解析(事件驱动,需要知道事件)
XMLPullPaser
写示例
Java的抛异常机制???
效率好低啊
JSON解析
在res文件夹下新建raw文件
期初加入到raw文件夹下的文件名为parJson.json,后报错,把文件名的大写J改为小写j即可
线程使用场景:解析xml并展示在listView上
工程:SimpleAdapterTest
1、onCreate方法中,创建子线程,并在子线程中添加要执行的异步操作(在run方法中),解析完文件,通过sendmessage回到主线程:
new Thread(){
@Override
public void run() {
try {
parseXml();
handler.sendEmptyMessage(what);
} catch (XmlPullParserException e) {
handler.sendEmptyMessage(lala);
// e.printStackTrace();
} catch (IOException e) {
handler.sendEmptyMessage(lala);
// e.printStackTrace();
}
};
}.start();
2、回到主线程在,handler的handleMessage方法将得到的数据复制到主线程的listview
注意:不能再子线程处理控件,否则报错,需要回归到主线程再操作主线程
2.21 StringBuilder的.append(name)方法,传参不能为空
控件
消息提示Toast:
弹出Toast:短暂弹框,不用用户响应
静态方法:makeText()
构造函数:new ;setView();setDuration()
自定义Toast:通过LayoutInflater.from加载自定义view
View tview = LayoutInflater.from(this).inflate(R.layout.toast_self_defined_view, null);
AlertDialog:通过Builder创建,链式语法.set设置:
1》提醒框: AlertDialog
以下对话框都是AlertDialog,只是参数不同:
列表对话框:
2》单选列表对话框:AlertDialog
.setSingleChoiceItems(ddArray, 1, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("TEST", "" + which + "");
}
})
3》多项选择列表对话框;AlertDialog
.setMultiChoiceItems(sdff, new boolean[]{false, true, true}, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
Log.d("TEST", which + "," + isChecked);
}
})
4》普通列表对话框 AlertDialog
无.setxxChoiceItems()方法
进度条对话框:ProcessDialog(圆圈或长条)
自定义对话框:工程SelfDefinedDialog
方式一:产生一个Dialog类实例:setContentView(View view)设置自定义的视图:
twoDialog = new Dialog(this);
twoDialog.dismiss();
方式二:使用AlertDialog.Builder创建AlertDialog实例:setView(View view)设置自定义视图;.create()创建对象 工程 SelfDefinedDialog
内部类要用到外部类的局部变量,需要用final修饰此局部变量
2019.2.25
适配器:Adapter
负责为选择部件提供数据源,也负责将单独的数据元素转换为显示在选择部件中的特定视图
ArrayAdapter的三个参数:(安卓系统写好的适配器)
参一:上下文,通常是当前activity的实例
参二:使用的视图资源的ID
参三:要实际显示的选项数组或列表
列表:ListView
示例工程:AdapterAndListview
ArrayAdapter arrayAdapter = new ArrayAdapter(
this,
android.R.layout.simple_list_item_1,
android.R.id.text1,
data
);
listView.setAdapter(arrayAdapter);
SimpleAdapter:将xml解析并赋值给listview
listView = findViewById(R.id.listview);
SimpleAdapter simpleAdapter = new SimpleAdapter(
this,//上下文
data,//数据源
R.layout.list_item,//项布局
new String[]{"name","age"},//显示数据在数据源中的key
new int[] {R.id.leftTV, R.id.rightTV }//显示数据的控件id
);
listView.setAdapter(simpleAdapter);
private static final int what = 1001; 修饰词这么多
BaseAdapter:
工程:BaseAdapterTest
BaseAdapter 只是一个父类,在使用时需要创建继承自BaseAdapter的子类
ListView提高效率(相当于ios的cell重用机制);
工程:BaseAdapterAndEfficientTest 2.26
与public View getView(int position, View convertView, ViewGroup parent) {}方法的covertView参数相关的重用机制,
获得自定义xml的解析方法是dom解析,此种解析方法每次解析都会将文件放入内存,如果没有使用重用机制就太浪费空间了,故我们在这创建了一个ViewHolder持有者,对自定义xml的子控件进行缓存持有。
此例用count值查看是否重用了;
ListView提高效率:使用ConterView+使用持有者模式
GridView:网格控件与上边的ListView相似(ios的collectionview)
与listview一样都是选项控件,用适配器:
verticalSpacing:垂直间距
GridView随着数据的刷新而更新:工程AdapterRefresh (数据更新reload;按钮的点击事件写法3:视频里extends Activity;而现在AS是extends AppCompatActivity,故这种事件点击方式不适用AS
public class AdapterRefresh extends AppCompatActivity implements OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addBtn.setOnClickListener(this);
}})
String name = editText.getText().toString().trim();
方法trim()的作用:去掉字符串收尾的空格
通知数据修改Adapter的notifyDataSetChanged()方法
Spinner:显示下拉式内容,显示多项内容的选择控件
工程:SpinnerTest
1》通过Adapter添加数据 topSpinner.setAdapter()
2》在xml文件中通过属性entries添加字符串资源中数组添加数据 android:entries="@array/name_string_array"
进阶:联动spinner(班级:学生级联菜单)工程SpinnerTest(自己写的有问题) + 工程SpinnerLianDongTest(视频的)
注:开始自己写的工程SpinnerTest来演示联动spinner,总是编译不过,经过各种尝试,发现是泛型使用不规范引起的,看来java对泛型的要求很高啊,以后凡是数组一定要加上泛型(ios在泛型这块就没那么苛刻了)
java数组:
private List
leftArray.add("安卓");
leftArray.add("苹果");
与
private String[] leftArray = {"安卓", "苹果"};
有啥区别?
前者是集合,后者才是数组待java书到之后细研究
Activity配置:
四大组件之一;组件必须在AndroidManifest.xml中说明才能使用
AndroidManifest.xml文件中的
1、package="com.example.yangyangzi.spinnertest”是包名
<activity android:name=".SpinnerTest"> 此处是类名
2、<activity android:name=".SecondActivity"
android:label="第二个Activity">activity>
此处的android:label默认是
<application
android:allowBackup="true"
android:label="@string/app_name”>处的label
Activity之间的跳转:
通过intent跳转:
显式跳转:通过目标Activity名称跳转
Intent intentt = new Intent(this,SecondActivity.class);
startActivity(intentt);
或
{
// Intent intent = new Intent();
// intent.setClass(this,SecondActivity.class);
// startActivity(intent);
}
隐式跳转:通过activity的逻辑动作名跳转,可以不暴露目标Activity的名称
AndroidManifest.xml:
<activity android:name=".ThirdActivity"
android:label="第三个Activity">
<intent-filter>
<action android:name="yhaction"/>
<category android:name="android.intent.category.DEFAULT"/>
intent-filter>
activity>
Intent intent = new Intent();
intent.setAction("yhaction");
startActivity(intent);
Activity间通讯:
启动Activity:startActivity;startActivityForResult:启动过程有返回
通过:intent.putExtras(Bundle); intent.putExtra(key,value);传值到另一个组件
接收:目标组件通过getIntent()得到intent,通过getExtras方法得到所传的对象
工程:ActivityPassSomething
Activity返回值:
开始Activity:
startActivityForResult() 启动Activity
onActivityResult() 接收目的Activity返回的数据
目标Activity:
setResult(code,intent); 目标Activity设置返回的内容
Activity生命周期:示例工程:LifeOfActivity
onCreate创建,在整个生命周期只调用一次
onStart加载到内存,Activity不可见,启动
onResume显示,Activity可见
onPause失焦点,Activity可见,但是不能操作
onStop被其他Activity盖掉,Activity不可见,未销毁
onDestory 在整个生命周期只调用一次,
点back则onDestory了
线程Thread中,返回到主线程的另一方法:
线程的终止居然用boolean属性值和死循环实现
new Thread(){
@Override
public void run() {
count++;
handler.post(new Runnable() {
@Override
public void run() {
//运行在主线程中
textView.setText("" + count);
}
});
}
}.start();
Activity的启动模式:4种launchMode
在AndroidManifest.xml中设置模式launchMode:
<activity android:name=".SingleInstanceActivity"
android:label="SingleInstanceActivity"
android:launchMode="singleInstance"
>activity>
1、standard(默认):每次激活Activity都会重新创建,并放入任务栈中
2、singleTop:如果在任务的栈顶正好存在该Activity的实例,就会重用该实例,而不会重新创建新的Activity对象,不过它会调用onNewIntent()方法;如果栈顶不存在就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。不会调用onNewIntent()方法
注:Activity中this.toString()结果 一般都是包名+@+16进制字符串
3、singleTask:如果在栈中有改Activity实例,就重用该实例(会调用实例的onNewIntent()方法);
重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。
如果栈中不存在该实例,将会创建新的实例放到栈中
在栈中只有一个
4、singleInstance:与singleTask模式的区别是存放singleInstance模式窗口对象的回退栈不能有其他任何窗口对象。因此如果该窗口不存在,则要新建任务来存放该singleInstance窗口???
即创建了一个新的栈,可以理解为单例模式
单例的理解如下图:
对上图的解释(也是singleInstance模式的精髓)
现在有两个Activity,即MainActivity(除SingleInsatnce模式以外的其他模式)和SingleInstanceActivity(SingleInstance模式):
由MainActivity跳到SingleInstanceActivity(创建新的SingleInstanceActivity),
再由SingleInstance跳到MainActivity(创建新的MainActivity),
再由MainActivity跳到SingleInstanceActivity(用旧的SingleInstanceActivity),
再由SingleInstance跳到MainActivity(创建新的MainActivity),三
再由MainActivity跳到SingleInstanceActivity(用旧的SingleInstanceActivity) 四
注意以上跳转是互相调用而非返回
MainActivity无论属于哪种模式在这种情况,按正常走都得新建;SingleInstanceActivity因为是SingleInstance模式的只用新建一次(跟单例差不多)
接下来,在上边操作步骤基础上,
做回退操作(当前在SingleInstanceActivity里即从四开始回退):
在SingleInstanceActivity时点击返回按钮,退到MainActivity,
再点返回按钮,还是退到MainActivity,
再点返回按钮,还是退到MainActivity,
再点返回按钮,还是退到MainActivity,
再点返回按钮,退到桌面
SingleInstance回退一次,在回退则进入正常的任务栈,将此栈的所有Activity销毁后,之后再点一次返回则退到home
做回退操作(当前在MainActivity里即从三开始回退):
在MainActivity页面点返回按钮,还是退到MainActivity,
再点返回按钮,还是退到MainActivity,
再点返回按钮,还是退到MainActivity,
再点返回按钮,还是退到MainActivity,
再点返回按钮,还是退到SingleInstanceActivity,
再点返回按钮,退到桌面
说明先是把正常的任务栈的所有Activity销毁后再点返回才会跳到SingleInstance模式的Activity,之后再点一次返回则退到home
注:finish()与点返回按钮当前Activity都被从任务栈中移除
栈id:栈的唯一标识符
灵活使用四种Activity模式可以节约系统资源
Fragment的生命周期和使用:
Fragment是在Android3.0(API level 11)开始引入新的API技术。
为提高代码重用性和改善用户体验,我们将Activity中的UI组件进行分组和模块化管理。这些分组后的UI组件就是Fragment。
一个Activity可以包含多个Fragment模块,而同一个Fragment模块也可以被多个Activity使用。
每个Fragment有自己的布局,有自己是生命周期。
我们可以设计Fragment的布局
Fragments必须放在一个Activity中,
Fragments有自己的生命周期,而且受到它所在宿主Activity是声明周期的影响
Fragmens可以接收它自己是事件
一个Fragment可以放在多个Activity中,一个Activity也可以放置多个Fragments
Fragment的生命周期:
创建一个Fragment需要实现是回调函数:
onCreate():创建Fragment时系统会调用此函数
onPause():当用户离开当前Fragment时调用此方法。通常用来保存持久化数据
OnCreateView():当Fragment第一次绘制它的UI时调用。这个方法必须返回一个View,表示这个Fragment的根布局
创建Fragment,如果用到早期的Android系统如2.2,2.3则需要继承自android.support.v4.app.Fragment()即minSdkVersion<11时继承自v4 jar包;其他直接继承自系统的Fragment的jar包,安卓3.0以上
Fragment的生命周期:
[Fragment is added]->onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume()->[Fragment is active]->1、/2、->onPause()->onStop()->onDestoryView()->onDestory()->onDetach()->[Fragment is destoryed]
Fragment的生命周期和Activity做比较:
(一)运行-》界面出现 (MyFragmentMyFragment是Fragment;ActivityMyFragment是Activity)
MyFragmentMyFragment: onCreate
MyFragmentMyFragment: onCreateView
ActivityMyFragment: onCreate
ActivityMyFragment: onStart
MyFragmentMyFragment: onStart
ActivityMyFragment: onResume
MyFragmentMyFragment: onResume
Fragment的onCreate->Activity的onCreate->Activity的onStart->Fragment的onStart->Actvity的onResume->Fragment的onResume
工程界面-》home键(Activity不销毁)-》桌面
MyFragmentMyFragment: onPause
ActivityMyFragment: onPause
MyFragmentMyFragment: onStop
ActivityMyFragment: onStop
Fragment的onPause->Activity的onPause->Fragment的onStop->Activtiy的onStop
桌面-》工程界面
ActivityMyFragment: onStart
MyFragmentMyFragment: onStart
ActivityMyFragment: onResume
MyFragmentMyFragment: onResume
Activity的onStart->Fragment的onStart->Activty的onResume->Fragment的onResume
工程界面-》返回键(Activity销毁)-》桌面
MyFragmentMyFragment: onPause
ActivityMyFragment: onPause
MyFragmentMyFragment: onStop
ActivityMyFragment: onStop
MyFragmentMyFragment: onDestroy
ActivityMyFragment: onDestroy
Fragment的onPause->Activty的onPause->Fragment的onStop->Activity的onStop->Fragment的onDestory->Activity的onDestory
返回后桌面-》工程界面
MyFragmentMyFragment: onPause
ActivityMyFragment: onPause
MyFragmentMyFragment: onStop
ActivityMyFragment: onStop
ActivityMyFragment: onStart
MyFragmentMyFragment: onStart
ActivityMyFragment: onResume
MyFragmentMyFragment: onResume
Fragment的生命周期和Activity非常相似,一个Fragment可以处于3种状态:
运行:Fragment在当前运行的前台,Activity中可见
暂停:另一个Activity在前台,具有焦点,但是Fragment所在的Activity依然可见
停止:Fragment不可见。宿主Activity处于停止状态或Fragment已经从Activity删除并添加到后台栈中。
Framment的宿主Activity的生命周期直接影响Fragment的生命周期。因此,Activity的每个生命周期回调函数都会调用Fragment的回调函数。例如,当宿主Activity的onPause()方法被调用时,Fragment的onPause()方法也被调用。
(二)Fragment还有一些其他的回调函数与宿主Activity交互,处理UI的创建与销毁。
onAttach()当Fragment与Activity建立关联时调用,Activity作为参数传入;
onCreateView()创建Framgment的UI;
onActivityCreated()当Activity的onCreate()方法返回时调用;
onDestoryView()当Fragment的UI被删除时调用;
onDetach()当Frament与Activty取消关联调用;
加入以上四个Fragment的方法后的运行顺序为:
运行-》工程界面:
MyFragmentMyFragment: onAttach
MyFragmentMyFragment: onCreate
MyFragmentMyFragment: onCreateView
ActivityMyFragment: onCreate
MyFragmentMyFragment: onActivityCreated
ActivityMyFragment: onStart
MyFragmentMyFragment: onStart
ActivityMyFragment: onResume
MyFragmentMyFragment: onResume
工程界面-》back-》桌面:
MyFragmentMyFragment: onPause
ActivityMyFragment: onPause
MyFragmentMyFragment: onStop
ActivityMyFragment: onStop
MyFragmentMyFragment: onDestroyView
MyFragmentMyFragment: onDestroy
MyFragmentMyFragment: onDetach
ActivityMyFragment: onDestroy
无论是home还是back后的桌面-》工程界面都和(一)相同
Fragment的生命周期:
当宿主Activity处于运行状态时,可以自由添加和删除Fragment。只有Activity处于运行状态时,Fragment的声明周期才能独立变化。否则,直接受宿主Activity声明周期的影响
3.4Frament交互及管理
1》FragmentManager API:工程FragmentManagerTest
APP:import android.app.FragmentManager;
获取FragmentManager:manager = getFragmentManager();
获取Fragment:fragmentDemo = (FragmentDemo) manager.findFragmentById(R.id.myfragment);
fragmentDemoOne = (FragmentDemo)manager.findFragmentByTag("YHLL");
V4包:import android.support.v4.app.FragmentManager;
获取FragmentManager:manager = getSupportFragmentManager();
获取Fragment:v4FragmentDemo = (V4FragmentDemo)fragmentManager.findFragmentById(R.id.v4fragment);
manager.findFragmentByTag("YHLL");
v4FragmentDemoTwo = (V4FragmentDemo)fragmentManager.findFragmentByTag("v4fragmentTwo");
2》FragmentTranscation API(动态添加Fragment,以前的都是静态添加的):工程FragmentTranscationTest
add():向容器中添加一个Fragment
remove():删除Fragment
replace():将容器中的Fragment替换成新的Fragment
hide():隐藏已存在的Fragment
show():显示此前隐藏的Fragment
addToBackStack():将事务添加到后台栈
commit():提交事务,将改变应用到Activity
.replace()替换Fragment(注意:不能替换本Fragment只能是替换另一个不同类型的Fragment)
添加Fragment:
FragmentManager manager = getFragmentManager();//1、获取FragmentManager
FragmentTransaction transaction = manager.beginTransaction();//2、通过FragmentManager获取FragmentTransaction事物
MyFragment myFragment = new MyFragment();//3、创建Fragment
transaction.add(R.id.frameLayout,myFragment,"he");//4、将上边的Fragment添加到FragmentTransaction事物
transaction.commit();//5、提交事物
替换Fragment:
//添加到返回栈中,点返回按钮则依次返回,最后退到桌面,不添加返回栈的则直接退到桌面
getFragmentManager().beginTransaction().replace(R.id.frameLayout,numFragment).addToBackStack(null).commit();
静态方法(类方法);静态成员变量(类成员变量ios无);工程JavaTest
3》系统提供的Fragment类开发者可以继承:实现了Fragment类的子类
DialogFragment:显示一个悬浮对话框 工程:DialogFragmentTest
好像和AlertDialog差不多啊,为么还要费事用DialogFragment???
DialogFragmentTest.this.showToast();//成员方法调用showToast()实例方法
((DialogFragmentTest)getActivity()).showToast();//getActivity()调的是FragmentActivity
java:
非静态方法可以访问静态方法;而静态的不能访问非静态的 非静态>静态 对比ios的工程:testLei
静态与非静态之间的互相调用 DialogFragmentTest-TestStatic类
public statc class MyDialogFragment extends DialogFragment{
public static MyDialogFragment newInstance (String tittle){//初始化带参静态方法
MyDialogFragment myDialogFragment = new MyDialogFragment();
Bundle bundle = new Bundle();
bundle.putString("title",tittle);
myDialogFragment.setArguments(bundle);
return myDialogFragment;
}
public Dialog onCreateDialog(Bundle savedInstanceState) {//创建AlertDialog弹窗
tittle = getArguments().getString("title");
Dialog dlog = new AlertDialog.Builder(getActivity())
.setTitle(tittle)
.setIcon(R.mipmap.ic_launcher)
.setPositiveButton("确定", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
((DialogFragmentTest)getActivity()).showToast();
}
})
.setNegativeButton("取消",null)
.create();
return dlog;
}
}
ListFragment:显示一个由adapter管理的项目列表
public void showListFragmentAction(View view){
String[]data = {"AAA","BBB","CCC"};
MyListFragment myListFragment = MyListFragment.newInstance(data);
getFragmentManager().beginTransaction()
.add(R.id.fatherLayout,myListFragment)
.commit();
}
public static class MyListFragment extends ListFragment {
public static MyListFragment newInstance(String[] data){
MyListFragment myListFragment = new MyListFragment();
Bundle bundle = new Bundle();
bundle.putStringArray("data",data);
myListFragment.setArguments(bundle);
return myListFragment;
}
@Override
public void onAttach(Context context) {//设置适配器
super.onAttach(context);
String[] data = getArguments().getStringArray("data");
setListAdapter(new ArrayAdapter
getActivity(),
android.R.layout.simple_list_item_1,
android.R.id.text1,
data
));
}
@Override
public void onListItemClick(ListView l, View v, int position, long id){//重新onListItemClick方法,响应点击事件
Toast.makeText(getActivity(),data[position],Toast.LENGTH_LONG).show();
super.onListItemClick(l, v, position, id);
}
}
Fragment如果是动态添加到宿主Activity,则不一定和Acitivity声明周期相关
3.11
Fragment总和应用(一)
支持平板和手机 工程名:FragmentAdaptePhoneAndPad 3月文件夹
v4包的Activity继承自FragmentActivity
另一种Activity继承自Activity
接口:
FragmentAdaptePhoneAndPad->MyJieKou
FragmentAdaptePhoneAndPad->SelectCityListener
FragmentAdaptePhoneAndPad->FatherJieKou
接口之间的继承;类在实现多个接口
适配横竖屏*** layout-land
为了避免在一个Fragment中出现调用另外一个避免耦合严重,应该定义回调接口,需要宿主Activity实现这个接口。这样在Fragment接收到事件的时候,调用这个接口中的方法让Activity根据具体的配置做出响应
Fragment总和应用(二)
ViewPager 在supportv4中:一般和Fragment使用,也可以和view使用;在3.0以下版本只能用view,以上版本用Fragment配合使用,官方(谷歌)推荐使用Fragment
<android.support.v4.view.ViewPager
android:layout_width=""
android:layout_height="">android.support.v4.view.ViewPager>
布局解析器inflater:LayoutInflater inflater = LayoytInflater.from(this);
viewPager对象设置适配器:PagerAdapter(是一个抽象类)
以view为子视图工程:ViewPagerTest 抽象类是PageAdapter
//给ViewPager对象设置适配器PageAdapter
viewPager.setAdapter(new MyPageAdapter());
public class MyPageAdapter extends PagerAdapter{
@Override
public int getCount() {
return views.length;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
return view == o;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView(views[position]);
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
container.addView(views[position]);
return views[position];
}
}
以Fragment为子视图工程:ViewPagerTestAgain 抽象类是专门用于Frament的FragmentPagerAdapter
viewPager.setAdapter(new MyPageAdapater(getSupportFragmentManager()));
class MyPageAdapater extends FragmentPagerAdapter {
public MyPageAdapater(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int i) {
return fragments[i];
}
@Override
public int getCount() {
return fragments.length;
}
}
注意:
1》view和Fragment分别做子类时,其viewpager对象的适配器PageAdapter不同,但都是继承自抽象类PageAdapter的自定义抽象类;
2》抽象类需要实现的方法不完全相同;
3》Viewpager设置适配器的构造方法的参数有差别
2019.3.12
ViewPager的总和运用(三)FragmentThreeTest
使用ViewPager实现基本导航,即不随ViewPager而滚动
Viewpager:
设置当前子控件:viewPager.setCurrentItem(item);
滑动及选中事件:viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int i, float v, int i1) {//正在滚动
}
@Override
public void onPageSelected(int i) {//已经改变
selectTittle(i);
}
@Override
public void onPageScrollStateChanged(int i) {//滚动状态发生改变
}
});
ViewPager的总和运用(四)工程:FragmentFourTest(自己写的) 工程:FragmentThreeTest的副本(视频关键位置运用)
欢迎界面:
选择器的创建和使用(FragmentThreeTest的副本):
在drawable文件夹下新建文件dot.xml(new -file -Drawble Resource File-dot.xml选择selector)
xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:drawable="@drawable/raidono">item>//选中状态是图片raidono
<item android:state_enabled="false" android:drawable="@drawable/raidoselec">item>//非选中状态是图片raidoselec
selector>
图片在使用时,则src如下:(dot为上边创建的xml的文件名)
<ImageView
style="@style/tab_style"
android:src="@drawable/dot"
/>
为何selector的图片只能放在drawable文件夹下??不做图片适配么?
ActionBar:(Fragment综合使用五)工程:ActionBarVSFragmentFiveTest
使用ActionBar来创建tab步骤,则滑动效果自然就有了
启用NAVIGATION_MODE_TABS
创建几个ActionBar.Tab的实例
对每个实例实现ActionBar.TabListener接口
2019.3.13
DrawerLayout :(抽屉式导航 Fragment综合使用五)工程:DrawerLayoutVSFragmentTest
自定义控件:
按类型划分,自定义View的实现方式可分为三种:
自绘控件:工程 SelfDefinedControlDraw
View上所展示的内容全部是绘制出来的;
绘制代码写在onDraw()方法中的;
自定义在View界面上显示,只需要像普通控件一样使用自定义view即可
示例:圈;长方形;图片
<com.example.yangyangzi.selfdefinedcontroldraw.DrawView //包名+类名
android:layout_width="match_parent"
android:layout_height="match_parent" />
移动的自定义view 工程:SelfDefinedControlInvalidate
view的刷新
组合控件:工程CollectionSelfDefinedControl
XML组合控件;代码组合控件
继承控件:工程ExtendsSelfDefinedControl
3.14 Service
是一种Android的组件,可以在后台长时间运行
不提供交互界面:
即便用户跳转至另一个应用后,service仍在后台运行
任意应用组件都可以绑定服务,甚至可以用来完成进程间通讯的任务,例如 需要下载时;播放音乐;文件I/o
3.15 工程:ServiceTest
1>单独的服务:
创建service file-》new service
启动服务:
intent = new Intent(this,MyService.class);
startService(intent);
停止服务:
intent = new Intent(this,MyService.class);
stopService(intent);
重写服务的方法:
onCreate;onDestroy;onStartCommand;onBind
点击start按钮:
onCreate
onStartCommand
点击stop按钮:
onDestroy
再点击start按钮:
onCreate
onStartCommand
再点击start按钮:
onStartCommand
注意:如果启动服务再次启动服务,则会调用onStartCommand方法
2>和应用关联的服务:
创建service file-》new service
启动服务:
intent = new Intent(this,MyService.class);
bindService(intent, conn, BIND_AUTO_CREATE);//bindService必须要有个连接的存在,如果不存在BIND_AUTO_CREATE参数指示自动创建
停止服务:
intent = new Intent(this,MyService.class);
unbindService(conn);
重写服务的方法:
onCreate;onDestroy;onStartCommand;onBind
点击bind按钮:
onCreate
onBind
onServiceConnected(Activity中)
点击unbind按钮:
onDestroy
再点击bind按钮:
无反应
再点击start按钮:
无反应
注意:如果要Activity的ServiceConnection的回调方法响应,必须在onBind方法中创建并返回继承自Binder的类
工程:BindServiceTest 用bind的service计算平均分,并显示在界面上
内部类方法可以调用外部类方法,反之不可
工程:StartServiceTest 用startService的方法计算平均分,只能在sevice计算,不能单纯返回到activity,以后可以用广播的方式返回并展示
系统服务:
由于是Android原代码,可以通过Android代码来对服务进行交互
Android将Binder封装成普通的Manager类,代码调用时无法察觉是使用了Service
这些服务通过Context.getSystemService(String name)来获得,name决定了获得不同的Mananger类,不同的Manager类有各自的方法来调用系统功能或是访问系统状态
例如:
电源管理:POWER_SERVICE
NotificationManager通知的管理:NOTIFICATION_SERVICE
LocationManager定位的控制:LOCATION_SERVICE
ConnectionManager网络连接的控制:CONNECTIVITY_SERVICE
示例:SystemServiceTest 音量和闹铃