第35,36,37,38章
第35章 图形和定制视图
- 使用绘图api自定义控件
(1)先创建一个自定义类 MyView继承View类
public class MyView extends View {
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
}
}
我们需要三个构造方法和一个重写的draw()方法。
(2)在draw方法里面使用canvas进行绘制一个正方形,绘制需要一个Paint类作为工具,所以还需要定义一个Paint类。并为其指定颜色等属性。
public class MyView extends View {
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
p = new Paint();
p.setColor(Color.RED);
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.save();
canvas.translate(200,200);
canvas.rotate(degrees,50,50);
canvas.drawRect(0 ,0 ,100 ,100 ,p);
degrees ++;
canvas.restore();
invalidate();//清除并重绘
}
private Paint p;
private float degrees=0;
}
注意init()方法需要在三个构造方法中同时添加,保证无论执行哪个构造方法都执行此方法。
在draw方法里面的操作为事这个正方形进行旋转,这样旋转很耗资源,所以最好在里面加一个handle延时,使其刷新的频率没有这么快。
(3)在xml文件里面添加我们自定义的控件
<com.example.lzc.myapplication.MyView
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
这样运行程序我们就会看到一个旋转的正方形!
android的绘图api非常强大,能够绘制出任何图形,执行任何动画。
第36章 片段
Frgment概念:您可以将片段视为 Activity 的模块化组成部分,它具有自己的生命周期,能接收自己的输入事件,
并且您可以在 Activity 运行时添加或移除片段(有点像您可以在不同 Activity 中重复使用的“子 Activity”)。
FragmentManager manager = getFragmentManager();
FragmentTran tiontransaction = manager.beginTransaction();
transaction.add(R.id.layout,MyFragment.getInstance());
transaction.commit();
这是Fragment中经常使用的动态添加方法
而MyFragment采用单例模式,实现onCreateView()即可。
public class MyFragment extends Fragment {
private static MyFragment instance = new MyFragment();
public MyFragment() {
}
public static MyFragment getInstance() {
return instance;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.content_main, container,false);
}
}
transaction.addToBackStack(null);
在上例中,MyFragment会替换目前在 R.id.layout ID 所标识的布局容器中的任何片段(如有)。
通过调用 addToBackStack() 可将替换事务保存到返回栈,以便用户能够通过按返回按钮撤消事务并回退到上一片段。
如果您没有在执行移除片段的事务时调用 addToBackStack(),则事务提交时该片段会被销毁,用户将无法回退到该片段。 不过,如果您在删除片段时调用了 addToBackStack(),则系统会停止该片段,并在用户回退时将其恢复。这是一个按下物理返回键能够回退到原来状态的操作。
第37章 多面板布局
平板电脑的屏幕比手机要大一些,因此,在平板电脑上,可以显示比在手机上更多的信息。如果你打算编写一个要在两种类型的设备上显示得都不错的应用程序,通常的策略是支持两种布局。
在多面板的布局中,通常有一个足够大容纳两个面板的活动。可以使用相同的片段,这一次,当选中一个项的时候,它将会更新第2个片段,而不是开始另一个活动。
第38章 动画
属性动画系统是一个强大的框架,允许您使用几乎任何对象来作动画,甚至不用管它是否是绘制到屏幕上的一个View。其主要的原理就是通过定义动画以随时间变化而更改对象的某一属性。更简单地说,就是修改对象的某个属性值来实现动画的。
-
主要特征:
持续时间:您可以指定动画的持续时间。默认长度为300毫秒。
时间插值:您可以指定如何计算属性值作为动画当前已用时间的函数。
重复计数和行为:您可以指定是否在到达持续时间结束时重复动画以及重复动画的次数。您还可以指定是否要反向播放动画。将其设置为反向向前播放动画然后反复播放动画,直到达到重复次数。
动画设置:您可以将动画分组为一起或按顺序或在指定延迟后播放的逻辑集。
帧刷新延迟:您可以指定刷新动画帧的频率。默认设置为每10毫秒刷新一次,但应用程序刷新帧的速度最终取决于系统整体的繁忙程度以及系统为基础计时器提供服务的速度。 -
属性动画的过程:
(1) 动画是由许多的关键帧组成的,这是一个动画能够动起来的最基本的原理。
(2) 属性动画的主要组成是 PropertyValuesHolder,而 PropertyValuesHolder 又封装了关键帧。
(3) 动画开始后,其监听了 Choreographer 的 vsync,使得其可以不断地调用 doAnimationFrame() 来驱动动画执行每一个关键帧。
(4) 每一次的 doAnimationFrame() 调用都会去计算时间插值,而通过时间插值器计算得到 fraction 又会传给估值器,使得估值器可以计算出属性的当前值。
(5) 最后再通过 PropertyValuesHolder 所记录下的 Setter 方法,以反射的方式来修改目标属性的值。当属性值一帧一帧的改变后,形成连续后,便是我们所见到的动画。