Android学习第三周_自定义控件、Fragment和Handler

一、自定义控件

1.px、dp和sp的关系

px:像素点,在web前段会用得比较多,但是对于移动端尽量少用,因为手机的分辨率是不同的;
dp:跟像素密度有关,因为密度的不同会导致相同的px,而dp不同的情况;
sp:和dp类似,但是是用来修饰文字的;

关于三者的关系,可参照http://www.cnblogs.com/bluestorm/p/3640786.html这篇文章。

总结:在android中表示尺寸一般使用dp,在表示文字时使用sp,若要画一条细线,则可以使用px。

2.Inflater的基本知识
对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入;而对于一个已经加载了的界面,就可以使用Activity.findViewById()来获得其中的界面元素。

LayoutInflater是一个抽象类,public abstract class LayoutInflater extends Objects;

获得LayouInflater的三种方式:
1)LayoutInflater inflater = getLayoutInflater();
2)LayoutInflater localinflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
3.)LayoutInflater inflater = LayoutInflater.from(context);
我们主要使用的还是第二种方式,因为三种方式中归根结底,都是来自第二种。

3.View的工作过程

自定义控件的流程一般是按照下面的方法进行的:
1)自定义view的属性,创建attrs.xml,创建自己想要的属性;
2)在view的构造方法中获取我们自定义的控件;
3)重写onMesure(),以确定大小;
4)重写onLayout(),以确定位置;
5)重写onDraw(),以绘制图形;
6)invalidate,刷新。

自定义控件的三种方式:

  • 通过继承已有的控件来自定义控件
  • 通过继承一个布局文件来实现自定义控件
  • 通过继承View类来实现自定义控件

代码实现过程:
attrs.xml的创建

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CountProgressBar">
        <attr name="staticColor" format="color"/>
        <attr name="motionColor" format="color"/>
        <attr name="roundWidth" format="dimension"/>
        <attr name="textColor" format="color"/>
        <attr name="textSize" format="dimension"/>
        <attr name="max" format="integer"/>
        <attr name="textIsDisplayable" format="boolean"/>
        <attr name="speed" format="integer"/>
        <attr name="style">
            <enum name="STROKE" value="0"/>
            <enum name="FILE" value="1"/>
        </attr>
    </declare-styleable>
</resources>

在布局文件中声明自定义的view:

<com.cqupt.yang.countdown.CountProgressBar
            android:id="@+id/count_progress_bar"
            android:layout_centerInParent="true"
            android:text="20dp"
            android:progress="0"
            android:layout_width="250dp"
            android:layout_height="250dp"/>

在view的构造方法中获取我的自定义属性:

 /** *画笔对象的引用 */
    private Paint mPaint;

    /** *圆环静止时的颜色 */
    private int staticColor;
    /** *圆环运动是的颜色 */
    private int motionColor;
    /** * 圆环的宽度 */
    private float roundWidth;

    /** * 进度 */
    private int progress;
    /** * 最大进度 */
    private int max;

    /** *进度的风格 */
    private int style;
    public static final int STROKE = 0;
    public static final int FILL = 1;
    private Rect mRect;
    public CountProgressBar(Context context) {
        this(context,null);
    }

    public CountProgressBar(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CountProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }
    private void init(Context context,AttributeSet attrs) {
        mPaint = new Paint();
        mRect = new Rect();
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CountProgressBar);
        staticColor = a.getColor(R.styleable.CountProgressBar_staticColor, Color.WHITE);
        motionColor = a.getColor(R.styleable.CountProgressBar_motionColor, Color.parseColor("#DF413B"));
        roundWidth = a.getDimension(R.styleable.CountProgressBar_roundWidth, 8);
        max = a.getInteger(R.styleable.CountProgressBar_max, 60);
        style = a.getInt(R.styleable.CountProgressBar_style, 0);
        a.recycle();
    }

重写onDraw()方法,以绘制图形:

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /** * 画圆环 */
        int center = getWidth() / 2;   //获取圆心的x坐标
        int radius = (int)(center - roundWidth / 2);  //获取半径
        mPaint.setStrokeWidth(roundWidth);   //设置圆环的宽度
        mPaint.setColor(staticColor);
        mPaint.setAntiAlias(true);   //抗锯齿
        mPaint.setStyle(Paint.Style.STROKE);   //设置空心
        canvas.drawCircle(center, center, radius, mPaint); //画出圆环

        /** * 画圆环进度条 */
        mPaint.setStrokeWidth(roundWidth); //设置圆环的宽度
        mPaint.setColor(motionColor);  //设置进度的颜色
        RectF oval = new RectF(center - radius, center - radius, center
                + radius, center + radius);  //用于定义的圆弧的形状和大小的界限
        switch (style) {
            case STROKE:{
                mPaint.setStyle(Paint.Style.STROKE);
                canvas.drawArc(oval, 0, 360 * progress / max, false, mPaint);  //根据进度画圆弧
                break;
            }
            case FILL:{
                mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
                if(progress !=0)
                    canvas.drawArc(oval, 0, 360 * progress / max, true, mPaint);  //根据进度画圆弧
                break;
            }
        }
    }

到这里,就绘制出了一个圆环,在整个过程中,主要是对类的构造,view方法的重写,而且这里只用到了onDraw()方法。

二、Fragment的学习

1.什么是fragment?

  • Fragment是Activity中的一部分
  • 多个Fragment可以组合到一个Activity中
  • 多个Activity可以重用一个Fragment

总结:Fragment相当于模块化的一段activity,具有自己的生命周期,接受自己的事件。可以在activity运行时被添加或删除

2.Fragment的生命周期
通过图表的方式表示:
Android学习第三周_自定义控件、Fragment和Handler_第1张图片
在上面的流程图中,有很多地方和Activity的生命周期较为类似,但是也有很多不同之处。其中比较重要的是onCreateView。

三、Handler的学习

1.多线程和异步
多线程是指从软件或者硬件上实现多个线程并发执行的技术,一个进程中有多个任务,每个任务就是一个线程,当一起执行的时候就需要异步执行。

2.Handler的基本概念
Handler的主要作用是用来处理异步的消息,可以用来传递Message和Runnable的对象

3.Looper
消息泵,是消息队列(Message queue)的管理者,每一个looper对象和一个线程关联,looper负责取出消息,然后交给Handler处理。

4.Message
Message的主要方法如下:

  • obtainMessage()取得消息
  • sendMessage() 发送
  • handlerMessage() 处理消息

四、总结

本周主要学习了自定义控件、Fragment和Handler。在学习的过程中,学习自定义控件花费的时间比较多,所以在本文中页阐述得比较多,对于Fragment和Handler的学习用的时间就比较少了,所以只是简单的描述了下。但是,Fragment和Handler都是android中很重要的点,所以后面会花费一定的时间重新学习。

你可能感兴趣的:(android,学习笔记)