《Android 群英传》读书笔记:自定义 View -

发布时间:2021-11-28 13:36:01


转载请注明出处: http://blog.csdn.net/like_program/article/details/53241308



先看一下我们最终要实现的自定义 View。


最终效果图:



分析

首先,我们来分析下这个自定义 View 的组成:中间是一个圆形,圆形中显示的有文字,外圈是弧线。这样的话,就很简单了,我们只要分别绘制出圆,文字,弧线就行了。


新建项目

打开 Android Studio,新建 CircleProgressTest 项目。


新建 CircleProgressView.java,继承自 View,并实现 CircleProgressView.java 的三个构造方法,代码如下:


package com.example.circleprogresstest;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

/**
* 自定义 View 比例图
*/
public class CircleProgressView extends View {

public CircleProgressView(Context context) {
super(context);
}

public CircleProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}

1. 绘制圆

我们先把圆绘制出来。圆的半径是屏幕宽度的 1/4,原点坐标的 x,y 值大小都是屏幕宽度的 1/2。


修改 CircleProgressView.java,代码如下:


package com.example.circleprogresstest;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;

/**
* 自定义 View 比例图
*/
public class CircleProgressView extends View {

private Context mContext;

/**
* 圆的画笔
*/
private Paint mCirclePaint;

/**
* 圆心的 x,y 坐标
*/
private float mCircleXY;

/**
* 圆的半径
*/
private float mRadius;

/**
* 屏幕宽度
*/
private int mScreenWidth;

public CircleProgressView(Context context) {
super(context);
}

public CircleProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}

public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

mScreenWidth = getScreenWidth((Activity) mContext);

// 圆心的 x,y 坐标
mCircleXY = mScreenWidth / 2f;
// 圆的半径
mRadius = mScreenWidth / 4f;

initPaint();
}

/**
* 初始化画笔
*/
private void initPaint() {
// 圆的画笔
mCirclePaint = new Paint();
// 颜色
mCirclePaint.setColor(getResources().getColor(
android.R.color.holo_blue_bright));
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

// 绘制圆
canvas.drawCircle(
mCircleXY,
mCircleXY,
mRadius,
mCirclePaint);
}

/**
* 获取屏幕宽度
*
* @param activity
* @return
*/
private int getScreenWidth(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
return metrics.widthPixels;
}
}

由于圆的半径,圆心坐标都和屏幕宽度有关,所以我们定义了 getScreenWidth() 方法来获取屏幕宽度。


获取了屏幕宽度之后,我们就可以给圆的半径,圆心坐标赋值了。


接着我们初始化了画笔,给画笔设置了颜色,设置的天蓝色,这样,等会绘制出来的圆就是天蓝色。


圆的属性,画笔,都已经准备就绪了,接下来,我们就在 onDraw() 方法中画圆。


画圆使用的是 canvas.drawCircle() 方法,这里解释下 drawCircle() 的几个参数:


/**
* 绘制圆
*
* @param cx 圆心的 x 坐标
* @param cy 圆心的 y 坐标
* @param radius 圆的半径
* @param paint 画笔
*/
public void drawCircle (float cx, float cy, float radius, Paint paint)

这几个参数很好理解,就不多说了。


好了,圆已经画好了,我们把自定义的 View 放在布局文件中看看效果。在 CircleProgressView 上点击右键,选择 Copy Reference



复制 CircleProgressView 的全限定类名,拷贝到布局文件中,activity_main.xml 代码如下:



xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.circleprogresstest.MainActivity">

android:layout_width="match_parent"
android:layout_height="match_parent"/>

预览异常

我们预览一下自定义的 View。嗯,一片空白?还报异常?



报的异常是:



java.lang.ClassCastException: com.android.layoutlib.bridge.android.BridgeContext cannot be cast to android.app.Activity



大意是 BridgeContext 这个 Context 无法转换为 Activity。


回忆一下刚才我们在什么地方使用了 Activity,嗯,是获取屏幕宽度的时候:


/**
* 获取屏幕宽度
*
* @param activity
* @return
*/
private int getScreenWidth(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
return metrics.widthPixels;
}

代码好像没什么问题。


异常说,Context 无法转换为 Activity,再看下我们在什么地方转换的 Activity,嗯,是调用 getScreenWidth() 方法获取屏幕宽度的时候:


mScreenWidth = getScreenWidth((Activity) mContext);

问题应该就是出在这了。在这个地方,我们把 mContext 转换为 Activity。


既然 Android Studio 说这个地方有问题,那我们就仔细分析一下,我们是在 MainActivity 中实例化了布局文件,自定义 View 又写在了布局文件中,那么实例化自定义 View 时,传进来的 Context 应该就是 MainActivity。


MainActivity 继承自 AppCompatActivity,AppCompatActivity 最终还是继承自 Activity,那么我们把 MainActivity 转换成 Activity 。。。


Fuck!有问题吗?


反正我没发现。


不管了,先跑一下,万一能跑起来呢。


运行一下程序:



看来我的代码写的没错。Fuck the Android Studio!



那刚才到底是什么问题呢,我们 StackOverFlow 一波~~


How to fix “java.lang.ClassCastException: com.android.layoutlib.bridge.android.BridgeContext cannot be cast to android.app.Activity” exception


这个回答,貌似也不能解决我们的问题,但是有一段对话引起了我们的注意:



大意是:如果代码中有什么地方用到了 activity,就把那段代码写在 if (!View.isInEditMode()) {} 语句中。


我们看下 View.isInEditMode() 这个方法的 api:



Indicates whether this View is currently in edit mode. A View is usually in edit mode when displayed within a developer tool. For instance, if this View is being drawn by a visual user interface builder, this method should return true. Subclasses should check the return value of this method to provide different behaviors if their normal behavior might interfere with the host environment. For instance: the class spawns a thread in its constructor, the drawing code relies on device-specific features, etc. This method is usually checked in the drawing code of custom widgets.
Returns
True if this View is in edit mode, false otherwise.



大意是:如果当前处于编辑器环境中,比如 Android Studio,那么 isInEditMode() 返回值就是true。


那么,为什么要使用这个方法呢?根据我在网上查的资料,有一种说法是:



如果在自定义控件的构造函数或者其他绘制相关地方使用系统依赖的代码,会导致可视化编辑器无法报错并提示。



嗯,那我们就修改下 CircleProgressView.java 的 onMeasure() 方法,代码如下:


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

// 获取屏幕宽度
if (!isInEditMode()) {
mScreenWidth = getScreenWidth((Activity) mContext);
} else {
// 这里填写你自己手机或模拟器的屏幕宽度
mScreenWidth = 768;
}
// mScreenWidth = getScreenWidth((Activity) mContext);

// 圆心的 x,y 坐标
mCircleXY = mScreenWidth / 2f;
// 圆的半径
mRadius = mScreenWidth / 4f;

initPaint();
}

由于在 Android Studio 中预览布局文件,不会执行 if (!isInEditMode()) 中的逻辑,那我们就要手动给 mScreenWidth(屏幕宽度)赋值了。这里我的模拟器的分辨率是 768 X 1280。所以我就直接给 mScreenWidth 赋值 768。


然后,我们 Rebuild 一下项目。



再预览一下布局文件,可以看到,圆已经成功的显示出来了。



绘制文字

圆已经成功的绘制出来,那么接下来我们就来绘制文字,在绘制文字之前,先要给大家普及一个概念:基线


什么是基线?

引用下 自定义控件之绘图篇( 五):drawText()详解 的内容:


小时候,我们在刚开始学*写字母时,用的本子是四线格的,我们必须把字母按照规则写在四线格内。
比如:



那么问题来了,在canvas在利用drawText绘制文字时,也是有规则的,这个规则就是基线!
我们先来看一下什么是基线:



基线就是四线格中的第三条线!


canvas.drawText() 方法与基线

绘制文字,需要调用 canvas.drawText() 这个方法,那我们来看下 canvas.drawText() 这个方法:


/**
* 绘制文字
*
* @param text 要绘制的文字内容
* @param x 要绘制文字的原点的 x 坐标
* @param y 要绘制文字的原点的 y 坐标
* @param paint 画笔
*/
public void drawText(String text, float x, float y, Paint paint)

上面这个构造函数是最常用的 drawText 方法,传进去一个 String 对象就能画出对应的文字。但这里有两个参数需要非常注意,文字原点的 x 坐标和 y 坐标 。很多同学可能会认为,这里传进去的原点参数 (x,y) 是绘制文字所在矩形的左上角的点。但实际上并不是!比如,我们上面如果要画 “like_program’s blog” 这几个字,这个原点坐标应当是下图中绿色小点的位置:



一般而言,(x,y) 所代表的位置是所画图形对应的矩形的左上角点。但在 drawText() 中是非常例外的,y 所代表的是基线的位置!


嗯,相信文字原点的概念,大家已经清楚了。


清楚了原点的概念,后面也就好办了。修改 CircleProgressView.java,代码如下:


package com.example.circleprogresstest;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;

/**
* 自定义 View 比例图
*/
public class CircleProgressView extends View {

......

/**
* 文字的画笔
*/
private Paint mTextPaint;

/**
* 绘制的文字
*/
private String mShowText = "Android Skill";

/**
* 文字的大小
*/
private int mShowTextSize = 50;

public CircleProgressView(Context context) {
super(context);
}

public CircleProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}

public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

......

/**
* 初始化画笔
*/
private void initPaint() {
......

// 文字的画笔
mTextPaint = new Paint();
// 颜色
mTextPaint.setColor(Color.BLACK);
// 文字大小
mTextPaint.setTextSize(mShowTextSize);
// 文本对齐
mTextPaint.setTextAlign(Paint.Align.CENTER);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

// 绘制圆
canvas.drawCircle(
mCircleXY,
mCircleXY,
mRadius,
mCirclePaint);

// 绘制文字
canvas.drawText(
mShowText,
0,
mShowText.length(),
mCircleXY, mCircleXY + mShowTextSize / 4,
mTextPaint);
}

......
}

我们初始化了文字的画笔,并设置了一些属性,比如画笔颜色,文字大小,文字内容,文本对齐方式。然后调用了 canvas.drawText() 来绘制文字。这里,我们来看下这里我们调用的 canvas.drawText() 方法的各个参数是什么意思:


/**
* 绘制文字
*
* @param text 要绘制的文字内容
* @param start 要绘制的文字中第一个字符的索引
* @param end 要绘制的文字中最后一个字符的索引是 (end - 1)
* @param x 要绘制文字的原点的 x 坐标
* @param y 要绘制文字的原点的 y 坐标
* @param paint 画笔
*/
public void drawText (String text, int start, int end, float x, float y, Paint paint)

参数意思很好懂,就不多说了。


好了,运行一下程序:



嗯,文字也已经成功显示出来了。


关于 setTextAlign() 方法

不知道大家注意到没有,刚才设置文本对齐的时候,我们调用了 setTextAlign() 方法,并传入了 Paint.Align.CENTER ,让文字的显示效果是水*居中。


那么,我想问一下,如果我传入 Align.LEFT ,文字会怎样放置?有的同学可能会想,这还不简单,当然是和屏幕左边缘对齐了。


真的是这样吗?



我们修改下代码:


// mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTextAlign(Paint.Align.LEFT);

运行一下程序:



咦?什么情况?怎么跑到右边去了,也没有和屏幕右边缘对齐。


我们查看下 setTextAlign 的 api:



Set the paint’s text alignment. This controls how the text is positioned relative to its origin. LEFT align means that all of the text will be drawn to the right of its origin (i.e. the origin specifieds the LEFT edge of the text) and so on.



大意是:设置绘制文字的对齐方式,控制绘制文字如何相对于文字原点的位置定位,如果是 LEFT,表示文字的左边缘和原点对齐。


原来,这里 Align.LEFT 的意思并不是和屏幕左边缘对齐,而是文字的左边缘和原点对齐,也就是原点在文字的左边(原点即上面图片中的绿色小点),我们设置的原点的 x 坐标是在屏幕中间,原点又在文字的左边,那文字自然就跑到屏幕右边了。


那这样的话,如果设置成 Align.RIGHT,那么原点就会在文字的右边。文字就会跑到屏幕左边。为了验证我们的猜想,修改下代码:


// mTextPaint.setTextAlign(Paint.Align.CENTER);
// mTextPaint.setTextAlign(Paint.Align.LEFT);
mTextPaint.setTextAlign(Paint.Align.RIGHT);

运行一下程序:



果然,文字跑到屏幕左边了。


绘制弧形

好了,圆和文字我们都绘制出来了,只剩弧形了。


Android 给我们提供了 canvas.drawArc() 来绘制弧形。我们来看下 canvas.drawArc() 方法的各个参数意思:


/**
* 绘制圆弧
*
* @param oval 椭圆的边界,用来定义弧形的形状和大小
* @param startAngle 圆弧的起始角度
* @param sweepAngle 圆弧扫过的角度
* @param useCenter 这个参数如果为 true,就把椭圆的中心包括在圆弧中
* @param paint 画笔
*/
public void drawArc (RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)

这个方法参数有点不好理解,所以详细解释下:


第一个参数 oval

看上去我们要传入一个椭圆参数,但是看下 api:



我们发现,这个椭圆参数居然是矩形类型。换句话说,我们传进去一个矩形,然后系统会使用矩形的内切椭圆来定义弧形的形状和大小。


内切椭圆。。。



估计很多人的数学知识都早已还给数学老师了,没事,这里我准备了两张图,来帮助大家理解:



内切椭圆就是矩形里面的那个椭圆。我们可以看出,只要一个矩形的形状和大小确定下来了,那么它的内切椭圆也就确定下来了。


所以呢,我们创建一个矩形传入 canvas.drawArc() 方法,系统就会使用这个矩形的内切椭圆的边界来确定弧形的形状和大小。


第二个参数 startAngle 和第三个参数 sweepAngle

圆弧的起始角度 startAngle 和圆弧扫过的角度 sweepAngle


这尼玛又用到数学知识了:*面直角坐标系。这里我也准备了一张图,来解释坐标系的角度:



第四个参数 useCenter

这个参数如果为 true,就把椭圆的中心包括在圆弧中。


听不懂是吧?听不懂就对了,我特么自己都听不懂,Fuck!所以我们直接看图:



最后一个参数 paint

不解释。


好了,接下来我们就来绘制圆弧。修改 CircleProgressView.java,代码如下:


package com.example.circleprogresstest;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;

/**
* 自定义 View 比例图
*/
public class CircleProgressView extends View {

......

/**
* 圆弧的画笔
*/
private Paint mArcPaint;

/**
* 圆弧扫过的角度
*/
private float sweepAngle;

/**
* 矩形,用来辅助绘制圆弧
*/
private RectF mRectF;

public CircleProgressView(Context context) {
super(context);
}

public CircleProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}

public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

......

// 圆弧扫过的角度,360 度的 66%
sweepAngle = 66 / 100f * 360f;

initPaint();
}

/**
* 初始化画笔
*/
private void initPaint() {
......

// 弧形的画笔
mArcPaint = new Paint();
// 颜色
mArcPaint.setColor(getResources().getColor(
android.R.color.holo_blue_bright));
// 描边
mArcPaint.setStyle(Paint.Style.STROKE);
// 描边宽度
mArcPaint.setStrokeWidth(mScreenWidth * 0.1f);

// 创建一个矩形,用来辅助绘制圆弧
mRectF = new RectF(
mScreenWidth * 0.1f,
mScreenWidth * 0.1f,
mScreenWidth * 0.9f,
mScreenWidth * 0.9f);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

// 绘制圆
canvas.drawCircle(
mCircleXY,
mCircleXY,
mRadius,
mCirclePaint);

// 绘制文字
canvas.drawText(
mShowText,
0,
mShowText.length(),
mCircleXY, mCircleXY + mShowTextSize / 4,
mTextPaint);

// 绘制圆弧
canvas.drawArc(
mRectF,
270,
sweepAngle,
false,
mArcPaint);
}

......
}

代码没什么好说的,嗯,再解释下关于创建矩形。矩形 RectF 的构造方法有四个参数,含义如下:


/**
* 创建矩形
*
* @param left 矩形左边缘的 x 坐标
* @param top 矩形上边缘的 y 坐标
* @param right 矩形右边缘的 x 坐标
* @param bottom 矩形下边缘的 y 坐标
*/
public RectF (float left, float top, float right, float bottom)

也很好懂,不多说。


运行一下程序:



好了,我们已经成功的把比例图绘制出来了。


绘制顺序

最后需要注意一下的是:在 onDraw() 方法中,canvas 绘制的图案是依次覆盖的。也就是说,如果你先画文字,再画圆,那么圆就会把文字覆盖掉,导致你在屏幕上看不到绘制的文字,我们来试验一下。


修改下 CircleProgressView.java 中的 onDraw() 方法,代码如下:


@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

// 先绘制文字
canvas.drawText(
mShowText,
0,
mShowText.length(),
mCircleXY, mCircleXY + mShowTextSize / 4,
mTextPaint);

// 再绘制圆
canvas.drawCircle(
mCircleXY,
mCircleXY,
mRadius,
mCirclePaint);

// 最后绘制圆弧
canvas.drawArc(
mRectF,
270,
sweepAngle,
false,
mArcPaint);
}

运行一下程序:



可以看到,屏幕上已经看不见文字了。


最后,贴上 CircleProgressView.java 的全部源码:


package com.example.circleprogresstest;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;

/**
* 自定义 View 比例图
*/
public class CircleProgressView extends View {

private Context mContext;

/**
* 圆的画笔
*/
private Paint mCirclePaint;

/**
* 圆心的 x,y 坐标
*/
private float mCircleXY;

/**
* 圆的半径
*/
private float mRadius;

/**
* 屏幕宽度
*/
private int mScreenWidth;

/**
* 文字的画笔
*/
private Paint mTextPaint;

/**
* 绘制的文字
*/
private String mShowText = "Android Skill";

/**
* 文字的大小
*/
private int mShowTextSize = 50;

/**
* 圆弧的画笔
*/
private Paint mArcPaint;

/**
* 圆弧扫过的角度
*/
private float sweepAngle;

/**
* 矩形,用来辅助绘制圆弧
*/
private RectF mRectF;

public CircleProgressView(Context context) {
super(context);
}

public CircleProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}

public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

// 获取屏幕宽度
if (!isInEditMode()) {
mScreenWidth = getScreenWidth((Activity) mContext);
} else {
// 这里填写你自己手机或模拟器的屏幕宽度
mScreenWidth = 768;
}
// mScreenWidth = getScreenWidth((Activity) mContext);

// 圆心的 x,y 坐标
mCircleXY = mScreenWidth / 2f;
// 圆的半径
mRadius = mScreenWidth / 4f;

// 圆弧扫过的角度,360 度的 66%
sweepAngle = 66 / 100f * 360f;

initPaint();
}

/**
* 初始化画笔
*/
private void initPaint() {
// 圆的画笔
mCirclePaint = new Paint();
// 颜色
mCirclePaint.setColor(getResources().getColor(
android.R.color.holo_blue_bright));

// 文字的画笔
mTextPaint = new Paint();
// 颜色
mTextPaint.setColor(Color.BLACK);
// 文字大小
mTextPaint.setTextSize(mShowTextSize);
// 文本对齐
// Align.CENTER 表示文字原点和文字中间对齐
mTextPaint.setTextAlign(Paint.Align.CENTER);
// Align.LEFT 表示文字原点和文字左边缘对齐
// mTextPaint.setTextAlign(Paint.Align.LEFT);
// Align.RIGHT 表示文字原点和文字右边缘对齐
// mTextPaint.setTextAlign(Paint.Align.RIGHT);

// 弧形的画笔
mArcPaint = new Paint();
// 颜色
mArcPaint.setColor(getResources().getColor(
android.R.color.holo_blue_bright));
// 描边
mArcPaint.setStyle(Paint.Style.STROKE);
// 描边宽度
mArcPaint.setStrokeWidth(mScreenWidth * 0.1f);

// 创建一个矩形,用来辅助绘制圆弧
mRectF = new RectF(
mScreenWidth * 0.1f,
mScreenWidth * 0.1f,
mScreenWidth * 0.9f,
mScreenWidth * 0.9f);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

// 绘制圆
// 第一个参数是 圆心的 x 坐标
// 第二个参数是 圆心的 y 坐标
// 第三个参数是 圆的半径
// 第四个参数是 画笔
canvas.drawCircle(
mCircleXY,
mCircleXY,
mRadius,
mCirclePaint);

// 绘制文字
// 第一个参数是 要绘制的文字内容
// 第二个参数是 要绘制的文字中第一个字符的索引
// 第三个参数是 要绘制的文字中最后一个字符的索引减去一
// 第四个参数是 要绘制文字的原点的 x 坐标
// 第五个参数是 要绘制文字的原点的 y 坐标
// 第六个参数是 画笔
canvas.drawText(
mShowText,
0,
mShowText.length(),
mCircleXY, mCircleXY + mShowTextSize / 4,
mTextPaint);

// 绘制圆弧
// 第一个参数是 椭圆的边界,用来定义弧形的形状和大小
// 第二个参数是 圆弧的起始角度
// 第三个参数是 圆弧扫过的角度
// 第四个参数是 这个参数如果为 true,就把椭圆的中心包括在圆弧中
// 第五个参数是 画笔
canvas.drawArc(
mRectF,
270,
sweepAngle,
false,
mArcPaint);
}

/**
* 获取屏幕宽度
*
* @param activity
* @return
*/
private int getScreenWidth(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
return metrics.widthPixels;
}
}

源码下载

相关文档

  • c++ mat赋值_Mat 的几种初始化和赋值方法
  • 猪肉馅怎么调好吃
  • 数字金字塔PTA
  • 学校特殊教育提升计划
  • 总务年度总结三篇
  • 决定命运的草棒
  • 别为不值得交的朋友多做投入
  • 安装Win10系统蓝屏错误代码0xc000000e怎么办
  • 2017年高考语文答题得分技巧
  • 走路初三的作文
  • 开发中遇到特别紧急的需求怎么办?
  • 盛开的希望高一作文
  • 李强说管理学习心得体会范文
  • 现代装饰设计彩铅设计简约风格手稿图
  • 中医怎么治疗牙神经痛
  • Unity数组Array
  • 最新会计面试问题及答案
  • 大学生职业规划书自我评价范文
  • 大学英语六级写作考易通
  • 公司经理致学校的感谢信精选多篇
  • 文明上网的方式
  • 猪肘怎么做比较好吃
  • java实现数组的冒泡排序、选择排序代码
  • HTML5:表格
  • 自身原因辞职报告
  • 从前有座灵剑山根据什么改编的从前有座灵剑山漫画在哪看
  • 办公室英语潜台词
  • linux proc 堆栈_资深程序员总结:分析Linux进程的6个方法,全都告诉你!
  • 家常炒西兰花要如何制作
  • 快手如何自动识别字幕
  • 猜你喜欢

  • 人教版七年级下册第二单元语文知识树
  • 欧空局“火星登陆器”和“火星电离层和测地实验”计划
  • 厨房美食菜谱:辣椒炒番茄的做法
  • 激战正酣的应用商店之争
  • 两岸关系转暖,海西迎来新的发展时期
  • 腾飞吧 祖国_小学作文
  • 【人教版】六年级下册数学单元四_3第3课时《图形的放大与缩小》教案设计
  • Dubbo Hessian序列化问题 参数为null
  • 幻想的哲学-初二作文
  • 2016年银行从业资格考试-《个人理财》考点重点汇总
  • 教训 初中作文【600字】
  • FDI对浙江技术创新的影响研究
  • 小学六年级话题作文:这些年,我们追过的零食
  • Fbipstn广播电视编辑记者资格证考试新闻业务模拟题
  • 《皇帝的新装》教学设计
  • 2019-2020学年西师大版小学数学五年级下册 2.4约分、通分 同步训练
  • 重庆市沙坪坝区如良建筑材料厂企业信用报告-天眼查
  • 年假和探亲假规定有没有冲突
  • 王者荣耀手柄好不好用
  • 地震要如何预测有哪些简单预测的方法
  • 学生演讲稿《健康了,才能快乐!》(完整版)
  • 苹果手机打开盲人模式了怎么关闭
  • 高档化纤面料项目投资建设规划立项报告
  • 现代企业管理的12件法宝(doc21)(1)
  • 3D小人 交流对话系列 图标 PPT素材 模板_10
  • 福州苏华商贸有限公司企业信用报告-天眼查
  • 城市管理执法工作存在的问题和几点建议
  • 2018年秋人教版九年级物理全册课件:21.3、4 广播、电视和移动通信 越来越宽的信息之路(共28张PPT)
  • 亲子教育-幼儿园小朋友新年贺词简短版【三篇】 精品
  • 【精品模板】大理学院毕业论文答辩PPT模板范本
  • 2-班组长一日管理
  • 笔记本电脑如何用优盘装系统
  • 军棋单挑阵法推荐
  • 头孢羟氨苄甲氧苄啶胶囊说明书
  • 扰性泵项目可行性研究报告(可编辑)
  • 山东省新泰二中2018_2019学年高二物理上学期第三次阶段性测试试题
  • 2 中级财务会计*题集(第1-3章*题答案)
  • cmd查看环境变量
  • 7年级暑假游记英语作文400字:A TRIP TO THE COUNTRY_初中作文
  • Java在线考试系统毕业设计说明书(含源文件)
  • 六年级英语上册期中考试试题
  • 小学语文作文加评语
  • 电脑版