Fragment
Fragment(碎片)就是小型的Activity,它是在Android3.0 时出现的。
- 可以把fragment 想象成activity的一个模块化区域
- 有它自己的生命周期,接收属于它自己的输入事件,并且可以在activity运行期间添加和删除
Fargment入门
- 为Fragment 定义一个布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="我是Fragment1里面的内容"
android:textColor="#ff0000" />
</LinearLayout>
- 定义类继承Fragment
- 重写类中的onCreateView 方法,返回一个View 对象作为当前Fragment 的根布局。如果fragment 不提供UI,可以返回null
//定义Fragment 理解为 是Activity的一部分
public class Fragment1 extends Fragment {
//当系统第一次画ui的时候调用 通过这个方法方法可以让Fragment显示自己的布局内容
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//通过打气筒把一个布局转换成一个View对象
View view = inflater.inflate(R.layout.fragment1, null);
return view;
}
}
- 展示:一是使用布局配置,二是代码动态加载
配置
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment android:name="com.itheima.fragmendemo.Fragment1"
android:id="@+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
动态加载
public class MainActivity extends Activity {
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]获取手机的分辨率
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
int width = wm.getDefaultDisplay().getWidth();
int height = wm.getDefaultDisplay().getHeight();
//[2]判断横竖屏
//[3]获取Fragment的管理者 通过上下文直接获取
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction beginTransaction = fragmentManager.beginTransaction(); //开启事物
if(height > width){
//说明是竖屏 加载一个Fragment android.R.id.content //代表当前手机的窗体
beginTransaction.replace(android.R.id.content, new Fragment1());
}else {
//说明是横屏 加载一个Fragment
beginTransaction.replace(android.R.id.content, new Fragment2());
}
//[4]最后一步 记得comment
beginTransaction.commit();
}
}
示例 使用Fragment模仿微信界面布局
public class MainActivity extends Activity implements OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// [1]找到按钮
Button btn_wx = (Button) findViewById(R.id.btn_wx);
Button btn_contact = (Button) findViewById(R.id.btn_contact);
Button btn_disconver = (Button) findViewById(R.id.btn_disconver);
Button btn_me = (Button) findViewById(R.id.btn_me);
// [2]设置点击事件
btn_wx.setOnClickListener(this);
btn_disconver.setOnClickListener(this);
btn_me.setOnClickListener(this);
btn_contact.setOnClickListener(this);
}
@Override
public void onClick(View v) {
//[4]获取Fragment的管理者
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction beginTransaction = fragmentManager.beginTransaction();
// 具体判断点击的是哪个按钮
switch (v.getId()) {
case R.id.btn_wx: // 点击的是微信
beginTransaction.replace(R.id.ll_layout, new WxFragment());
break;
case R.id.btn_contact: // 点击的是联系人
beginTransaction.replace(R.id.ll_layout, new ContactFragment());
break;
case R.id.btn_disconver: // 点击的发现
beginTransaction.replace(R.id.ll_layout, new DiscoverFragment());
break;
case R.id.btn_me: // 点击的是我
beginTransaction.replace(R.id.ll_layout, new MeFragment());
break;
}
//记得comment
beginTransaction.commit();
}
}
Fragment 的生命周期
onAttach:绑定到activity
onCreate:创建fragment
onCreateView: 创建fragment 的布局
onActivityCreated: activity 创建完成后
onStart: 可见, 不可交互
onResume: 可见, 可交互
onPause: 部分可见, 不可交互
onStop:不可见
onDestroyView: 销毁fragment 的view 对象
onDestroy: fragment 销毁了
onDetach: 从activity 解绑了
- Fragment 的向下兼容
Fragment 是在Android 3.0 才推出的
- 把所有Fragment 和FragmentManager 改成support-v4 包下的类
- 把Activity 的继承改为FragmentActivity(support-v4 包下的)
Fragment 之间的通信案例
- Fragment有一个公共的桥梁 Activity
Fragment1
//定义Fragment 理解为 是Activity的一部分
public class Fragment1 extends Fragment {
//当系统第一次画ui的时候调用 通过这个方法方法可以让Fragment显示自己的布局内容
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//通过打气筒把一个布局转换成一个View对象
View view = inflater.inflate(R.layout.fragment1, null);
//[1]找到按钮 设置点击事件
view.findViewById(R.id.btn_update).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//[2]修改fragment2里面的内容 通过fragment的公共桥梁 --->activity
Fragment2 fragment2 = (Fragment2) getActivity().getFragmentManager().findFragmentByTag("f2");
fragment2.updateText("哈哈哈呵呵");
}
});
return view;
}
}
Fragment2
public class Fragment2 extends Fragment {
private TextView tv_content;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment2, null);
//[1]找到tv
tv_content = (TextView) view.findViewById(R.id.tv_content);
return view;
}
//修改textview的内容
public void updateText(String content){
tv_content.setText(content);
}
}
AutoCompleteTextView
示例
<AutoCompleteTextView
android:id="@+id/actv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="1"
/>
代码
public class MainActivity extends Activity {
//模拟actv这个控件要显示的数据
private String[] COUNTRIES = new String[] {
"laofang", "laoli", "laozhang", "laobi", "laowang","aa","abb","ccc"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]找到控件
AutoCompleteTextView actv = (AutoCompleteTextView) findViewById(R.id.actv);
//[2]actv这个控件显示数据的原理和listview一样 需要一个数据适配器
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, COUNTRIES);
//[3]显示数据
actv.setAdapter(adapter);
}
}
动画
Android 3.0 以前,Android 支持两种动画模式,tween animation,frame animation
在android3.0 中又引入了一个新的动画系统:property animation
帧动画Frame Animation
Frame Animation(帧动画):创建一个Drawable 序列,这些Drawable 可以按照指定的时间间隔一个一个的显示,也就是顺序播放事先做好的图像。
- 将准备好的图片文件放到res/drawable-hdpi 目录中。
- 在项目的res 目录下创建文件夹drawable,然后在文件夹下面定义动画XML 文件,文件名称可以自定义,例如frame_anim.xml。
- 打开创建好的xml 文件,在里面添加根节点,
- 可以在此根节点中设置属性”android:oneshot”来控制动画只播放一次,否则系统将默认持续播放。在根节点 下为帧动画的每幅图片添加一个 节点, 节点的”android:drawable”属性是图片的资源id,”android:duration”属性指定图片展示的时间(一般每秒展示5-8 张图片就可以感受到动画的效果)。
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true" >
<item
android:drawable="@drawable/a1"
android:duration="200">
</item>
<item
android:drawable="@drawable/a2"
android:duration="200">
</item>
</animation-list>
- 在动画start()之前要先stop(),不然在第一次动画之后会停在最后一帧,这样动画就只会触发一次。
- 最后一点是SDK 中提到的, 不要在onCreate 中调用start , 因为AnimationDrawable 还没有完全跟Window 相关联,如果想要界面显示时就开始动画的话,可以在onWindowFoucsChanged()中调用start()。
代码
public class MainActivity extends Activity {
private ImageView iv;
private AnimationDrawable animationDrawable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
iv.setImageResource(R.drawable.frame_anim);
animationDrawable = (AnimationDrawable) iv.getDrawable();
}
public void startAnimation(View view) {// 点击按钮调用此方法
if (animationDrawable.isRunning())
animationDrawable.stop();
animationDrawable.start();
}
}
补间(渐变)动画 TweenAnimation
View Animation(Tween Animation):补间动画,给出两个关键帧,通过一些算法将给定属性值在给定的时间内在两个关键帧间渐变。
渐变包括:包括平移、缩放、旋转、改变透明度
特性:
动画效果不会改变控件真实的坐标
只能应用于View 对象,而且只支持一部分属性,如支持缩放旋转而不支持背景颜色的改变。
- 使用代码实现补间动画
常用的方法
Animation:
setDuration 设置动画的执行时间
setRepeatCount 设置动画的重复次数
setRepeatMode 指定重复的模式(如:反转)
setFillAfter 指示动画指定完毕之后控件的状态是否停留在动画停止的时候
setAnimationListener 设置动画的事件监听器
ImageView:
startAnimation(Animation a) 让ImageView 执行某动画
示例代码
public class MainActivity extends Activity {
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 这个控件用来执行动画
iv = (ImageView) findViewById(R.id.iv);
iv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "你点不到我", 1).show();
}
});
}
// 点击按钮 实现透明效果
public void click1(View v) {
//创建透明动画 1.0意味着完全不透明 0.0意外者完全透明
AlphaAnimation aa = new AlphaAnimation(1.0f, 0.0f);
aa.setDuration(2000); //设置动画执行的时间
aa.setRepeatCount(1); //设置动画重复的次数
aa.setRepeatMode(Animation.REVERSE); //设置重复的模式
//开始执行动画
iv.startAnimation(aa);
}
// 点击按钮 实现旋转效果
public void click2(View v) {
//fromDegrees 开始角度 toDegrees 结束的角度
// RotateAnimation ra = new RotateAnimation(0, 360);
RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
ra.setDuration(2000); //设置动画执行的时间
ra.setRepeatCount(1); //设置动画重复的次数
ra.setRepeatMode(Animation.REVERSE); //设置重复的模式
//开始执行动画
iv.startAnimation(ra);
}
// 点击按钮 实现缩放效果
public void click3(View v) {
ScaleAnimation sa = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
sa.setDuration(2000); //设置动画执行的时间
sa.setRepeatCount(1); //设置动画重复的次数
sa.setRepeatMode(Animation.REVERSE); //设置重复的模式
//开始执行动画
iv.startAnimation(sa);
}
// 点击按钮 实现平移效果
public void click4(View v) {
TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.2f);
ta.setDuration(2000); //设置动画执行的时间
ta.setFillAfter(true);//当动画结束后 停留在结束的位置上
//开始执行动画
iv.startAnimation(ta);
}
//点击按钮 让动画一起执行
public void click5(View v) {
//创建动画的合集
AnimationSet set = new AnimationSet(true);
AlphaAnimation aa = new AlphaAnimation(1.0f, 0.0f);
aa.setDuration(2000); //设置动画执行的时间
aa.setRepeatCount(1); //设置动画重复的次数
aa.setRepeatMode(Animation.REVERSE); //设置重复的模式
RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
ra.setDuration(2000); //设置动画执行的时间
ra.setRepeatCount(1); //设置动画重复的次数
ra.setRepeatMode(Animation.REVERSE); //设置重复的模式
ScaleAnimation sa = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
sa.setDuration(2000); //设置动画执行的时间
sa.setRepeatCount(1); //设置动画重复的次数
sa.setRepeatMode(Animation.REVERSE); //设置重复的模式
//添加动画
set.addAnimation(aa);
set.addAnimation(ra);
set.addAnimation(sa);
//执行动画
iv.startAnimation(set);
}
}
- 使用XML实现补间动画
如果使用xml方式定义补间动画 要在res下创建一个anim目录
alpha 透明度
<?xml version="1.0" encoding="utf-8"?>
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="2000"
android:repeatCount="1"
android:repeatMode="reverse"
xmlns:android="http://schemas.android.com/apk/res/android">
</alpha>
rotate 旋转
<?xml version="1.0" encoding="utf-8"?>
<rotate
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="0"
android:toDegrees="360"
android:repeatMode="reverse"
android:repeatCount="1"
android:duration="2000"
xmlns:android="http://schemas.android.com/apk/res/android">
</rotate>
scale 缩放
<?xml version="1.0" encoding="utf-8"?>
<scale
android:fromXScale="1.0"
android:toXScale="2.0"
android:fromYScale="1.0"
android:toYScale="2.0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="1"
android:repeatMode="reverse"
android:duration="2000"
xmlns:android="http://schemas.android.com/apk/res/android">
</scale>
translate 位移
<?xml version="1.0" encoding="utf-8"?>
<translate
android:fromXDelta="0%p"
android:toXDelta="0%p"
android:fromYDelta="0%p"
android:toYDelta="20%p"
android:fillAfter="true"
android:duration="2000"
xmlns:android="http://schemas.android.com/apk/res/android">
</translate>
集合 set
<?xml version="1.0" encoding="utf-8"?>
<set>
<!-- 属性略-->
<alpha></alpha>
<rotate></rotate>
<translate></translate>
<scale> </scale>
</set>
调用
Animation aa = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.alpha);
//开始执行动画
iv.startAnimation(aa);
属性动画 Property Animation
属性动画会改变控件真实的坐标
如果使用xml方式定义属性动画 要在res下创建一个animator目录
代码
public class MainActivity extends Activity {
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//加载布局
setContentView(R.layout.activity_main);
//作用 执行动画
iv = (ImageView) findViewById(R.id.iv);
//给iv设置了一个监听事件
iv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "你点不到我", 0).show();
}
});
//
// iv.setTranslationX(translationX)
// iv.setScaleX(scaleX)
// iv.setAlpha(alpha)
// iv.setro
}
//位移动画
public void translate(View v){
//创建属性动画
/**
* target 执行的目标 谁执行动画
* propertyName 属性名字 The name of the property being animated.
* float... values 可变参数
*/
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 10, 50,20,150);
oa.setDuration(2000);
oa.start(); //开始动画
}
//缩放动画
public void scale(View v){
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "scaleY", 0.1f, 2, 1, 2);
oa.setDuration(2000);
oa.start();
}
//实现透明的效果
public void alpha(View v){
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "alpha", 0, 0.5f, 0, 1,0,1);
oa.setDuration(2000);
oa.start();
}
//实现旋转的效果
public void rotate(View v){
// ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotation", 0, 180, 90, 360);
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotationY", 0, 180, 90, 360);
oa.setDuration(2000);
oa.start();
}
//一起飞
public void fly(View v){
AnimatorSet as = new AnimatorSet();
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 10, 50, 20, 100);
ObjectAnimator oa2 = ObjectAnimator.ofFloat(iv, "scaleY", 0.1f, 2, 1, 2);
ObjectAnimator oa3 = ObjectAnimator.ofFloat(iv, "alpha", 0, 0.5f, 0, 1);
ObjectAnimator oa4 = ObjectAnimator.ofFloat(iv, "rotationY", 0, 180, 90, 360);
as.setDuration(2000);
as.setTarget(iv);
//往集合中添加动画
//挨个飞
as.playSequentially(oa, oa2, oa3, oa4);
//一起飞
// as.playTogether(oa, oa2, oa3, oa4);
as.start();
}
//使用xml的方式创建属性动画
public void playxml(View v){
ObjectAnimator oa = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.oanimator);
//设置执行目标
oa.setTarget(iv);
oa.start();//开始执行
}
}
xml实现
<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android" >
<objectAnimator
android:propertyName="translationX"
android:duration="2000"
android:valueFrom="10"
android:valueTo="100"></objectAnimator>
</animator>
通知栏
通知用于在状态栏显示消息,消息到来时以图标方式表示,
如果需要查看消息,可以拖动状态栏到屏幕下方即可查看消息,
在Android 中通过通知管理器NotificationManager 来发出或关闭一个通知。
- 若设置了弹出通知会有声音/震动/亮灯的效果,注意添加对应权限,否则会抛错比如,设置震动需加权限android.permission.VIBRATE
- 获取延期意图PendingIntent 时,封装的意图对象必须采用隐式的方式
- startForeground(id, notification);可以提升进程优先级
public class MainActivity extends Activity {
private NotificationManager nm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]获取NotificationManager 的实例
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
// 点击按钮发送一条通知
public void click1(View v) {
//链式调用
/* Notification noti = new Notification.Builder(this)
.setContentTitle("我是大标题")
.setContentText("我是标题的内容")
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher))
.build();*/
//兼容低版本的写法 使用过时的方法
Notification notification = new Notification(R.drawable.ic_launcher, "我接收到了一条通知", System.currentTimeMillis());
//来一条通知 设置一下震动 让呼吸灯亮
notification.defaults = Notification.DEFAULT_ALL;
//设置通知不让清除
notification.flags = Notification.FLAG_NO_CLEAR;
//创建意图对象
Intent intent = new Intent();
//实现拨打电话的功能
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:"+119));
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
//点击通知对应的业务逻辑
notification.setLatestEventInfo(this, "小芳", "老地方见", pendingIntent);
//发出通知
nm.notify(10, notification);
}
// 点击按钮 取消发送一条通知
public void click2(View v) {
//取消通知
nm.cancel(10);
}
}