I have a custom Imageview class like below. I have a field called timeInterval which I pass it in constructor, but in onDraw it's value is 0. What is the proper way to pass this? also I don't know if I can pass it dynamically as attribute.
public class ProgressBarView extends AppCompatImageView {
private final Handler mHandler = new Handler();
private int mTimeInterval;
private int mColor;
private int[] mLocations = new int[2];
public ProgressBarView(Context context, int timeInterval) {
super(context);
mTimeInterval = timeInterval;
init(null);
}
public ProgressBarView(Context context, AttributeSet attrst) {
super(context, attrst);
init(attrst);
}
public ProgressBarView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
private void init(AttributeSet attrs) {
if (attrs == null) {
return;
}
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ProgressBarView);
mColor = typedArray.getColor(R.styleable.ProgressBarView_overlay_color, Color.BLACK);
}
public void updatePainting() {
mHandler.postDelayed(this::invalidate, mTimeInterval / 360);
}
#Override
public void onDraw(final Canvas canvas) {
if (mTimeInterval == 0) {
return;
}
Calendar now = Calendar.getInstance();
int seconds = now.get(Calendar.SECOND);
int mStartAngel = (int) (((float) (seconds % (mTimeInterval / 1000))
/ (mTimeInterval / 1000)) * 360);
final Paint paint = new Paint(Paint.DITHER_FLAG);
paint.setColor(mColor);
paint.setStyle(Paint.Style.FILL);
paint.setAlpha(-50);
getLocationOnScreen(mLocations);
int radius = getWidth() / 2;
float centreX = this.getX() + radius;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
canvas.drawArc(centreX - radius, centreX - radius, centreX + radius, centreX + radius, 0, mStartAngel, true, paint);
} else {
final RectF oval = new RectF();
oval.set(centreX - radius, centreX - radius, centreX + radius, centreX + radius);
canvas.drawArc(oval, 0, mStartAngel, true, paint);
}
updatePainting();
}
}
I instantiate it like this:
mProgressBarView = new ProgressBarView(getContext(), timeInterval);
You forgot about "this"
public ProgressBarView(Context context, int timeInterval) {
super(context);
this.mTimeInterval = timeInterval;
init(null);
}
Related
I use this class to make lines inside editText which works well. I want to change the line colors in another activities programmatically. How to do that?
public class LinedEditText extends androidx.appcompat.widget.AppCompatEditText{
public final Paint mPaint = new Paint();
public LinedEditText(Context context) {
super(context);
initPaint();
}
public LinedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
}
public LinedEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initPaint();
}
private void initPaint() {
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLUE);
}
#Override protected void onDraw(Canvas canvas) {
int left = getLeft();
int right = getRight();
int paddingTop = getPaddingTop();
int paddingBottom = getPaddingBottom();
int paddingLeft = getPaddingLeft();
int paddingRight = getPaddingRight();
int height = getHeight();
int lineHeight = getLineHeight();
int count = (height-paddingTop-paddingBottom) / lineHeight;
for (int i = 0; i < count; i++) {
int baseline = lineHeight * (i+1) + paddingTop;
canvas.drawLine(left+paddingLeft, baseline, right-paddingRight, baseline, mPaint);
}
super.onDraw(canvas);
}
}
Second question is, how to make new line when the user pressed enter or return key so as to the will have something like unlimited lines?
public class LinedEditText extends EditText {
private Rect mRect;
protected Paint mPaint;
// we need this constructor for LayoutInflater
public LinedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mRect = new Rect();
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setColor(Color.parseColor("#82B6C6"));
}
#Override
public void onDraw(Canvas canvas) {
//int count = getLineCount();
int height = getHeight();
int line_height = getLineHeight();
int count = height / line_height;
if (getLineCount() > count)
count = getLineCount();//for long text with scrolling
Rect r = mRect;
Paint paint = mPaint;
int baseline = getLineBounds(0, r);//first line
for (int i = 0; i < count; i++) {
canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint);
baseline += getLineHeight();//next line
}
super.onDraw(canvas);
}
}
I have a method to Cropped image to circle and work fine but need scale type to center crop or center in image but dont work if I define in XML file.
In xml value= SCALE TYPE= CENTER_CROP OR SCALE_TYPE CENTER
This is my class button:
public class CircleImage extends ImageView {
public CircleImage(Context context) {
super(context);
}
public CircleImage(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CircleImage(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
int w = getWidth(), h = getHeight();
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
Bitmap sbmp;
if (bmp.getWidth() != radius || bmp.getHeight() != radius) {
float smallest = Math.min(bmp.getWidth(), bmp.getHeight());
float factor = smallest / radius;
sbmp = Bitmap.createScaledBitmap(bmp, (int)(bmp.getWidth() / factor), (int)(bmp.getHeight() / factor), false);
} else {
sbmp = bmp;
}
Bitmap output = Bitmap.createBitmap(radius, radius,
Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xffa19774;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, radius, radius);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(radius / 2 + 0.7f,
radius / 2 + 0.7f, radius / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
}
Pass a complete and fixed class for circle image and center scale type
public class CircleImage extends ImageView {
public CircleImage(Context context) {
super(context);
}
public CircleImage(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CircleImage(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
int w = getWidth(), h = getHeight();
Bitmap bm_scale_center_crop;
if (bitmap.getWidth() >= bitmap.getHeight()){
bm_scale_center_crop = Bitmap.createBitmap(
bitmap,
bitmap.getWidth()/2 - bitmap.getHeight()/2,
0,
bitmap.getHeight(),
bitmap.getHeight()
);
}else{
bm_scale_center_crop = Bitmap.createBitmap(
bitmap,
0,
bitmap.getHeight()/2 - bitmap.getWidth()/2,
bitmap.getWidth(),
bitmap.getWidth()
);
}
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
I am having a line that I draw it using "canvas.drawLine(250, 400 , 250 , 200, p3 )" , I want to rotate it using the rotateAnimation , is there away to do it ?
when I try to put the drawLine(...) in a method it getting no compiled...
import android.widget.Toast;
class Circles<Graphics> extends View
{
public Circles(Context context)
{
super(context);
}
public void onDraw(final Canvas canvas)
{
super.onDraw(canvas);
//2 Circels
Paint p1 = new Paint();
p1.setColor(Color.BLUE);
p1.setStyle(Style.STROKE);
Paint p2 = new Paint();
p2.setColor(Color.RED);
p2.setStyle(Style.FILL);
canvas.drawCircle(250, 400, 250, p1);
canvas.drawCircle(250, 400, 20, p2);
// invalidate();
// Seconds
final Paint p3 = new Paint();
p3.setColor(Color.RED);
p3.setStyle(Style.FILL);
int b1 ;
Runnable seconds = new Runnable() {
public void run() {
try {
int seconds = 0;
RotateAnimation rotateAnimation = new RotateAnimation(
(seconds - 1) * 6, seconds * 6,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(1000);
rotateAnimation.setFillAfter(true);
// now rotate this canvas.drawLine(250, 400 , 250 , 200, p3 ) ;
} catch (Exception e) {
}
}
};
}
If you want to use animation for drawing circle line use my code.
There is an animation which only gives you interpolated time of rotate animation, so you can simply refresh the toAngleValue and refresh the drawing state for smoothy your line draw.
/**
* Created by GIGAMOLE on 17.06.2015.
*/
public class CustomView extends View {
public CustomView(Context context) {
this(context, null);
}
public CustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
startAnimation(new CustomAnimation(fromAngleValue, toAngleValue));
setWillNotDraw(false);
}
//Out values for angle circle
private float fromAngleValue = 0f;
private float toAngleValue = 360f;
private float currentAngleValue;
//Paint
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG) {
{
setDither(true);
setColor(Color.RED);
setStrokeWidth(5);
setStyle(Style.STROKE);
}
};
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//Always draw arc and invalidate it in animation
canvas.drawArc(
new RectF(
50,
50,
getWidth() - 50,
getHeight() - 50
),
fromAngleValue,
currentAngleValue,
false,
paint
);
}
private class CustomAnimation extends RotateAnimation {
public CustomAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomAnimation(float fromDegrees, float toDegrees) {
super(fromDegrees, toDegrees);
setDuration(3000);
setFillAfter(true);
}
public CustomAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY) {
super(fromDegrees, toDegrees, pivotX, pivotY);
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
currentAngleValue = interpolatedTime * toAngleValue;
invalidate();
//Change current value relative to animation
}
}
}
Also you can use esiest method which only increment value with post invalidate, but there is no features like concret duration and any kind of intelpolators.
/**
* Created by GIGAMOLE on 17.06.2015.
*/
public class CustomView extends View {
public CustomView(Context context) {
this(context, null);
}
public CustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWillNotDraw(false);
}
//Out values for angle circle
private float fromAngleValue = 0f;
private float toAngleValue = 360f;
private float currentAngleValue;
//Paint
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG) {
{
setDither(true);
setColor(Color.RED);
setStrokeWidth(5);
setStyle(Style.STROKE);
}
};
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//Always draw arc and invalidate it in animation
canvas.drawArc(
new RectF(
50,
50,
getWidth() - 50,
getHeight() - 50
),
fromAngleValue,
currentAngleValue,
false,
paint
);
if (currentAngleValue <= toAngleValue) {
currentAngleValue++;
postInvalidateDelayed(1);
}
}
}
I am writing an pixel art app that paints images the user draws on the screen to pixel look. There are two ways to approach it. Either pixelate the image after saving or have a grid before hand so the user draws the pixel image. I don't find anything on the later method. So my issue with the first is drawing a grid where if a cell is touched I would change the color of it. I tried drawing rectangles on a canvas but that was pointless because i couldn't control the cells.
I was thinking about nested for loops that creates a bitmap at each cell?
The following is just a simple, illustrative example. It is not optimized, implements no exception handling, etc.
public class PixelGridView extends View {
private int numColumns, numRows;
private int cellWidth, cellHeight;
private Paint blackPaint = new Paint();
private boolean[][] cellChecked;
public PixelGridView(Context context) {
this(context, null);
}
public PixelGridView(Context context, AttributeSet attrs) {
super(context, attrs);
blackPaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
public void setNumColumns(int numColumns) {
this.numColumns = numColumns;
calculateDimensions();
}
public int getNumColumns() {
return numColumns;
}
public void setNumRows(int numRows) {
this.numRows = numRows;
calculateDimensions();
}
public int getNumRows() {
return numRows;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
calculateDimensions();
}
private void calculateDimensions() {
if (numColumns < 1 || numRows < 1) {
return;
}
cellWidth = getWidth() / numColumns;
cellHeight = getHeight() / numRows;
cellChecked = new boolean[numColumns][numRows];
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
if (numColumns == 0 || numRows == 0) {
return;
}
int width = getWidth();
int height = getHeight();
for (int i = 0; i < numColumns; i++) {
for (int j = 0; j < numRows; j++) {
if (cellChecked[i][j]) {
canvas.drawRect(i * cellWidth, j * cellHeight,
(i + 1) * cellWidth, (j + 1) * cellHeight,
blackPaint);
}
}
}
for (int i = 1; i < numColumns; i++) {
canvas.drawLine(i * cellWidth, 0, i * cellWidth, height, blackPaint);
}
for (int i = 1; i < numRows; i++) {
canvas.drawLine(0, i * cellHeight, width, i * cellHeight, blackPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int column = (int)(event.getX() / cellWidth);
int row = (int)(event.getY() / cellHeight);
cellChecked[column][row] = !cellChecked[column][row];
invalidate();
}
return true;
}
}
Here's a simple Activity for demonstration:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PixelGridView pixelGrid = new PixelGridView(this);
pixelGrid.setNumColumns(4);
pixelGrid.setNumRows(6);
setContentView(pixelGrid);
}
}
public class PixelGridView extends View {
//number of row and column
int horizontalGridCount = 2;
private Drawable horiz;
private Drawable vert;
private final float width;
public PixelGridView(#NonNull Context context) {
this(context, null);
}
public PixelGridView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
horiz = new ColorDrawable(Color.WHITE); horiz.setAlpha(160);
vert = new ColorDrawable(Color.WHITE); vert.setAlpha(160);
width = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0.9f, context.getResources().getDisplayMetrics());
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
horiz.setBounds(left, 0, right, (int) width);
vert.setBounds(0, top, (int) width, bottom);
}
private float getLinePosition(int lineNumber) {
int lineCount = horizontalGridCount;
return (1f / (lineCount + 1)) * (lineNumber + 1f);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// drawTask.start();
int count = horizontalGridCount;
for (int n = 0; n < count; n++) {
float pos = getLinePosition(n);
// Draw horizontal line
canvas.translate(0, pos * getHeight());
horiz.draw(canvas);
canvas.translate(0, - pos * getHeight());
// Draw vertical line
canvas.translate(pos * getWidth(), 0);
vert.draw(canvas);
canvas.translate(- pos * getWidth(), 0);
}
//drawTask.end(count);
}
}
and in your main activity:
//inside on create method
val myView = PixelGridView(this)
id_frame.addView(myView)
id_frame is frame layout in xml
This view class will draw grid of equidistance lines in Canvas based on how much GAP_WIDTH_DP is allocated
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
public class PixelGridView extends View {
private int screenWidth;
private int screenHeight;
public static final int GAP_WIDTH_DP = 62;
private float GAP_WIDTH_PIXEL;
private Paint paint = new Paint();
public PixelGridView(Context context) {
super(context);
init(context);
}
public PixelGridView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public PixelGridView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public PixelGridView(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
public static float convertDpToPixel(float dp, Context context){
return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
public void init(Context context) {
// set paint color
paint.setColor(Color.GREEN);
// get view dimentions
getScreenDimensions();
}
private void getScreenDimensions() {
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
screenWidth = displayMetrics.widthPixels;
screenHeight = displayMetrics.heightPixels;
//gap size in pixel
GAP_WIDTH_PIXEL = convertDpToPixel(GAP_WIDTH_DP, getContext());
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
getScreenDimensions();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw Horizontal line from Y= 0 -> Y+=Gap... till screen width
float verticalPosition = 0;
while (verticalPosition <= screenHeight) {
canvas.drawLine(0, verticalPosition,
screenWidth, verticalPosition, paint);
verticalPosition += GAP_WIDTH_PIXEL;
}
// draw Vertical line from X=0 -> X+=Gap... till screen Height 0|||hor+gap|||W
float horizontalPosition = 0;
while (horizontalPosition <= screenWidth) {
canvas.drawLine(horizontalPosition, 0,
horizontalPosition, screenHeight,paint);
horizontalPosition += GAP_WIDTH_PIXEL;
}
}
}
One available option is to look into using the Android Gridview as the drawing grid; I have not tested this myself, however if you create an object to be touched in each cell with your desired pixel dimensions, you should be able to create a rudimentary Pixel Art application by saving the variables.
Note, grid view cells are sized based on their contents, as noted in How to set a cell size in Android grid view?
Also, when it comes to drawing things, there are many different ways to handle it, however following a guide or tutorial such as http://code.tutsplus.com/tutorials/android-sdk-create-a-drawing-app-touch-interaction--mobile-19202 is generally the best place to start and pull what you need from it.
Good luck!
I need to denote progress by the border of view.
E.g. Initially view will not have any border at all, when 50% progress is reached, only 50% of view will get border.Find the attached image.
I did lot of googling but no luck.The view I used is textview.
Edited
The following code, cuts the edges of bitmap.
What I've done in this code is -
1. Bg is set to Black Hexagon
2. And I've taken hollow green bordered hexagon & revealing this hollow hexagon, so that it will look like border is getting accumulated.
public class MyView extends View {
private Bitmap mBitmap;
private Paint mPaint;
private RectF mOval;
private float mAngle = 135;
private Paint mTextPaint;
private Bitmap bgBitmap;
public MyView(Context context) {
super(context);
doInit();
}
/**
* #param context
* #param attrs
* #param defStyleAttr
*/
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
doInit();
}
/**
* #param context
* #param attrs
*/
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
doInit();
}
private void doInit() {
// use your bitmap insted of R.drawable.ic_launcher
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.hexagon_border);
bgBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.view_message_small_hexagon);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mOval = new RectF();
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextSize(48);
mTextPaint.setTextAlign(Align.CENTER);
mTextPaint.setColor(0xffffaa00);
mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Matrix m = new Matrix();
RectF src = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
RectF dst = new RectF(0, 0, w, h);
m.setRectToRect(src, dst, ScaleToFit.CENTER);
Shader shader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);
shader.setLocalMatrix(m);
mPaint.setShader(shader);
m.mapRect(mOval, src);
}
#Override
protected void onDraw(Canvas canvas) {
//canvas.drawColor(0xff0000aa);
Matrix matrix = new Matrix();
canvas.drawBitmap(bgBitmap, matrix, null);
canvas.drawArc(mOval, -90, mAngle, true, mPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float w2 = getWidth() / 2f;
float h2 = getHeight() / 2f;
mAngle = (float) Math.toDegrees(Math.atan2(event.getY() - h2, event.getX() - w2));
mAngle += 90 + 360;
mAngle %= 360;
invalidate();
return true;
}
}
try this SO answer:
public class MyView extends View {
private Bitmap mBitmap;
private Paint mPaint;
private RectF mOval;
private float mAngle = 135;
private Paint mTextPaint;
public MyView(Context context) {
super(context);
// use your bitmap insted of R.drawable.ic_launcher
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mOval = new RectF();
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextSize(48);
mTextPaint.setTextAlign(Align.CENTER);
mTextPaint.setColor(0xffffaa00);
mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Matrix m = new Matrix();
RectF src = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
RectF dst = new RectF(0, 0, w, h);
m.setRectToRect(src, dst, ScaleToFit.CENTER);
Shader shader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);
shader.setLocalMatrix(m);
mPaint.setShader(shader);
m.mapRect(mOval, src);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xff0000aa);
canvas.drawArc(mOval, -90, mAngle, true, mPaint);
canvas.drawText("click me", getWidth() / 2, getHeight() / 2, mTextPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float w2 = getWidth() / 2f;
float h2 = getHeight() / 2f;
mAngle = (float) Math.toDegrees(Math.atan2(event.getY() - h2, event.getX() - w2));
mAngle += 90 + 360;
mAngle %= 360;
invalidate();
return true;
}
}
Getting a good circular progress spinner is difficult in itself. The ProgressWheel is a good custom View that does this. You should be able to modify the ProgressWheel's onDraw() class to do something very similar to what you want.