Geekband003第三周笔记分享

来源:互联网 发布:javascript:alert 编辑:程序博客网 时间:2024/06/14 05:14

px dp sp 的区别

  1. px : 一个像素点 ,如手机分辨率320*480表示宽有320像素,高有480像素。
  2. dpi : dots per inch, 打印分辨率 (每英寸所能打印的点数,即打印精度)假如我们知道一部手机的分辨率是1080×1920,屏幕大小是5英寸,根据公式计算结果是440dpi。
    dp=dip(Density-independent pixels),基于屏幕物理分辨率一个抽象的单位,用于说明与密度无关的尺寸和位置。
    px = dp*dpi/160
    dp = px*160/dpi
    从公式可以看出,公式的由来是已160dpi的屏幕为基准,此时该屏幕1dp=1px。如果320dpi的屏幕上,公式推导可得1dp = 2px。
    dp更类似一个物理尺寸,比如一张宽和高均为100dp的图片在320×480和480×800的手机上“看起来”一样大。而实际上,它们的像素值并不一样。dp正是这样一个尺寸,不管这个屏幕的密度是多少,屏幕上相同dp大小的元素看起来始终差不多大。
  3. sp :Scale-independent Pixels - 和dp单位很像,不过sp可以通过用户设置的字体大小而缩放. 为了能够自适应屏幕密度和用户的设置,建议设置字体大小时候用sp.当安卓系统字号设为“普通”时,sp=dp.
    系统定义dpi图解
    这里写图片描述

Inflater
将xml布局解析成视图view
在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById()。不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化;而findViewById()是找xml布局文件下的具体widget控件(如Button、TextView等)。 具体作用: 1、对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入;

获得 LayoutInflater 实例的三种方式

1.LayoutInflater inflater = getLayoutInflater(); //调用Activity的getLayoutInflater()

2.LayoutInflater localinflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
3. LayoutInflater inflater = LayoutInflater.from(context);

这三种方式最终本质是都是调用的Context.getSystemService()。

style/theme
可以将共同的属性拿出来放在styles.xml文件中

自定义控件
自定义的控件继承自View,初始化代码应该使用如下形式

public class CircleBackgroundView extends View {    public CircleBackgroundView(Context context) {        this(context, null);    }    public CircleBackgroundView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public CircleBackgroundView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }}

之后在xml中跟正常控件一样使用就可以

对图像界面的刷新可以使用invalidate();

如下为画一个圆以及可以指定角度的圆弧的代码

@Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        // draw background circle        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setColor(Color.WHITE);        mPaint.setStrokeWidth(5);        mPaint.setAntiAlias(true);        mCircleRectf.set(getWidth()/32, getWidth()/32, getWidth()*31/32, getWidth()*31/32);        canvas.drawArc(mCircleRectf,0,360,false,mPaint);        // draw the red Arc        mPaint.setColor(ContextCompat.getColor(getContext(),R.color.red));        mPaint.setAntiAlias(true);        canvas.drawArc(mCircleRectf, 270, mAngle, false, mPaint);    }

如下为暂停按钮的代码

@Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        int width = getWidth();        int height = getHeight();        // draw red background circle        mPaint.setStyle(Paint.Style.FILL);        mPaint.setColor(ContextCompat.getColor(getContext(),R.color.red));        canvas.drawCircle(width/2,width/2,width/2,mPaint);        mPaint.setColor(Color.WHITE);        mPaint.setStrokeWidth(5);        canvas.drawLine(width*4/10, width*3/10, width*4/10, width*7/10,mPaint);        canvas.drawLine(width*6/10, width*3/10, width*6/10, width*7/10,mPaint);    }

如下为开始按钮的代码

@Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        int width = getWidth();        int height = getHeight();        // draw red background circle        mPaint.setStyle(Paint.Style.FILL);        mPaint.setColor(ContextCompat.getColor(getContext(),R.color.red));        canvas.drawCircle(width/2,width/2,width/2,mPaint);        mPaint.setColor(Color.WHITE);        mPaint.setStrokeWidth(5);        mPath.moveTo(width*4/10,width*3/10);        mPath.lineTo(width*3/4,width/2);        mPath.lineTo(width*4/10,width*7/10);        mPath.close(); // 使这些点构成封闭的多边形        canvas.drawPath(mPath, mPaint);    }

如下为清空按钮的代码

@Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        int width = getWidth();        int height = getHeight();        // draw red background circle        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setColor(Color.WHITE);        mPaint.setStrokeWidth(5);        mCircleRectf.set(width/8, width/8, width*7/8, width*7/8);        canvas.drawArc(mCircleRectf, 270, 315, false, mPaint);        canvas.drawLine(width/8,width/8,width*7/20,width*7/20,mPaint);    }

其效果如下图

Fragment
Fragment必须是依存与Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。官网这张图很好的说明了两者生命周期的关系:
这里写图片描述

使用Fragment最简单的一种方式,把Fragment当成普通的控件,直接写在Activity的布局文件中。步骤:
1、继承Fragment,重写onCreateView决定Fragemnt的布局
2、在Activity中声明此Fragment,就当和普通的View一样

如何管理Fragment?
查找Fragment
1. findFragmentById()
2. findFragmentByTag()
Fragment的后退
1. Fragment Stack
2. popBackStack()
3. addOnBackStackChangedListerner()
Fragment的管理
1. FragmentManager
2. FragmentTransaction
3. Add/Remove

Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。

Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。

MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。

Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。

Thread:线程,负责调度整个消息循环,即消息循环的执行场所。

在主线程中,使用handler很简单,new一个Handler对象实现其handleMessage方法,在handleMessage中
提供收到消息后相应的处理方法即可

新建message并通过handler发送消息代码

void startTimer() {        timer = new Timer();        timerTask = new TimerTask() {            @Override            public void run() {                timeMessage = timeHandler.obtainMessage();                timeMessage.what = START_MESSAGE_CODE;                timeHandler.sendMessage(timeMessage);            }        };        timer.schedule(timerTask,0,10);    }

在handler类中重写一个handlerMessage的函数进行处理message

@Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            MainActivity mainActivity = mainActivityWeakReference.get();            switch (msg.what) {                case START_MESSAGE_CODE:                    totalCentiSceond++;                    partCentiSecond++;                    mainActivity.repaint(totalCentiSceond);                    break;                case COUNT_MESSAGE_CODE:                    mainActivity.repaint(totalCentiSceond);                    mainActivity.addResult(partCentiSecond,totalCentiSceond);                    partCentiSecond = 0;                    break;                case CLEAR_MESSAGE_CODE:                    totalCentiSceond = 0;                    partCentiSecond = 0;                    mainActivity.repaint(0);                    mainActivity.clearResult();                    break;            }        }
1 0