For the following custom view : If stroke width is 0.01 then in Android M and and pre-M devices(ex:lollipop)
However If stroke width is 0.0f then in Android M and and pre-M devices(ex:lollipop)
Are there changes in stroke width in Android M that should be considered ? Is there a dependecy between Stroke style and stroke width ?
XML layout file:
<RelativeLayout 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="${relativePackage}.${activityClass}" >
<com.example.testspeedtestgui.TestView
android:id="@+id/testView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
/>
</RelativeLayout>
The code that implements speedometer.java is shown below :
package com.example.testspeedtestgui;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
public class TestView extends View {
private Paint outerLogoPaint;
private Paint centerOuterPaint;
private Path outerLogoEdge;
public TestView(Context context) {
super(context);
init(context);
}
public TestView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public TestView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
if(Build.VERSION.SDK_INT >= 11){
this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
initDrawingTools();
}
private void initDrawingTools() {
float strokeWidth=0.01f;
centerOuterPaint=new Paint();
centerOuterPaint.setAntiAlias(true);
centerOuterPaint.setColor(Color.BLUE);
centerOuterPaint.setStrokeWidth(strokeWidth);
centerOuterPaint.setStrokeCap(Paint.Cap.ROUND);
centerOuterPaint.setStyle(Paint.Style.STROKE);
RectF rect = new RectF();
float angle = getSemicircle(0.025f,0.5f,0.975f,0.5f,rect);
outerLogoEdge = new Path();
outerLogoEdge.moveTo(0.025f, 0.495f);
outerLogoEdge.arcTo(rect, angle, 180);
outerLogoEdge.moveTo(0.025f, 0.495f);
outerLogoEdge.lineTo(0.2f, 0.495f);
//Edge surrounding the lower part of outer semi circle(Logo edge Init) Logo edge Init
angle = getSemicircle(0.20f,0.5f,0.80f,0.5f,rect);
outerLogoEdge.arcTo(rect, angle, 180);
outerLogoEdge.moveTo(0.975f, 0.495f);
outerLogoEdge.lineTo(0.8f, 0.495f);
}
@Override
protected void onDraw(Canvas canvas) {
float scale = getWidth();
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(scale, scale);
drawLogo(canvas);
canvas.restore();
}
private void drawLogo(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.drawPath(outerLogoEdge, centerOuterPaint);
canvas.restore();
}
public float getSemicircle(float xStart, float yStart, float xEnd,
float yEnd, RectF ovalRectOUT) {
float centerX = xStart + ((xEnd - xStart) / 2);
float centerY = yStart + ((yEnd - yStart) / 2);
double xLen = (xEnd - xStart);
double yLen = (yEnd - yStart);
float radius = (float) (Math.sqrt(xLen * xLen + yLen * yLen) / 2);
RectF oval = new RectF(centerX - radius,
centerY - radius, centerX + radius,
centerY + radius);
ovalRectOUT.set(oval);
double radStartAngle = 0;
radStartAngle = Math.atan2(yStart - centerY, xStart - centerX);
float startAngle = (float) Math.toDegrees(radStartAngle);
return startAngle;
}
}
From the code TestView.java , centerOuterPaint.setStrokeWidth(strokeWidth) seems to cause the issue.
This is part of my app module and doesnt work on Android M. Tested on Nexus 5 running Android 6.0 .
source code at https://github.com/vyshas/SpeedometerTest
You have a couple of problems here:
canvas.save(Canvas.MATRIX_SAVE_FLAG);
Instead just use canvas.save()
.Note: if possible, use the parameter-less save(). It is simpler and faster than individually disabling the saving of matrix or clip with this method.
You are drawing everything at microscopic level in the range of (0...1). And then you are scaling it up nearly a hundred folds. This is bad. canvas.scale()
should not be used this way. Instead try drawing your elements at the normal scale itself.
You can use canvas.getHeight()
and canvas.getWidth()
to get the height
and width
of the view you have. Based on this detail, draw the arc
and the line
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With