I wrote a Compass example that came out of an Android application tutorial book and wrote the custom view, methods, and such, but nothing is being drawn on the screen when the app runs.
Here is the class:
package com.example.compass;
import android.view.View;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.accessibility.AccessibilityEvent;
public class CompassView extends View {
private float bearing;
private Paint markerPaint;
private Paint textPaint;
private Paint circlePaint;
private String northString;
private String eastString;
private String southString;
private String westString;
private int textHeight;
public CompassView(Context context) {
super(context);
initCompassView();
}
public CompassView(Context context, AttributeSet attrs) {
super(context, attrs);
initCompassView();
}
public CompassView(Context context, AttributeSet ats, int defaultStyle) {
super(context, ats, defaultStyle);
initCompassView();
}
protected void initCompassView() {
setFocusable(true);
Resources r = this.getResources();
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(r.getColor(R.color.background_color));
circlePaint.setStrokeWidth(1);
circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
northString = r.getString(R.string.cardinal_north);
eastString = r.getString(R.string.cardinal_east);
southString = r.getString(R.string.cardinal_south);
westString = r.getString(R.string.cardinal_west);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(r.getColor(R.color.text_color));
textHeight = (int)textPaint.measureText("yY");
markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
markerPaint.setColor(r.getColor(R.color.marker_color));
}
#Override
protected void onDraw(Canvas canvas) {
int mMeasuredWidth = getMeasuredWidth();
int mMeasuredHeight = getMeasuredHeight();
int px = mMeasuredWidth/2;
int py = mMeasuredHeight/2;
int radius = Math.min(px, py);
canvas.drawCircle(px, py, radius, circlePaint);
canvas.save();
canvas.rotate(-bearing, px, py);
int textWidth = (int) textPaint.measureText("W");
int cardinalX = px-textWidth/2;
int cardinalY = py-radius+textHeight;
for (int i = 0; i < 24; i++) {
canvas.drawLine(px, py-radius, px, py-radius+10, markerPaint);
canvas.save();
canvas.translate(0, textWidth);
if (i%6 == 0) {
String dirString = "";
switch (i) {
case(0):{
dirString = northString;
int arrowY = 2*textHeight;
canvas.drawLine(px, arrowY, px-5, 3*textHeight, markerPaint);
canvas.drawLine(px, arrowY, px+5, 3*textHeight, markerPaint);
break;
}
case(6): dirString = eastString; break;
case(12): dirString = southString; break;
case(18): dirString = westString; break;
}
canvas.drawText(dirString, cardinalX, cardinalY, textPaint);
}
else if (i%3==0) {
String angle = String.valueOf(i*15);
float angleTextWidth = textPaint.measureText(angle);
int angleTextX = (int)(px-angleTextWidth/2);
int angleTextY = py-radius+textHeight;
canvas.drawText(angle, angleTextX, angleTextY, textPaint);
}
canvas.restore();
canvas.rotate(15, px, py);
}
canvas.restore();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = measure(widthMeasureSpec);
int measuredHeight = measure(heightMeasureSpec);
int d = Math.min(measuredWidth, measuredHeight);
setMeasuredDimension(d, d);
}
private int measure(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getMode(measureSpec);
if (specMode == MeasureSpec.UNSPECIFIED) {
result = 200;
}
else {
result = specSize;
}
return result;
}
public void setBearing(float _bearing) {
bearing = _bearing;
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
}
public float getBearing() {
return bearing;
}
#SuppressWarnings("deprecation")
#Override
public boolean dispatchPopulateAccessibilityEvent(final AccessibilityEvent event) {
super.dispatchPopulateAccessibilityEvent(event);
if (isShown()) {
String bearingStr = String.valueOf(bearing);
if (bearingStr.length() > AccessibilityEvent.MAX_TEXT_LENGTH)
bearingStr = bearingStr.substring(0, AccessibilityEvent.MAX_TEXT_LENGTH);
event.getText().add(bearingStr);
return true;
}
else
return false;
}
}
I don't get any logcat errors; it does however display this (which might be relevant):
04-01 18:41:57.163: D/gralloc_goldfish(583): Emulator without GPU emulation detected.
However, after seeing this I added GPU emulation hardware to my emulator and selected the "Yes" option, but this message keeps showing up.
What could be the cause of nothing displaying on the screen? I can also post xml files if needed.
Figured out the cause: called getMode a second time instead of getSize... I feel dumb now.
Related
This is my code below but its not working. I am trying to draw a background image, and then have random sparkles and glitter effects randomly show on the screen. All I get is a black screen.
package com.griffslabs.glitterlwptest;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.service.wallpaper.WallpaperService;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import java.util.ArrayList;
import java.util.Random;
public class RainbowSparkleWallpaperService extends WallpaperService {
#Override
public Engine onCreateEngine() {
return new RainbowSparkleEngine();
}
class RainbowSparkleEngine extends Engine {
private ArrayList<Sparkle> sparkles = new ArrayList<>();
private ArrayList<GlitterTrail> glitterTrails = new ArrayList<>();
private Paint paint = new Paint();
private int sparkleSize = 5;
private int glitterTrailSize = 10;
private int sparkleSpeed = 5;
private int glitterTrailSpeed = 2;
private int width;
private int height;
private Random random = new Random();
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
this.width = width;
this.height = height;
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
int x = (int) event.getX();
int y = (int) event.getY();
sparkles.add(new Sparkle(x, y, sparkleSize, sparkleSpeed));
glitterTrails.add(new GlitterTrail(x, y, glitterTrailSize, glitterTrailSpeed));
}
private class DrawThread extends Thread {
private boolean running = false;
private SurfaceHolder surfaceHolder;
DrawThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
}
void setRunning(boolean running) {
this.running = running;
}
#Override
public void run() {
Canvas canvas;
while (running) {
canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
if (canvas != null) {
Rect frame = surfaceHolder.getSurfaceFrame();
onDraw(canvas, frame);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
public void onDraw(Canvas canvas, Rect frame) {
canvas.drawBitmap(getBackgroundImage(), null, frame, null);
for (int i = 0; i < sparkles.size(); i++) {
Sparkle sparkle = sparkles.get(i);
paint.setColor(sparkle.color);
canvas.drawCircle(sparkle.x, sparkle.y, sparkle.size, paint);
sparkle.update();
if (sparkle.y + sparkle.size < 0 || sparkle.y - sparkle.size > height) {
sparkles.remove(sparkle);
}
}
for (int i = 0; i < glitterTrails.size(); i++) {
GlitterTrail glitterTrail = glitterTrails.get(i);
paint.setColor(glitterTrail.color);
canvas.drawRect(glitterTrail.x, glitterTrail.y, glitterTrail.x + glitterTrail.size, glitterTrail.y + glitterTrail.size, paint);
glitterTrail.update();
if (glitterTrail.y + glitterTrail.size < 0 || glitterTrail.y - glitterTrail.size > height) {
glitterTrails.remove(glitterTrail);
}
}
}
private Bitmap getBackgroundImage() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap background = BitmapFactory.decodeResource(getResources(), R.drawable.background, options);
background = Bitmap.createScaledBitmap(background, width, height, true);
return background;
}
private class Sparkle {
int x;
int y;
int size;
int speed;
int color;
Sparkle(int x, int y, int size, int speed) {
this.x = x;
this.y = y;
this.size = size;
this.speed = speed;
this.color = getRandomColor();
}
void update() {
y -= speed;
}
int getRandomColor() {
int[] rainbowColors = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA};
return rainbowColors[random.nextInt(rainbowColors.length)];
}
}
private class GlitterTrail {
int x;
int y;
int size;
int speed;
int color;
GlitterTrail(int x, int y, int size, int speed) {
this.x = x;
this.y = y;
this.size = size;
this.speed = speed;
this.color = getRandomColor();
}
void update() {
y -= speed;
}
int getRandomColor() {
int[] rainbowColors = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA};
return rainbowColors[random.nextInt(rainbowColors.length)];
}
}
}
}
expecting it to work. I have tried almost everything and it just does not work. any input will be aprecciated.
I am making android custom view, which is supposed to be loading animation(spinning arc), my view allows developer to set background color and top color.
The problem is that when I draw light colored arc on top of black arc I can see just a little bit of those black pixels around my top arc.
This problem doesn't occur when anti aliasing is off, but that is not an option because it's just ugly then.
I have tried drawing it on bitmap but it doesn't help.
My temporary solution is to make top arc 1px wider than bottom arc, but I have this moment when I swap colors for cool animation and then it can be seen if you look closely.
custom_view
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import com.example.basil.expensemanager.R;
public class MyProgress extends View {
private int mxSize, mySize;
private Paint mPaint;
private Paint incomeAmountCirlce;
private Paint expenseAmountCirlce;
private Paint innerCirclePaint;
private Paint txtviewCirclePaint;
private float finishedStrokeWidth;
private float unfinishedStrokeWidth;
private float sweepAngle;
private int textColor;
private int expenseColor;
private int incomeColor;
private int strokeWidth;
private int textSize;
private String textContent;
private RectF finishedOuterRect = new RectF();
private RectF unfinishedOuterRect = new RectF();
public MyProgress(Context context) {
super(context);
/* init();*/
}
public MyProgress(Context context, AttributeSet attrs) {
super(context, attrs);
/* init();*/
}
public MyProgress(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
/* init();*/
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
}
public float getFinishedStrokeWidth() {
return finishedStrokeWidth;
}
public void setFinishedStrokeWidth(float finishedStrokeWidth) {
this.finishedStrokeWidth = finishedStrokeWidth;
}
public float getUnfinishedStrokeWidth() {
return unfinishedStrokeWidth;
}
public void setUnfinishedStrokeWidth(float unfinishedStrokeWidth) {
this.unfinishedStrokeWidth = unfinishedStrokeWidth;
}
public String getTextContent() {
return textContent;
}
public void setTextContent(String textContent) {
this.textContent = textContent;
}
public int getTextSize() {
return textSize;
}
public void setTextSize(int textSize) {
this.textSize = textSize;
}
public float getSweepAngle() {
return sweepAngle;
}
public void setSweepAngle(float sweepAngle) {
this.sweepAngle = sweepAngle;
}
public int getIncomeColor() {
return incomeColor;
}
public void setIncomeColor(int incomeColor) {
this.incomeColor = incomeColor;
}
public Integer getExpenseColor() {
return expenseColor;
}
public void setExpenseColor(int expenseColor) {
this.expenseColor = expenseColor;
}
public int getStrokeWidth() {
return strokeWidth;
}
public void setStrokeWidth(int strokeWidth) {
this.strokeWidth = strokeWidth;
}
public void init() {
txtviewCirclePaint = new Paint();
txtviewCirclePaint.setColor(getResources().getColor(getTextColor()));
txtviewCirclePaint.setTextSize(getTextSize());
txtviewCirclePaint.setFakeBoldText(true);
txtviewCirclePaint.setAntiAlias(true);
incomeAmountCirlce = new Paint();
incomeAmountCirlce.setColor(getResources().getColor(getIncomeColor()));
incomeAmountCirlce.setStyle(Paint.Style.STROKE);
incomeAmountCirlce.setAntiAlias(true);
finishedStrokeWidth = getFinishedStrokeWidth();
incomeAmountCirlce.setStrokeWidth(finishedStrokeWidth);
expenseAmountCirlce = new Paint();
expenseAmountCirlce.setColor(getResources().getColor(getExpenseColor()));
expenseAmountCirlce.setStyle(Paint.Style.STROKE);
expenseAmountCirlce.setAntiAlias(true);
unfinishedStrokeWidth = getUnfinishedStrokeWidth();
expenseAmountCirlce.setStrokeWidth(unfinishedStrokeWidth);
innerCirclePaint = new Paint();
innerCirclePaint.setColor(getResources().getColor(R.color.cardview_light_background));
innerCirclePaint.setAntiAlias(true);
}
#Override
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
float delta = Math.max(finishedStrokeWidth, unfinishedStrokeWidth);
finishedOuterRect.set(delta, delta, getWidth() - delta, getHeight() - delta);
unfinishedOuterRect.set(delta, delta, getWidth() - delta, getHeight() - delta);
float innerCircleRadius = (getWidth() - Math.min(finishedStrokeWidth, unfinishedStrokeWidth) + Math.abs(finishedStrokeWidth - unfinishedStrokeWidth)) / 2f;
canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, innerCircleRadius, innerCirclePaint);
canvas.drawArc(finishedOuterRect, 270, getSweepAngle(), false, incomeAmountCirlce);
canvas.drawArc(unfinishedOuterRect, 270 + getSweepAngle(), 360 - getSweepAngle(), false, expenseAmountCirlce);
float textHeight = txtviewCirclePaint.descent() + txtviewCirclePaint.ascent();
canvas.drawText(getTextContent(), (getWidth() - txtviewCirclePaint.measureText(getTextContent())) / 2.0f, (getWidth() - textHeight) / 2.0f, txtviewCirclePaint);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth / 2, parentHeight / 2);
// bounds.set(0, 0, MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
new RectF().set(0, 0, parentWidth / 4, parentHeight / 4);
}
}
i have done this on one of my project for showing total income and expense in progress bar hope this may help you , if you feel any difficulty comment below
In you activity use this to init view
public void init_decorate_progressbar() {
float val = calcalute_progressbar_data();
String totalPercent = "";
totalPercent = "" + (val / 3.6);
myProgressBar.invalidate();
myProgressBar.setExpenseColor(R.color.royalGreenDark);
myProgressBar.setIncomeColor(R.color.royalGreen);
myProgressBar.setFinishedStrokeWidth(30);
myProgressBar.setUnfinishedStrokeWidth(30);
myProgressBar.setTextColor(R.color.colorPrimaryDark);
myProgressBar.setTextSize(30);
if (totalPercent.equalsIgnoreCase("NaN")) {
myProgressBar.setSweepAngle(0);
myProgressBar.setTextContent("0%");
expenseMarkerLayout.setVisibility(View.GONE);
incomeMarkerLayout.setVisibility(View.GONE);
} else {
myProgressBar.setSweepAngle(val);
int incom = calculateIncomePercent();
myProgressBar.setTextContent("" + incom + "%");
txtIncomePercentMarker.setText("" + incom + "%");
int ex = calculateExpensePercent();
txtExpensePercentMarker.setText("" + ex + "%");
}
myProgressBar.init();
}
in your activity XML
<com.example.basil.expensemanager.SupportClasses.MyProgress
android:id="#+id/myProgressBar"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerHorizontal="true"
android:layout_below="#id/main_header"
android:layout_marginBottom="#dimen/activity_horizontal_margin"
android:layout_marginTop="#dimen/activity_horizontal_margin"
android:max="100"
android:progress="0" />
I'm using this library from GitHub: https://github.com/lzyzsd/CircleProgress
I put ArcProgress into my MainLayout. I'm trying to change values on the progress bar but I cannot not see on screen. If I check with mArcProgress.getProgress(); this get me the right value, but the bar is empty in screen and doesn't show any progress.
I was trying using:
mArcProgress.invalidate();
but doesnt work.
The only way I found was with:
finish();
startActivity(getIntent());
but works not as I expected, because the full screen start and seems like a blink.
Anyone know how from another activity, changes this View and make possible to see the changes when setting mArcProgress.setProgress(aNumber); ?
this is ArcProgressFuel
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
public class ArcProgressFuel extends View {
private Paint paint;
private RectF rectF = new RectF();
private float strokeWidth;
public int progress;
private int max;
private int finishedStrokeColor;
private int unfinishedStrokeColor;
private float arcAngle;
Path path;
MainPageFragment mMainPageFragment;
public static int fuel_to_show;
private float arcBottomHeight;
private final int default_finished_color = Color.WHITE;
private final int default_unfinished_color = Color.rgb(72, 106, 176);
private final float default_suffix_padding;
private final float default_stroke_width;
private final int default_max = 100;
private final float default_arc_angle = 360 * 0.5f; //0.8 for speed, 0.5 for fuel
private float default_text_size;
private final int min_size;
private static final String INSTANCE_STATE = "saved_instance";
private static final String INSTANCE_STROKE_WIDTH = "stroke_width";
public static String instance_progress = "progress";
private static final String INSTANCE_MAX = "max";
private static final String INSTANCE_FINISHED_STROKE_COLOR = "finished_stroke_color";
private static final String INSTANCE_UNFINISHED_STROKE_COLOR = "unfinished_stroke_color";
private static final String INSTANCE_ARC_ANGLE = "arc_angle";
private static final String INSTANCE_SUFFIX = "suffix";
public ArcProgressFuel(Context context) {
this(context, null);
}
public ArcProgressFuel(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ArcProgressFuel(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
min_size = (int) Utils.dp2px(getResources(), 100);
default_suffix_padding = Utils.dp2px(getResources(), 4);
default_stroke_width = Utils.dp2px(getResources(), 4);
TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArcProgress, defStyleAttr, 0);
initByAttributes(attributes);
attributes.recycle();
initPainters();
}
protected void initByAttributes(TypedArray attributes) {
finishedStrokeColor = attributes.getColor(R.styleable.ArcProgress_arc_finished_color, default_finished_color);
unfinishedStrokeColor = attributes.getColor(R.styleable.ArcProgress_arc_unfinished_color, default_unfinished_color);
arcAngle = attributes.getFloat(R.styleable.ArcProgress_arc_angle, default_arc_angle);
setMax(attributes.getInt(R.styleable.ArcProgress_arc_max, default_max));
setProgress(attributes.getInt(R.styleable.ArcProgress_arc_progress, 0));
strokeWidth = attributes.getDimension(R.styleable.ArcProgress_arc_stroke_width, default_stroke_width);
fuel_to_show=mMainPageFragment.carFuel;
setProgress(fuel_to_show); //Aca puedo modificar el valor
}
protected void initPainters() {
paint = new Paint();
paint.setColor(default_unfinished_color);
paint.setAntiAlias(true);
paint.setStrokeWidth(strokeWidth);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeCap(Paint.Cap.ROUND);
}
/* #Override
public void invalidate() {
initPainters();
super.invalidate();
postInvalidate();
}*/
public float getStrokeWidth() {
return strokeWidth;
}
public void setStrokeWidth(float strokeWidth) {
this.strokeWidth = strokeWidth;
this.invalidate();
}
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
this.progress = progress;
if (this.progress > getMax()) {
this.progress %= getMax();
}
invalidate();
}
public int getMax() {
return max;
}
public void setMax(int max) {
if (max > 0) {
this.max = max;
invalidate();
}
}
public int getFinishedStrokeColor() {
return finishedStrokeColor;
}
public void setFinishedStrokeColor(int finishedStrokeColor) {
this.finishedStrokeColor = finishedStrokeColor;
this.invalidate();
}
public int getUnfinishedStrokeColor() {
return unfinishedStrokeColor;
}
public void setUnfinishedStrokeColor(int unfinishedStrokeColor) {
this.unfinishedStrokeColor = unfinishedStrokeColor;
this.invalidate();
}
public float getArcAngle() {
return arcAngle;
}
public void setArcAngle(float arcAngle) {
this.arcAngle = arcAngle;
this.invalidate();
}
#Override
protected int getSuggestedMinimumHeight() {
return min_size;
}
#Override
protected int getSuggestedMinimumWidth() {
return min_size;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
rectF.set(strokeWidth / 2f, strokeWidth / 2f, width - strokeWidth / 2f, MeasureSpec.getSize(heightMeasureSpec) - strokeWidth / 2f);
float radius = width / 2f;
float angle = (360 - arcAngle) / 2f;
arcBottomHeight = radius * (float) (1 - Math.cos(angle / 180 * Math.PI));
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float startAngle = 90 - arcAngle / 2f; //270 for speed, 90 for fuel
float finishedSweepAngle = progress / (float) getMax() * arcAngle;
float finishedStartAngle = startAngle;
if(progress == 0) finishedStartAngle = 0.01f;
paint.setColor(unfinishedStrokeColor);
canvas.drawArc(rectF, startAngle, arcAngle, false, paint);
paint.setColor(finishedStrokeColor);
canvas.drawArc(rectF, finishedStartAngle, finishedSweepAngle, false, paint);
if(arcBottomHeight == 0) {
float radius = getWidth() / 2f;
float angle = (360 - arcAngle) / 2f;
arcBottomHeight = radius * (float) (1 - Math.cos(angle / 180 * Math.PI));
}
}
#Override
protected Parcelable onSaveInstanceState() {
final Bundle bundle = new Bundle();
bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());
bundle.putFloat(INSTANCE_STROKE_WIDTH, getStrokeWidth());
bundle.putInt(instance_progress, getProgress());
bundle.putInt(INSTANCE_MAX, getMax());
bundle.putInt(INSTANCE_FINISHED_STROKE_COLOR, getFinishedStrokeColor());
bundle.putInt(INSTANCE_UNFINISHED_STROKE_COLOR, getUnfinishedStrokeColor());
bundle.putFloat(INSTANCE_ARC_ANGLE, getArcAngle());
return bundle;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
if(state instanceof Bundle) {
final Bundle bundle = (Bundle) state;
strokeWidth = bundle.getFloat(INSTANCE_STROKE_WIDTH);
setMax(bundle.getInt(INSTANCE_MAX));
setProgress(bundle.getInt(instance_progress));
finishedStrokeColor = bundle.getInt(INSTANCE_FINISHED_STROKE_COLOR);
unfinishedStrokeColor = bundle.getInt(INSTANCE_UNFINISHED_STROKE_COLOR);
initPainters();
super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE));
return;
}
super.onRestoreInstanceState(state);
}
}
this is inside my MainLayout, this part I want to update:
<RelativeLayout
android:id="#+id/scale_gaz_inmain"
android:layout_width="#dimen/_57sdp"
android:layout_centerHorizontal="true"
android:layout_below="#+id/icon_gazinmain"
android:layout_height="#dimen/_60sdp"
>
<com.itelma.tele2.ArcProgressFuel
android:id="#+id/arc_progress2"
android:background="#android:color/transparent"
android:layout_width="match_parent"
android:scaleX="-1"
android:layout_height="match_parent"
custom:arc_progress="50"
custom:arc_unfinished_color="#color/mDark_gray"
custom:arc_finished_color="#color/colorApp"
custom:arc_max="100"/>
</RelativeLayout>
so in my main java file I have:
ArcProgressFuel mArcProgressFuel;
mArcProgressFuel=new ArcProgressFuel(this);
mArcProgressFuel.invalidate();
ok, I could resove it, with the following lines:
mArcProgressFuel=new ArcProgressFuel(this);
RelativeLayout relativeLayout2=(RelativeLayout)findViewById(R.id.speed_indicator);
View child = getLayoutInflater().inflate(R.layout.fragment_speed_indicator, null);
relativeLayout2.addView(child);
i have got some problem with my own progressbar.
When i click on dot they catch me.
I try do it something like that:
here is code:
package test.pionas.myapplication;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class PioArcCircle extends View {
private static final String TAG = PioArc.class.getSimpleName();
private static int INVALID_PROGRESS_VALUE = -1;
private float mThickness = 50f; // thickness of line
private int mRotate = 0; // rotate circle in degrees
private Paint mCircleBgPaint;
private int mCircleEndAngle = 270; // end arc
private int mCircleStartAngle = 0; // start arc
private int mCircleSweepAngle = 0; // actualy arc
private RectF mCircleOuterBounds;
private int mCircleBgColor = Color.RED; // color of circle
private Paint mCirclePaint; // progressbar
private int mCircleColor = Color.BLUE; // color of progressbar
private Paint mEraserPaint;
private RectF mCircleInnerBounds;
private int mEraserColor = Color.YELLOW; // background color of circle
private boolean mEraserInnerBackground = false; // eraser background inner circle
private Bitmap mBitmap;
private Canvas mCanvas;
private float mMinValue = 0; // min progressbar value
private float mMaxValue = 100; // max progressbar value
private float mProgressSweep = 0; // start progressbar value
private boolean mEnabled; // draw dot
private float mDotSize; // dot size
private Paint mCircleThumbPaint;
private float mTranslateX; // center circle (axis X)
private float mTranslateY; // center circle (axis Y)
private boolean mTouchInside; // touch inside circle can change position on progress
private float mTouchIgnoreRadius;
private int mArcRadius;
private int mThumbXPos;
private int mThumbYPos;
private OnPioArcCircleChangeListener mOnPioArcCircleChangeListener;
public PioArcCircle(Context context) {
super(context);
initDefaultValue(context, 0, null);
}
public PioArcCircle(Context context, AttributeSet attrs) {
super(context, attrs);
initDefaultValue(context, 0, attrs);
}
public PioArcCircle(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initDefaultValue(context, defStyleAttr, attrs);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public PioArcCircle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initDefaultValue(context, defStyleAttr, attrs);
}
private void initDefaultValue(Context context, int defStyleAttr, AttributeSet attrs) {
if (attrs != null) {
TypedArray typedArray = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.PioArcCircle,
defStyleAttr, 0);
this.mThickness = typedArray.getFloat(R.styleable.PioArcCircle_thickness1, this.mThickness);
this.mRotate = typedArray.getInt(R.styleable.PioArcCircle_rotate, this.mRotate);
this.mCircleSweepAngle = typedArray.getInt(R.styleable.PioArcCircle_circleSweepAngle, this.mCircleSweepAngle);
this.mCircleEndAngle = typedArray.getInt(R.styleable.PioArcCircle_circleEndAngle, this.mCircleEndAngle);
this.mCircleStartAngle = typedArray.getInt(R.styleable.PioArcCircle_circleStartAngle, this.mCircleStartAngle);
this.mCircleBgColor = typedArray.getInt(R.styleable.PioArcCircle_circleBgColor, this.mCircleBgColor);
this.mEraserColor = typedArray.getInt(R.styleable.PioArcCircle_eraserColor, this.mEraserColor);
this.mEraserInnerBackground = typedArray.getBoolean(R.styleable.PioArcCircle_eraserInnerBackground, this.mEraserInnerBackground);
this.mMinValue = typedArray.getFloat(R.styleable.PioArcCircle_minValue, this.mMinValue);
this.mMaxValue = typedArray.getFloat(R.styleable.PioArcCircle_maxValue, this.mMaxValue);
this.mEnabled = typedArray.getBoolean(R.styleable.PioArcCircle_enable, this.mEnabled);
this.mDotSize = typedArray.getFloat(R.styleable.PioArcCircle_dotSize, this.mDotSize);
this.mTouchInside = typedArray.getBoolean(R.styleable.PioArcCircle_touchInside, this.mTouchInside);
this.mCircleColor = typedArray.getInt(R.styleable.PioArcCircle_circleBgColor, this.mCircleColor);
}
mCircleBgPaint = new Paint();
mCircleBgPaint.setAntiAlias(true);
mCircleBgPaint.setColor(mCircleBgColor);
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(mCircleColor);
mEraserPaint = new Paint();
mEraserPaint.setAntiAlias(true);
mEraserPaint.setColor(mEraserColor);
if (mEraserInnerBackground) {
mEraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
mCircleThumbPaint = new Paint();
mCircleThumbPaint.setAntiAlias(true);
mCircleThumbPaint.setColor(Color.CYAN);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != oldw || h != oldh) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mBitmap.eraseColor(Color.TRANSPARENT);
mCanvas = new Canvas(mBitmap);
}
super.onSizeChanged(w, h, oldw, oldh);
updateBounds();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
int min = Math.min(widthMeasureSpec, heightMeasureSpec);
this.setMeasuredDimension(parentWidth, parentHeight);
this.setTouchInSide(this.mTouchInside);
super.onMeasure(min, min);
}
#Override
protected void onDraw(Canvas canvas) {
mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
mCanvas.drawArc(mCircleOuterBounds, (mCircleStartAngle + mRotate), (mCircleEndAngle - mCircleStartAngle), true, mCircleBgPaint);
if (mCircleSweepAngle - mRotate > 0f) {
mCanvas.drawArc(mCircleOuterBounds, (mCircleStartAngle + mRotate), (mCircleSweepAngle - mRotate), true, mCirclePaint);
}
mCanvas.drawOval(mCircleInnerBounds, mEraserPaint);
if (mEnabled) {
mThumbXPos = (int) (mTranslateX + (mArcRadius * Math.cos(Math.toRadians((double) this.mCircleSweepAngle))));
mThumbYPos = (int) (mTranslateY + (mArcRadius * Math.sin(Math.toRadians((double) this.mCircleSweepAngle))));
mCanvas.drawCircle(mThumbXPos, mThumbYPos, mThickness, mCircleThumbPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, null);
}
private void updateBounds() {
if (this.getPaddingLeft() < (mThickness / 2)) {
this.setPadding((int) (mThickness / 2), this.getPaddingTop(), this.getPaddingRight(), this.getPaddingBottom());
}
mCircleOuterBounds = new RectF(0 + this.getPaddingLeft(), 0 + this.getPaddingLeft(), getWidth() - this.getPaddingLeft(), getHeight() - this.getPaddingLeft());
mCircleInnerBounds = new RectF(
mCircleOuterBounds.left + mThickness,
mCircleOuterBounds.top + mThickness,
mCircleOuterBounds.right - mThickness,
mCircleOuterBounds.bottom - mThickness);
this.mTranslateX = mCircleOuterBounds.centerX();
this.mTranslateY = mCircleOuterBounds.centerY();
this.mArcRadius = (int) (mTranslateX - this.getPaddingLeft() - (mThickness / 2));
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.mEnabled) {
this.getParent().requestDisallowInterceptTouchEvent(true);
switch (event.getAction()) {
case 0:
this.onStartTrackingTouch();
this.updateOnTouch(event);
break;
case 1:
this.onStopTrackingTouch();
this.setPressed(false);
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
case 2:
this.updateOnTouch(event);
break;
case 3:
this.onStopTrackingTouch();
this.setPressed(false);
this.getParent().requestDisallowInterceptTouchEvent(false);
}
return true;
} else {
return false;
}
}
public void setTouchInSide(boolean isEnabled) {
int thumbHalfheight = (int) (mThickness / 2);
int thumbHalfWidth = (int) (mThickness / 2);
this.mTouchInside = isEnabled;
if (this.mTouchInside) {
this.mTouchIgnoreRadius = (float) this.mArcRadius / 4.0F;
} else {
this.mTouchIgnoreRadius = (float) (this.mArcRadius - Math.min(thumbHalfWidth, thumbHalfheight));
}
}
private void updateOnTouch(MotionEvent event) {
boolean ignoreTouch = this.ignoreTouch(event.getX(), event.getY());
if (!ignoreTouch) {
this.setPressed(true);
this.mProgressSweep = (float) this.getTouchDegrees(event.getX(), event.getY());
this.updateProgress((int) this.mProgressSweep);
}
}
private double getTouchDegrees(float xPos, float yPos) {
double angle = (int) (Math.atan2(yPos - mTranslateY, xPos - mTranslateX) * 180 / Math.PI);
if (angle < 0) {
angle += 360;
}
float x = xPos - this.mTranslateX;
float y = yPos - this.mTranslateY;
angle = Math.toDegrees(Math.atan2((double) y, (double) x) + 1.5707963267948966D - Math.toRadians((double) this.mRotate));
if (angle < 0.0D) {
angle += 360.0D;
}
angle -= (double) this.mCircleStartAngle;
return angle;
}
private boolean ignoreTouch(float xPos, float yPos) {
boolean ignore = false;
double touchRadius = Math.sqrt(Math.pow(xPos - this.mTranslateX, 2) + Math.pow(yPos - this.mTranslateY, 2));
if (this.mTouchInside && touchRadius > this.mArcRadius) {
ignore = true;
} else {
if ((touchRadius > (this.mArcRadius + (this.mThickness / 2))) ||
(touchRadius < (this.mArcRadius - (this.mThickness / 2)))) {
ignore = true;
}
}
return ignore;
}
private void onStartTrackingTouch() {
if (this.mOnPioArcCircleChangeListener != null) {
this.mOnPioArcCircleChangeListener.onStartTrackingTouch(this);
}
}
private void onStopTrackingTouch() {
if (this.mOnPioArcCircleChangeListener != null) {
this.mOnPioArcCircleChangeListener.onStopTrackingTouch(this);
}
}
private void updateProgress(int progress) {
if (progress != INVALID_PROGRESS_VALUE) {
if (this.mOnPioArcCircleChangeListener != null) {
this.mOnPioArcCircleChangeListener.onProgressChanged(this);
}
mCircleSweepAngle = progress;
this.invalidate();
}
}
public OnPioArcCircleChangeListener getmOnPioArcCircleChangeListener() {
return mOnPioArcCircleChangeListener;
}
public void setmOnPioArcCircleChangeListener(OnPioArcCircleChangeListener mOnPioArcCircleChangeListener) {
this.mOnPioArcCircleChangeListener = mOnPioArcCircleChangeListener;
}
public interface OnPioArcCircleChangeListener {
void onProgressChanged(PioArcCircle var1);
void onStartTrackingTouch(PioArcCircle var1);
void onStopTrackingTouch(PioArcCircle var1);
}
}
activity_main.xml:
<com.test.myapplication.PioArcCircle
android:layout_width="200dp"
android:layout_height="200dp"
android:padding="#dimen/activity_vertical_margin"
android:progressDrawable="#drawable/circular_progress_bar"
pioarccircle:circleColor="#color/colorAccent"
pioarccircle:enable="true"
pioarccircle:minValue="50.0"
pioarccircle:rotate="135"
pioarccircle:thickness1="100" />
First problem:
How i can create a few colors of progress?
Thanks for help.
Here is the custom class of GradientTextView provided by #koush (source is there on (github)
Now I got the class but how to call this class anyone can help since I am new bee on android
As far as I understood it can use custom attribute to but nyways how to call this class from MainActivity to get run. I dont know how to send AttributeSet parameters. it's too confusing
package android.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.LinearGradient;
import android.graphics.Shader.TileMode;
import android.text.BoringLayout;
import android.util.AttributeSet;
import android.widget.TextView;
public class GradientTextView extends TextView {
public GradientTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
int mStartColor = 0;
int mEndColor = 0;
float mAngle;
String mText;
BoringLayout mLayout;
public GradientTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
int[] ids = new int[attrs.getAttributeCount()];
for (int i = 0; i < attrs.getAttributeCount(); i++) {
ids[i] = attrs.getAttributeNameResource(i);
}
TypedArray a = context.obtainStyledAttributes(attrs, ids, defStyle, 0);
for (int i = 0; i < attrs.getAttributeCount(); i++) {
String attrName = attrs.getAttributeName(i);
if (attrName == null)
continue;
if (attrName.equals("startColor")) {
mStartColor = a.getColor(i, -1);
}
else if (attrName.equals("endColor")) {
mEndColor = a.getColor(i, -1);
}
else if (attrName.equals("angle")) {
mAngle = a.getFloat(i, 0);
}
}
}
public static void setGradient(TextView tv, float angle, int startColor, int endColor) {
tv.measure(tv.getLayoutParams().width, tv.getLayoutParams().height);
LinearGradient gradient = getGradient(tv.getMeasuredWidth(), tv.getMeasuredHeight(), angle, startColor, endColor);
tv.getPaint().setShader(gradient);
}
static LinearGradient getGradient(int measuredWidth, int measuredHeight, float angle, int startColor, int endColor) {
// calculate a vector for this angle
double rad = Math.toRadians(angle);
double oa = Math.tan(rad);
double x;
double y;
if (oa == Double.POSITIVE_INFINITY) {
y = 1;
x = 0;
}
else if (oa == Double.NEGATIVE_INFINITY) {
y = -1;
x = 0;
}
else {
y = oa;
if (rad > Math.PI)
x = -1;
else
x = 1;
}
// using the vector, calculate the start and end points from the center of the box
int mx = measuredWidth;
int my = measuredHeight;
int cx = mx / 2;
int cy = my / 2;
double n;
if (x == 0) {
n = (double)cy / y;
}
else if (y == 0) {
n = (double)cx / x;
}
else {
n = (double)cy / y;
double n2 = (double)cx / x;
if (Math.abs(n2) < Math.abs(n))
n = n2;
}
int sx = (int)(cx - n * x);
int sy = (int)(cy - n * y);
int ex = (int)(cx + n * x);
int ey = (int)(cy + n * y);
return new LinearGradient(sx, sy, ex, ey, startColor, endColor, TileMode.CLAMP);
}
protected void onDraw(android.graphics.Canvas canvas) {
if (mGradient == null) {
mGradient = getGradient(getMeasuredWidth(), getMeasuredHeight(), mAngle, mStartColor, mEndColor);
getPaint().setShader(mGradient);
}
super.onDraw(canvas);
}
public int getStartColor() {
return mStartColor;
}
public void setStartColor(int startColor) {
mStartColor = startColor;
invalidate();
}
public int getEndColor() {
return mEndColor;
}
public void setEndColor(int endColor) {
mEndColor = endColor;
invalidate();
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mGradient = null;
}
LinearGradient mGradient;
}
This custom class are too confusing but they are used for tweaking like outline, gradients, and etc I am very keen to understand the flow
you can use this "View Element" by instanciating/using a view object:
TextView myView = new TextView (this);
myView.setText("Test");
GradientTextView.setGradient(myView, 90, Color.BLACK, Color.WHITE);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
Layoutparams.WRAP_CONTENT);
myLayout.addView(myView, params);
You can even use this object using it your layouts XML file.