由于公司做的Android第二版App改版用到了扇形图,折线图以及柱状图,所以,鄙人学习了一些画笔的使用。
首先,在一张canvas上作画,要确定下笔的位置,这时候需要获取画布的信息(如果没有对画布的宽高做限制,默认就是屏幕的宽高)
下面我们来探讨一下屏幕参数的获取:
1.通过WindowMananger和display
先说说WindowMananger,我的理解就是Android视图显示最底端的东西,Android的窗口机制基于WindowManager,而Activity,dialog以及popupwindow都是直接
添加到WindowManager上面的,所以说他们是同等级的,这就是为什么dialog以及popupwindow可以叠加或者悬浮在activity上的控件上面。Windowmanager的一端是view,
另一端就是屏幕了。当我们把View直接布局在WindowManager上面,就可以实现悬浮或者叠加的效果了。
Display类获取屏幕参数如下(在Activity中):
WindowManager wm = getWindowManager();
Display dp = wm.getDefaultDisplay();
int screenWith = dp.getHeight(); //已注销的方法
int screenHeight = dp.getWidth();
//可以通过下面的方法获取宽高
Point size = new Point();
dp.getSize(size);
int with = size.x;
int height = size.y;
不在Activity中则可以这样获取:
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); //当然在activity中也能用,只不过context要用当前的Activity来代替
Display dp = wm.getDefaultDisplay();
在这里要插一句,如果需要悬浮或者叠加在布局所有控件之上的,只需要wm.addView(view,layoutParames),就行了,具体的效果自己去体验一下,可以设透明,渐变等等。
2.通过DisplayMetrics来获取屏幕的参数
API:A structure describing general information about a display, such as its size, density, and font scaling.
在Android中的API介绍可以,这个类可以获取关于Display的相关信息,比如大小神马的。
DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm); //this指当前的Activity
int screentWith = dm.widthPixels;
int screenHeight = dm.heightPixels;
貌似这样用也行,具体要自己去试验一下:
DisplayMetrics dm = getResources().getDisplayMetrics(); //getResources获取当前View的上下文(Activity其实也可以看做一个View)
ScrHeight = dm.heightPixels;
ScrWidth = dm.widthPixels;
这两种方法要在setContentView之后调用才会返回值,否则返回空。这两种方法其实差不多,就是先获取WindowManager后再调用display或者displayMetrics保存屏幕的宽高,再通过方法获取。
3.还有一种方法是在画布上面获取(该画布是默认的全局)
int w = canvas.getWidth();
int h = canvas.getHeight();
一般view的宽高是不包括任务栏和状态栏的,所以view的宽高一般不等于canvas的宽高
在获取好屏幕的宽高之后,我们就可以开始画画了。
1.画笔初始化
Paint paintLine = new Paint();
paintLine.setStrokeWidth(1.5f); //设置画笔的宽度
paintLine.setColor(Color.WHITE); //设置画笔的颜色
PaintLine.setAntiAlias(true); //消除锯齿
//具体画笔的更多的方法,大家有兴趣自己去看Android的Api
2.设置画布
// 画布背景
canvas.drawColor(getResources().getColor(R.color.green_operate_bg));
3.画线
canvas.drawLine(startx, starty, endx, endy, paintLine); //(startX, startY)线条开始的坐标点,(endX, endY)线条结束的坐标点,注意:Android的坐标原点在左上角
//paintLine是线条自定义的画笔样式
4.画矩形
canvas.drawRect(left, top, right, bottom, paint); //左边,上边,右边,下边
<pre name="code" class="java">canvas.drawRect(r, paint); //r是Rect类,规定了矩形的四边
canvas.drawRect(rect, paint); //rect是RectF类,一样也规定了矩形的四边
5.画圆形
canvas.drawCircle(cirX, cirY, radius , Paint); //圆心位置(cirX, cirY),圆的半径radius
6.画文字
canvas.drawText(text, x, y, paint); //text文本显示内容,是个String,起始位置(x,y)
7.画圆弧
canvas.drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint);
1.oval :指定圆弧的外轮廓矩形区域。
2.startAngle: 圆弧起始角度,单位为度。
3.sweepAngle: 圆弧扫过的角度,顺时针方向,单位为度。
4.useCenter: 如果为True时,在绘制圆弧时将圆心包括在内,通常用来绘制扇形。
5.paint: 绘制圆弧的画板属性,如颜色,是否填充等。
8.画扇形
画扇形其实很简单,就是画两个圆,一大一小叠加,就可以了,如果要画扇形折线图则,需要用到圆弧,当然要包括圆心,填充不同的颜色就可以形成扇形折现图的效果。
// 在饼图中显示所占比例
canvas.drawArc(arcRF0, CurrPer, Percentage, true, PaintArc); //画实心的圆弧,0度在圆的右边,顺时针计算角度
//arcRFO
float arcLeft = cirX - radius;
float arcTop = cirY - radius;
float arcRight = cirX + radius;
float arcBottom = cirY + radius;
RectF arcRF0 = new RectF(arcLeft, arcTop, arcRight, arcBottom)
//画中间的小圆
canvas.drawCircle(cirX, cirY, radius * 5 / 7, PaintArc);
//这样形成扇形的效果
9.计算圆弧的坐标点
public class ChartCalc
{
//Position位置
private float posX = 0.0f;
private float posY = 0.0f;
public ChartCalc()
{
}
//依圆心坐标,半径,扇形角度,计算出扇形终射线与圆弧交叉点的xy坐标
public void CalcArcEndPointXY(float cirX, float cirY, float radius, float cirAngle){
//将角度转换为弧度
float arcAngle = (float) (Math.PI * cirAngle / 180.0);
//当angle = 90°时,radian = ∏ / 2 = ∏ * 90°/ 180°= ∏ * angle / 180°,
//当angle = 180°时,radian = ∏ = ∏ * 180°/ 180°= ∏ * angle / 180°,
//所以radian(弧度) = ∏ * angle / 180(1弧度是等于半径的圆弧对应的圆心角,1度是1/360圆心角)
if (cirAngle < 90) //直角的三角形斜边是半径
{
posX = cirX + (float)(Math.cos(arcAngle)) * radius;
posY = cirY + (float)(Math.sin(arcAngle)) * radius;
}
else if (cirAngle == 90)
{
posX = cirX;
posY = cirY + radius;
}
else if (cirAngle > 90 && cirAngle < 180)
{
arcAngle = (float) (Math.PI * (180 - cirAngle) / 180.0);
posX = cirX - (float)(Math.cos(arcAngle)) * radius;
posY = cirY + (float)(Math.sin(arcAngle)) * radius;
}
else if (cirAngle == 180)
{
posX = cirX - radius;
posY = cirY;
}
else if (cirAngle > 180 && cirAngle < 270)
{
arcAngle = (float) (Math.PI * (cirAngle - 180) / 180.0);
posX = cirX - (float)(Math.cos(arcAngle)) * radius;
posY = cirY - (float)(Math.sin(arcAngle)) * radius;
}
else if (cirAngle == 270)
{
posX = cirX;
posY = cirY - radius;
}
else
{
arcAngle = (float) (Math.PI * (360 - cirAngle) / 180.0);
posX = cirX + (float)(Math.cos(arcAngle)) * radius;
posY = cirY - (float)(Math.sin(arcAngle)) * radius;
}
}
//
public float getPosX() {
return posX;
}
public float getPosY() {
return posY;
}
}
10,既然说到这里,我就顺便说一下px和dip的单位换算的问题
px是单位像素,真实的物理像素
dip则是拉伸像素
public class ChangePXandDip {
Context context = null;
float value = 0.0f;
public ChangePXandDip(Context context, float value) {
super();
this.context = context;
this.value = value;
}
public void pxChangeDip(){
final float scale = context.getResources().getDisplayMetrics().density;
value =value / scale + 0.5f;
}
public void dipChangePx(){
final float scale = context.getResources().getDisplayMetrics().density;
value = value * scale + 0.5f;
}
public float getValue() {
return value;
}
}
用Paint中的measureText获取字符串的长度
paint.measureText(total+"¥")