StateListDrawable on ImageView is not working - java

When trying this snippet of code from AOSP Launcher3:
void generatePressedFocusedStates(ImageView v) {
if (!mStatesUpdated && v != null) {
mStatesUpdated = true;
Bitmap original = createOriginalImage(v, mTempCanvas);
Bitmap outline = createImageWithOverlay(v, mTempCanvas, mHighlightColor);
Bitmap hotword = createImageWithOverlay(v, mTempCanvas, mHotwordColor);
FastBitmapDrawable originalD = new FastBitmapDrawable(original);
FastBitmapDrawable outlineD = new FastBitmapDrawable(outline);
FastBitmapDrawable hotwordD = new FastBitmapDrawable(hotword);
StateListDrawable states = new StateListDrawable();
states.addState(new int[] {android.R.attr.state_pressed}, outlineD);
states.addState(new int[] {android.R.attr.state_focused}, outlineD);
states.addState(new int[] {R.attr.stateHotwordOn}, hotwordD);
states.addState(new int[] {}, originalD);
v.setImageDrawable(states);
}
}
The 2 ImageView s I applied this to suddenly lose their Drawables: they're empty.
If I replace the last line with
v.setImageDrawable(originalD);
// or
v.setImageDrawable(outlineD);
// or
v.setImageDrawable(hotwordD);
then the ImageViews display the chosen drawable. So I think this proves that there's no problem with the ImageView or with the Drawables... Only with the StateListDrawable.
For completion, here are the used methods:
private Bitmap createOriginalImage(ImageView v, Canvas canvas) {
final Drawable d = v.getDrawable();
final Bitmap b = Bitmap.createBitmap(
d.getIntrinsicWidth(), d.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
canvas.setBitmap(b);
canvas.save();
d.draw(canvas);
canvas.restore();
canvas.setBitmap(null);
return b;
}
-
private Bitmap createImageWithOverlay(ImageView v, Canvas canvas, int color) {
final Drawable d = v.getDrawable();
final Bitmap b = Bitmap.createBitmap(
d.getIntrinsicWidth(), d.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
canvas.setBitmap(b);
canvas.save();
d.draw(canvas);
canvas.restore();
canvas.drawColor(color, PorterDuff.Mode.SRC_IN);
canvas.setBitmap(null);
return b;
}
-
class FastBitmapDrawable extends Drawable {
private Bitmap mBitmap;
private int mAlpha;
private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
FastBitmapDrawable(Bitmap b) {
mAlpha = 255;
mBitmap = b;
setBounds(0, 0, b.getWidth(), b.getHeight());
}
#Override
public void draw(Canvas canvas) {
final Rect r = getBounds();
// Draw the bitmap into the bounding rect
canvas.drawBitmap(mBitmap, null, r, mPaint);
}
#Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public void setAlpha(int alpha) {
mAlpha = alpha;
mPaint.setAlpha(alpha);
}
public void setFilterBitmap(boolean filterBitmap) {
mPaint.setFilterBitmap(filterBitmap);
mPaint.setAntiAlias(filterBitmap);
}
public int getAlpha() {
return mAlpha;
}
#Override
public int getIntrinsicWidth() {
return getBounds().width();
}
#Override
public int getIntrinsicHeight() {
return getBounds().height();
}
#Override
public int getMinimumWidth() {
return getBounds().width();
}
#Override
public int getMinimumHeight() {
return getBounds().height();
}
public Bitmap getBitmap() {
return mBitmap;
}
}

Related

AndroidRuntime: FATAL EXCEPTION: Nullpointerexception, Inflateexception

Please, i got many errors on my code really i need your help.
Errors:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: tools.myapp.app1, PID: 23986
java.lang.RuntimeException: Unable to start activity ComponentInfo{tools.myapp.app1/tools.myapp.app1.activitys.GreatingCardShowActivity}: android.view.InflateException: Binary XML file line #58 in tools.myapp.app1:layout/activity_greating_card_show: Binary XML file line #58 in tools.myapp.app1:layout/activity_greating_card_show: Error inflating class tools.myapp.app1.StickerView.StickerView
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3479)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3651)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2104)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:7861)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:600)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
Caused by: android.view.InflateException: Binary XML file line #58 in tools.myapp.app1:layout/activity_greating_card_show: Binary XML file line #58 in tools.myapp.app1:layout/activity_greating_card_show: Error inflating class tools.myapp.app1.StickerView.StickerView
Caused by: android.view.InflateException: Binary XML file line #58 in tools.myapp.app1:layout/activity_greating_card_show: Error inflating class tools.myapp.app1.StickerView.StickerView
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at android.view.LayoutInflater.createView(LayoutInflater.java:856)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1008)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:963)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1125)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1086)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1128)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1086)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1128)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1086)
at android.view.LayoutInflater.inflate(LayoutInflater.java:684)
at android.view.LayoutInflater.inflate(LayoutInflater.java:536)
at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
at `androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:706)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:195)
at tools.myapp.app1.activitys.GreatingCardShowActivity.onCreate(GreatingCardShowActivity.java:1001)
at android.app.Activity.performCreate(Activity.java:8109)
at android.app.Activity.performCreate(Activity.java:8083)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1310)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3452)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3651)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2104)
at android.os.Handler.dispatchMessage(Handler.java:106)
E/AndroidRuntime: at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:7861)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:600)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.drawable.Drawable.getIntrinsicWidth()' on a null object reference
at tools.myapp.app1.StickerView.DrawableSticker.getWidth(DrawableSticker.java:38)
at tools.myapp.app1.StickerView.DrawableSticker.<init>(DrawableSticker.java:10)
at tools.myapp.app1.StickerView.BitmapStickerIcon.<init>(BitmapStickerIcon.java:16)
at tools.myapp.app1.StickerView.StickerView.<init>(StickerView.java:129)
at tools.myapp.app1.StickerView.StickerView.<init>(StickerView.java:111)
Here: layout/activity_greating_card_show
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/background_ss">
code......
**//this is a line #58 that the compiler marked**
<tools.myapp.app1.StickerView.StickerView
android:id="#+id/stickerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:layout_margin="#dimen/_8sdp"
android:visibility="visible" />
</RelativeLayout>
Here: GreatingCardShowActivity/onCreate
public void onCreate(#Nullable Bundle bundle) {
ImageView imageView;
float f;
super.onCreate(bundle);
**//the compiler select this line #1001**
setContentView(R.layout.activity_greating_card_show);
InterstitialAdHelper instance = InterstitialAdHelper.Companion.getInstance();
if (instance == null) {
Intrinsics.throwNpe();
}
instance.load(this, this);
this.activity = this;
this.assetManager = getAssets();
this.mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
if (Share.ActivityCardCreate) {
this.bgposition = getIntent().getStringExtra("bgposition");
Log.e("val", "onCreate: bg pos-->" + this.bgposition);
} else {
Intent intent = getIntent();
this.gretingcatname = intent.getStringExtra("gretingcatname");
this.pos = intent.getIntExtra("pos", 0);
}
initView();
if (Share.ActivityCardCreate || Share.ActivityGalleryCardCreate) {
ImageView imageView2 = this.iv_custom_sticker_view;
if (imageView2 == null) {
Intrinsics.throwNpe();
}
f = 1.0f;
imageView2.setAlpha(1.0f);
ImageView imageView3 = this.iv_gc_quotes;
if (imageView3 == null) {
Intrinsics.throwNpe();
}
imageView3.setAlpha(1.0f);
imageView = this.iv_ad_frame;
} else {
ImageView imageView4 = this.iv_custom_sticker_view;
if (imageView4 == null) {
Intrinsics.throwNpe();
}
f = 0.5f;
imageView4.setAlpha(0.5f);
ImageView imageView5 = this.iv_gc_quotes;
if (imageView5 == null) {
Intrinsics.throwNpe();
}
imageView5.setAlpha(0.5f);
imageView = this.iv_ad_frame;
}
imageView.setAlpha(f);
initAction();
drawables_sticker.clear();
}
Here: class DrawableSticker
public class DrawableSticker extends Sticker {
private Drawable mDrawable;
**// Below is line #10 the compiler select getWidth() in this line**
private final Rect mRealBounds = new Rect(0, 0, getWidth(), getHeight());
public DrawableSticker(Drawable drawable) {
this.mDrawable = drawable;
this.a = new Matrix();
}
#Override
public void draw(Canvas canvas) {
canvas.save();
canvas.concat(this.a);
this.mDrawable.setBounds(this.mRealBounds);
this.mDrawable.draw(canvas);
canvas.restore();
}
#Override
public Drawable getDrawable() {
return this.mDrawable;
}
#Override
public int getHeight() {
return this.mDrawable.getIntrinsicHeight();
}
#Override
public int getWidth() {
return this.mDrawable.getIntrinsicWidth(); **//here line #38**
}
#Override
public void release() {
super.release();
if (this.mDrawable != null) {
this.mDrawable = null;
}
}
#Override
public void setDrawable(Drawable drawable) {
this.mDrawable = drawable;
}
}
This is : class Sticker
"extended in class DrawableSticker"
public abstract class Sticker {
protected Matrix a;
protected boolean b;
private String tag = "";
private float[] mMatrixValues = new float[9];
private float getMatrixAngle(#NonNull Matrix matrix) {
return (float) (-(Math.atan2((double) getMatrixValue(matrix, 1), (double)
getMatrixValue(matrix, 0)) * 57.29577951308232d));
}
private float getMatrixScale(#NonNull Matrix matrix) {
return (float) Math.sqrt(Math.pow((double) getMatrixValue(matrix, 0), 2.0d) +
Math.pow((double) getMatrixValue(matrix, 3), 2.0d));
}
private float getMatrixValue(#NonNull Matrix matrix, #IntRange(from = 0, to = 9) int i) {
matrix.getValues(this.mMatrixValues);
return this.mMatrixValues[i];
}
public boolean contains(float f, float f2) {
Matrix matrix = new Matrix();
matrix.setRotate(-getCurrentAngle());
float[] fArr = new float[8];
float[] fArr2 = new float[2];
matrix.mapPoints(fArr, getMappedBoundPoints());
matrix.mapPoints(fArr2, new float[]{f, f2});
return StickerUtils.trapToRect(fArr).contains(fArr2[0], fArr2[1]);
}
public abstract void draw(Canvas canvas);
public RectF getBound() {
return new RectF(0.0f, 0.0f, (float) getWidth(), (float) getHeight());
}
public float[] getBoundPoints() {
return !this.b ? new float[]{0.0f, 0.0f, (float) getWidth(), 0.0f, 0.0f, (float)
getHeight(), (float) getWidth(), (float) getHeight()} : new float[]{(float) getWidth(), 0.0f,
0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 0.0f, (float) getHeight()};
}
public PointF getCenterPoint() {
return new PointF((float) (getWidth() / 2), (float) (getHeight() / 2));
}
public float getCurrentAngle() {
return getMatrixAngle(this.a);
}
public float getCurrentHeight() {
return getMatrixScale(this.a) * ((float) getHeight());
}
public float getCurrentScale() {
return getMatrixScale(this.a);
}
public float getCurrentWidth() {
return getMatrixScale(this.a) * ((float) getWidth());
}
public abstract Drawable getDrawable();
public abstract int getHeight();
public RectF getMappedBound() {
RectF rectF = new RectF();
this.a.mapRect(rectF, getBound());
return rectF;
}
public float[] getMappedBoundPoints() {
float[] fArr = new float[8];
this.a.mapPoints(fArr, getBoundPoints());
return fArr;
}
public PointF getMappedCenterPoint() {
PointF centerPoint = getCenterPoint();
float[] mappedPoints = getMappedPoints(new float[]{centerPoint.x, centerPoint.y});
return new PointF(mappedPoints[0], mappedPoints[1]);
}
public float[] getMappedPoints(float[] fArr) {
float[] fArr2 = new float[fArr.length];
this.a.mapPoints(fArr2, fArr);
return fArr2;
}
public Matrix getMatrix() {
return this.a;
}
public abstract int getWidth();
public boolean isFlipped() {
return this.b;
}
public void release() {
}
public abstract void setDrawable(Drawable drawable);
public void setFlipped(boolean z) {
this.b = z;
}
public void setMatrix(Matrix matrix) {
this.a.set(matrix);
}
public void setTag(String str) {
this.tag = str;
}
}
And this is : class BitmapStickerIcon
public class BitmapStickerIcon extends DrawableSticker {
public static final float DEFAULT_ICON_EXTRA_RADIUS = 10.0f;
public static final float DEFAULT_ICON_RADIUS = 30.0f;
private float x;
private float y;
private float mIconRadius ;
private float mIconExtraRadius ;
public BitmapStickerIcon(Drawable drwbl) {
super(drwbl); **//this is line #16 selected by compiler**
this.mIconRadius = 30.0f;
this.mIconExtraRadius = 10.0f;
}
public void draw(Canvas canvas, Paint paint) {
canvas.drawCircle(this.x, this.y, this.mIconRadius, paint);
super.draw(canvas);
}
public float getIconExtraRadius() {
return this.mIconExtraRadius;
}
public float getIconRadius() {
return this.mIconRadius;
}
public float getX() {
return this.x;
}
public float getY() {
return this.y;
}
public void setIconExtraRadius(float f) {
this.mIconExtraRadius = f;
}
public void setIconRadius(float f) {
this.mIconRadius = f;
}
public void setX(float f) {
this.x = f;
}
public void setY(float f) {
this.y = f;
}
}
Here : class StickerView
public class StickerView extends FrameLayout {
public static final float MAX_SCALE_SIZE = 3.2f;
public static final float MIN_SCALE_SIZE = 0.1f;
private static final String TAG = "StickerView";
public static float[] bitmapPoints;
public static boolean mLocked;
public static List<Sticker> mStickers = new ArrayList();
private Paint mBorderPaint;
private ActionMode mCurrentMode;
private BitmapStickerIcon mDeleteIcon;
private Matrix mDownMatrix;
private float mDownX;
private float mDownY;
private BitmapStickerIcon mEditIcon;
private BitmapStickerIcon mFlipIcon;
private Sticker mHandlingSticker;
private PointF mMidPoint;
private Matrix mMoveMatrix;
private float mOldDistance;
private float mOldRotation;
private OnStickerOperationListener mOnStickerOperationListener;
private Matrix mSizeMatrix;
private RectF mStickerRect;
private int mTouchSlop;
private BitmapStickerIcon mZoomIcon;
public static class kcm1 {
static final int[] aaz;
static {
int[] iArr = new int[ActionMode.values().length];
aaz = iArr;
try {
iArr[ActionMode.NONE.ordinal()] = 1;
} catch (NoSuchFieldError unused) {
}
try {
aaz[ActionMode.DRAG.ordinal()] = 2;
} catch (NoSuchFieldError unused2) {
}
try {
aaz[ActionMode.ZOOM_WITH_TWO_FINGER.ordinal()] = 3;
} catch (NoSuchFieldError unused3) {
}
try {
aaz[ActionMode.ZOOM_WITH_ICON.ordinal()] = 4;
} catch (NoSuchFieldError unused4) {
}
}
}
public enum ActionMode {
NONE,
DRAG,
ZOOM_WITH_TWO_FINGER,
ZOOM_WITH_ICON,
DELETE,
FLIP_HORIZONTAL,
CLICK
}
public interface OnStickerOperationListener {
void onStickerClicked(Sticker sticker);
void onStickerDeleted(Sticker sticker);
void onStickerDragFinished(Sticker sticker);
void onStickerEdit(Sticker sticker);
void onStickerFlipped(Sticker sticker);
void onStickerZoomFinished(Sticker sticker);
}
public StickerView(Context context) {
this(context, null); **//this line #111 selected by compiler**
}
public StickerView(Context context, AttributeSet attributeSet) {
this(context, attributeSet, 0);
}
public StickerView(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
this.mOldDistance = 0.0f;
this.mOldRotation = 0.0f;
this.mCurrentMode = ActionMode.NONE;
this.mTouchSlop = 3;
Paint paint = new Paint();
this.mBorderPaint = paint;
paint.setAntiAlias(true);
this.mBorderPaint.setColor(-16777216);
this.mBorderPaint.setAlpha(128);
this.mSizeMatrix = new Matrix();
this.mDownMatrix = new Matrix();
this.mMoveMatrix = new Matrix();
this.mStickerRect = new RectF();
**//Below line #129 the compiler select BitmapStickerIcon**
this.mDeleteIcon = new BitmapStickerIcon(ContextCompat.getDrawable(getContext(), R.drawable.ic_close_white_18dp));
this.mZoomIcon = new BitmapStickerIcon(ContextCompat.getDrawable(getContext(), R.drawable.ic_scale_white_18dp));
} ...more
I have no idea how to fix the errors, I have tested many solutions but nothing changed.
I will be happy for your help.
In the StickerView file:
Remove the StickerView(Context context) constructor
Put the initialization code also in the StickerView(Context context, AttributeSet attributeSet) constructor (creating a dedicated method is a good approach) and
Change this(context, attributeSet, 0) to super(context, attributeSet)
public StickerView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
setup();
}
public StickerView(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
setup();
}
private void setup() {
this.mOldDistance = 0.0f;
this.mOldRotation = 0.0f;
this.mCurrentMode = ActionMode.NONE;
this.mTouchSlop = 3;
Paint paint = new Paint();
this.mBorderPaint = paint;
paint.setAntiAlias(true);
this.mBorderPaint.setColor(-16777216);
this.mBorderPaint.setAlpha(128);
this.mSizeMatrix = new Matrix();
this.mDownMatrix = new Matrix();
this.mMoveMatrix = new Matrix();
this.mStickerRect = new RectF();
**//Below line #129 the compiler select BitmapStickerIcon**
this.mDeleteIcon = new BitmapStickerIcon(ContextCompat.getDrawable(getContext(), R.drawable.ic_close_white_18dp));
this.mZoomIcon = new BitmapStickerIcon(ContextCompat.getDrawable(getContext(), R.drawable.ic_scale_white_18dp));
}

Saving bitmaps to ArrayList makes Bitmaps whole black

I am trying to save bitmaps in an ArrayList. I generate 2 types of bitmaps, they are basically identical - drawn with a finger by the user.
The first bitmap is fully visible in activity
The second is stored dynamically in the ArrayList - it is a slice of the last x milliseconds from the visible bitmap - It will be further converting and sending by BT.
The problem is that the last bitmap in the ArrayList is well saved, while each previous bitmap turns into a black rectangle when you add another one.
Relevant code snippets:
private ArrayList<Bitmap> bitmapsListToSend = new ArrayList<>();
private ArrayList<Canvas> canvasListToSend = new ArrayList<>();
mBitmapToShow = Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565);
mCanvasToShow = new Canvas(mBitmapToShow);
bitmapsListToSend.add(Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565))
//mCanvasToSend = new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1));
canvasListToSend.add(new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1)));;
I tried to make separate Canvas to each bitmap without success
public class PaintView extends View {
private final Paint mPaintToShow = new Paint();
private Bitmap mBitmapToShow;
private Canvas mCanvasToShow;
private final Paint mPaintToSend = new Paint();
//private Canvas mCanvasToSend;
private TouchPoint startPoint;
#Nullable
private ArrayList<Bitmap> bitmapsListToSend = new ArrayList<>();
private ArrayList<Canvas> canvasListToSend = new ArrayList<>();
private int bitmapCounter = 0;
private int alpha = 1;
/* debug */
Stopwatch watch = Stopwatch.createUnstarted();
public PaintView(Context c) {
super(c);
setFocusable(true);
mPaintToShow.setAntiAlias(true);
mPaintToShow.setColor(BLACK);
mPaintToShow.setAlpha(alpha);
mPaintToShow.setStrokeJoin(Paint.Join.ROUND);
mPaintToShow.setStrokeCap(Paint.Cap.ROUND);
mPaintToSend.setAntiAlias(true);
mPaintToSend.setColor(BLACK);
mPaintToSend.setStrokeJoin(Paint.Join.ROUND);
mPaintToSend.setStrokeCap(Paint.Cap.ROUND);
mBitmapToShow = Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565);
mCanvasToShow = new Canvas(mBitmapToShow);
bitmapsListToSend.add(Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565));
//mCanvasToSend = new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1));
canvasListToSend.add(new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1)));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCanvasToShow.drawColor(Color.WHITE);
//mCanvasToSend.drawColor(Color.WHITE);
canvasListToSend.get(canvasListToSend.size()-1).drawColor(WHITE);
}
public void clear() {
if (mCanvasToShow != null) {
mPaintToShow.setColor(Color.WHITE);
mCanvasToShow.drawPaint(mPaintToShow);
//mCanvasToSend.drawPaint(mPaintToShow);
bitmapCounter=0;
alpha=1;
bitmapsListToSend.clear();
canvasListToSend.clear();
mPaintToShow.setColor(BLACK);
watch.reset();
invalidate();
}
}
#Override
protected void onDraw(Canvas canvas) {
if (mBitmapToShow != null) {
canvas.drawBitmap(mBitmapToShow, 0, 0, null);
//mCanvasToSend.drawBitmap(bitmapsListToSend.get(bitmapsListToSend.size()-1), 0, 0, null);
}
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event) {
return onTouchOrHoverEvent(event, true /*isTouch*/);
}
private boolean onTouchOrHoverEvent(MotionEvent event, boolean isTouch) {
/*if (SENDING_NOW)
return true;*/
final int action = event.getActionMasked();
mPaintToShow.setStrokeWidth((float) ( getBrushSize() ));
if (action == MotionEvent.ACTION_DOWN) {
startPoint = new TouchPoint(event, 0);
runnableSaveBitmaps.run();
runnableChangeAlpha.run();
watch.start();
}else if(action == MotionEvent.ACTION_MOVE){
runnableChangeAlpha.run();
}else if (action == MotionEvent.ACTION_UP) {
startPoint = new TouchPoint(event, 0);
handlerSaveBitmaps.removeCallbacks(runnableSaveBitmaps);
handlerChangeAlpha.removeCallbacks(runnableChangeAlpha);
watch.stop();
}
//make drawings//
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
paintLines(mTouchPoints);
break;
case MotionEvent.ACTION_DOWN:
mCanvasToShow.drawCircle(startPoint.x, startPoint.y, getBrushSize()/2f, mPaintToShow);
//mCanvasToSend.drawCircle(startPoint.x, startPoint.y, getBrushSize()/2f, mPaintToSend);
canvasListToSend.get(canvasListToSend.size()-1).drawCircle(startPoint.x, startPoint.y, getBrushSize()/2f, mPaintToSend);
break;
}
invalidate();
}
return true;
}
//drawing methods//
Handler handlerSaveBitmaps = new Handler();
Runnable runnableSaveBitmaps = new Runnable() {
public void run() {
handlerSaveBitmaps.postDelayed(runnableSaveBitmaps, 10);
Log.v("B", "Bitmap added " + bitmapCounter + " " + (watch.toString()));
bitmapsListToSend.add(bitmapCounter, Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565));
canvasListToSend.add(bitmapCounter++, new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1)));
}
};
Handler handlerChangeAlpha = new Handler();
Runnable runnableChangeAlpha = new Runnable() {
#Override
public void run() {
handlerChangeAlpha.postDelayed(runnableChangeAlpha, 635);
if(alpha < 255)
mPaintToShow.setAlpha(alpha++);
else {
handlerChangeAlpha.removeCallbacks(runnableChangeAlpha);
Log.v("A", "ALPHA MAX" + (watch.toString()));
}
}
};
}
If Runnable saves 100 bitmaps - 99 will be black, the last one will be ok
//Bitmap.copy() fixed it

Remove the last color form bitmap Undo

Please I need the help regarding Undo method , I tried to implement it like the code below but it is not remove the last color,
Kindly help me to resolve it.
awaiting your kind response.
Thanks in Advance.
MainActivity
public class MainActivity extends AppCompatActivity implements
View.OnTouchListener {
Button red, blue, yellow, undo;
Paint paint;
private RelativeLayout drawingLayout;
private MyView myView;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
/**
* Called when the activity is first created.
*/
/*
*
* private ImageView imageView; private Canvas cv; private Bitmap mask,
* original, colored; private int r,g,b; private int sG, sR, sB;
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myView = new MyView(this);
drawingLayout = (RelativeLayout) findViewById(R.id.relative_layout);
drawingLayout.addView(myView);
red = (Button) findViewById(R.id.btn_red);
blue = (Button) findViewById(R.id.btn_blue);
yellow = (Button) findViewById(R.id.btn_yellow);
undo = (Button) findViewById(R.id.undo);
red.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
paint.setColor(Color.RED);
}
});
yellow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
paint.setColor(Color.YELLOW);
}
});
blue.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
paint.setColor(Color.BLUE);
}
});
undo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.onClickUndo();
}
});
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
// flood fill
public class MyView extends View {
final Point p1 = new Point();
Bitmap mBitmap;
ProgressDialog pd;
Canvas canvas;
private Path path;
// Bitmap mutableBitmap ;
public MyView(Context context) {
super(context);
paint = new Paint();
paint.setAntiAlias(true);
pd = new ProgressDialog(context);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(5f);
mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.gp1_1).copy(Bitmap.Config.ARGB_8888, true);
this.path = new Path();
}
public void onClickUndo() {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
invalidate();
} else {
Toast.makeText(getContext(), getString(R.string.nomore), Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onDraw(Canvas canvas) {
this.canvas = canvas;
paint.setColor(Color.GREEN);
// int width = drawingLayout.getWidth();
// int height = drawingLayout.getHeight();
// float centerX = (width - mBitmap.getWidth()) * 0.5f;
//float centerY = (height - mBitmap.getHeight()) * 0.5f;
canvas.drawBitmap(mBitmap, 0, 0, paint);
///////////////////////////////
for (Path p : paths) {
canvas.drawPath(p, paint);
//////////////////////////
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
p1.x = (int) x;
p1.y = (int) y;
final int sourceColor = mBitmap.getPixel((int) x, (int) y);
final int targetColor = paint.getColor();
new TheTask(mBitmap, p1, sourceColor, targetColor).execute();
paths.add(path);
invalidate();
}
return true;
}
public void clear() {
path.reset();
invalidate();
}
public int getCurrentPaintColor() {
return paint.getColor();
}
class TheTask extends AsyncTask<Void, Integer, Void> {
Bitmap bmp;
Point pt;
int replacementColor, targetColor;
public TheTask(Bitmap bm, Point p, int sc, int tc) {
this.bmp = bm;
this.pt = p;
this.replacementColor = tc;
this.targetColor = sc;
pd.setMessage(getString(R.string.wait));
pd.show();
}
#Override
protected void onPreExecute() {
pd.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
}
#Override
protected Void doInBackground(Void... params) {
FloodFill f = new FloodFill();
f.floodFill(bmp, pt, targetColor, replacementColor);
return null;
}
#Override
protected void onPostExecute(Void result) {
pd.dismiss();
invalidate();
}
}
}
public class FloodFill {
public void floodFill(Bitmap image, Point node, int targetColor,
int replacementColor) {
int width = image.getWidth();
int height = image.getHeight();
int target = targetColor;
int replacement = replacementColor;
if (target != replacement) {
Queue<Point> queue = new LinkedList<Point>();
do {
int x = node.x;
int y = node.y;
while (x > 0 && image.getPixel(x - 1, y) == target) {
x--;
}
boolean spanUp = false;
boolean spanDown = false;
while (x < width && image.getPixel(x, y) == target) {
image.setPixel(x, y, replacement);
if (!spanUp && y > 0
&& image.getPixel(x, y - 1) == target) {
queue.add(new Point(x, y - 1));
spanUp = true;
} else if (spanUp && y > 0
&& image.getPixel(x, y - 1) != target) {
spanUp = false;
}
if (!spanDown && y < height - 1
&& image.getPixel(x, y + 1) == target) {
queue.add(new Point(x, y + 1));
spanDown = true;
} else if (spanDown && y < height - 1
&& image.getPixel(x, y + 1) != target) {
spanDown = false;
}
x++;
}
} while ((node = queue.poll()) != null);
}
}
}
}
I guess you mean the undo method doesn't work. The possible reason is the previous drawing on the canvas is not removed. Try clearing the canvas before drawing in the onDraw() method.
#Override protected void onDraw(Canvas canvas) {
this.canvas = canvas;
canvas. drawColor(0,PorterDuff.Mode.CLEAR); //This clears the canvas.
paint.setColor(Color.GREEN);
//rest of the code
}
Seems it is impossible to return previous color it is required an array for each point to store the used color in every point.

Changing path size without changing previous paths

I have an app for erasing the background, And I used a seekbar for changing the size of Eraser. but when I change the progress of SeekBar, the previous path change.
I want to change the path size without changing the previous paths
Main Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image_overlay_bitmap);
scratchView = (WScratchView) findViewById(R.id.scratch_view);
global = ((Global) getApplicationContext());
scratchView.setRevealSize(1);
SeekBar seekbar = (SeekBar) findViewById(R.id.myseek);
seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
scratchView.setRevealSize(progress);
}
});
if (getIntent().getExtras().getBoolean("isFromCrop")) {
Log.i("width", "" + global.getBitmap().getWidth());
Log.i("height", "" + global.getBitmap().getHeight());
// set bitmap to scratchview
// Bitmap bitmap =
// BitmapFactory.decodeResource(getResources(),R.drawable.test);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
/*
* int height = displaymetrics.heightPixels; int width =
* displaymetrics.widthPixels;
*/
int height = global.getBitmap().getHeight();
int width = global.getBitmap().getWidth();
Bitmap scaledBitmap = Bitmap.createBitmap(width, height,
Config.ARGB_8888);
float ratioX = width / (float) global.getBitmap().getWidth();
float ratioY = height / (float) global.getBitmap().getHeight();
float middleX = width / 2.0f;
float middleY = height / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(global.getBitmap(), middleX
- global.getBitmap().getWidth() / 2, middleY
- global.getBitmap().getHeight() / 2, new Paint(
Paint.FILTER_BITMAP_FLAG));
i = seekbar.getProgress();
scratchView.setRevealSize(i);
} else {
SharedPreferences settings = getApplicationContext()
.getSharedPreferences("pref", 0);
settings = getApplicationContext().getSharedPreferences("pref", 0);
String picture = settings.getString("file_path", "");
Bitmap mbitmap = BitmapFactory.decodeFile(picture);
scratchView.setScratchBitmap(mbitmap);
}
/*
* scratchView.setScratchBitmap(getResizedBitmap(global.getBitmap(),
* width, height));
*/
// scratchView.setOverlayColor(1);
//i = seekbar.getProgress();
// seekbar.setMax(100);
}
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Log.i("scalewidth", "" + scaleWidth);
Log.i("scaleheight", "" + scaleHeight);
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// RECREATE THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
return resizedBitmap;
}
private File captureImage() {
// TODO Auto-generated method stub
OutputStream output;
Calendar cal = Calendar.getInstance();
Bitmap bitmap = Bitmap.createBitmap(scratchView.getWidth(),
scratchView.getHeight(), Config.ARGB_8888);
bitmap = ThumbnailUtils.extractThumbnail(bitmap,
scratchView.getWidth(), scratchView.getHeight());
Canvas b = new Canvas(bitmap);
scratchView.draw(b);
// Find the SD Card path
File filepath = Environment.getExternalStorageDirectory();
// Create a new folder in SD Card
File dir = new File(filepath.getAbsolutePath() + "/demotemp/");
dir.mkdirs();
mImagename = "imageTemp" + ".png";
// Create a name for the saved image
file = new File(dir, mImagename);
// Show a toast message on successful save
Toast.makeText(ImageOverlayBitmap.this, "Image Saved to SD Card",
Toast.LENGTH_SHORT).show();
try {
output = new FileOutputStream(file);
// Compress into png format image from 0% - 100%
bitmap.compress(Bitmap.CompressFormat.PNG, 100, output);
output.flush();
output.close();
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return file;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public void onClickHandler(View view) {
switch (view.getId()) {
case R.id.reset_button:
captureImage();
SharedPreferences settings = getApplicationContext()
.getSharedPreferences("pref", 0);
settings = getApplicationContext().getSharedPreferences("pref", 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString("file_path", file.getPath());
editor.commit();
Intent i = new Intent(ImageOverlayBitmap.this,
SelectedImgActivity.class);
global.setfile_path(file.getPath());
i.putExtra("isBackgroundSet", false);
startActivity(i);
finish();
// scratchView.resetView();
break;
}
} }
Draw Activity
public WScratchView(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
init(ctx, attrs);
}
public WScratchView(Context context) {
super(context);
init(context, null);
}
private void init(Context context, AttributeSet attrs) {
mContext = context;
// default value
mOverlayColor = DEFAULT_COLOR;
mRevealSize = DEFAULT_REVEAL_SIZE;
setZOrderOnTop(true);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
holder.setFormat(PixelFormat.TRANSPARENT);
mOverlayPaint = new Paint();
mOverlayPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
mOverlayPaint.setStyle(Paint.Style.STROKE);
mOverlayPaint.setStrokeCap(Paint.Cap.ROUND);
mOverlayPaint.setStrokeJoin(Paint.Join.ROUND);
// convert drawable to bitmap if drawable already set in xml
if (mScratchDrawable != null) {
mScratchBitmap = ((BitmapDrawable) mScratchDrawable).getBitmap();
}
mBitmapPaint = new Paint();
mBitmapPaint.setAntiAlias(true);
mBitmapPaint.setFilterBitmap(true);
mBitmapPaint.setDither(true);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mScratchBitmap != null) {
if (mMatrix == null) {
float scaleWidth = (float) canvas.getWidth() / mScratchBitmap.getWidth();
float scaleHeight = (float) canvas.getHeight() / mScratchBitmap.getHeight();
mMatrix = new Matrix();
mMatrix.postScale(scaleWidth, scaleHeight);
}
canvas.drawBitmap(mScratchBitmap, mMatrix, mBitmapPaint);
} else {
canvas.drawColor(mOverlayColor);
}
for (Path path : mPathList) {
mOverlayPaint.setAntiAlias(mIsAntiAlias);
mOverlayPaint.setStrokeWidth(mRevealSize);
canvas.drawPath(path, mOverlayPaint);
}
}
private void updateScratchedPercentage() {
if(mOnScratchCallback == null) return;
mOnScratchCallback.onScratch(getScratchedRatio());
}
#Override
public boolean onTouchEvent(MotionEvent me) {
synchronized (mThread.getSurfaceHolder()) {
if (!mIsScratchable) {
return true;
}
switch (me.getAction()) {
case MotionEvent.ACTION_DOWN:
path = new Path();
path.moveTo(me.getX(), me.getY());
startX = me.getX();
startY = me.getY();
mPathList.add(path);
break;
case MotionEvent.ACTION_MOVE:
//if (mScratchStart) {
if (path.isEmpty()) {
path.lineTo(me.getX(), me.getY());
} else {
if (isScratch(startX, me.getX(), startY, me.getY())) {
mScratchStart = true;
}
updateScratchedPercentage();
break;
case MotionEvent.ACTION_UP:
mPathList.add(path);
// mScratchStart = false;
break;
}
return true;
}
}
private boolean isScratch(float oldX, float x, float oldY, float y) {
float distance = (float) Math.sqrt(Math.pow(oldX - x, 2) + Math.pow(oldY - y, 2));
if (distance > mRevealSize * 2) {
return true;
} else {
return false;
}
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// do nothing
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mScratchedTestBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mScratchedTestCanvas = new Canvas(mScratchedTestBitmap);
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
mThread = new WScratchViewThread(getHolder(), this);
mThread.setRunning(true);
mThread.start();
mScratchedTestBitmap = Bitmap.createBitmap(arg0.getSurfaceFrame().width(), arg0.getSurfaceFrame().height(), Bitmap.Config.ARGB_8888);
mScratchedTestCanvas = new Canvas(mScratchedTestBitmap);
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
boolean retry = true;
mThread.setRunning(false);
while (retry) {
try {
mThread.join();
retry = false;
} catch (InterruptedException e) {
// do nothing but keep retry
}
}
}
class WScratchViewThread extends Thread {
private SurfaceHolder mSurfaceHolder;
private WScratchView mView;
private boolean mRun = false;
public WScratchViewThread(SurfaceHolder surfaceHolder, WScratchView view) {
mSurfaceHolder = surfaceHolder;
mView = view;
}
public void setRunning(boolean run) {
mRun = run;
}
public SurfaceHolder getSurfaceHolder() {
return mSurfaceHolder;
}
#Override
public void run() {
Canvas c;
while (mRun) {
c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
if (c != null) {
mView.draw(c);
}
}
} finally {
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
#Override
public void resetView() {
synchronized (mThread.getSurfaceHolder()) {
mPathList.clear();
}
}
#Override
public boolean isScratchable() {
return mIsScratchable;
}
#Override
public void setScratchable(boolean flag) {
mIsScratchable = flag;
}
#Override
public void setOverlayColor(int ResId) {
mOverlayColor = ResId;
}
#Override
public void setRevealSize(int size) {
Canvas canvas = new Canvas();
//mScratchedTestBitmap = Bitmap.createBitmap(mScratchedTestBitmap.getWidth(), mScratchedTestBitmap.getWidth(), Bitmap.Config.ARGB_8888);
//mScratchedTestCanvas = new Canvas(mScratchedTestBitmap);
canvas.drawBitmap(mScratchBitmap,mMatrix, mBitmapPaint);
mRevealSize = size;
}
#Override
public void setAntiAlias(boolean flag) {
mIsAntiAlias = flag;
}
#Override
public void setScratchDrawable(Drawable d) {
mScratchDrawable = d;
if (mScratchDrawable != null) {
mScratchBitmap = ((BitmapDrawable) mScratchDrawable).getBitmap();
}
}
#Override
public void setScratchBitmap(Bitmap b) {
mScratchBitmap = b;
}
#Override
public float getScratchedRatio() {
return getScratchedRatio(DEFAULT_SCRATCH_TEST_SPEED);
}
/**
* thanks to https://github.com/daveyfong for providing this method
*/
#Override
public float getScratchedRatio(int speed) {
if (null == mScratchedTestBitmap) {
return 0;
}
draw(mScratchedTestCanvas);
final int width = mScratchedTestBitmap.getWidth();
final int height = mScratchedTestBitmap.getHeight();
int count = 0;
for (int i = 0; i < width; i += speed) {
for (int j = 0; j < height; j += speed) {
if (0 == Color.alpha(mScratchedTestBitmap.getPixel(i, j))) {
count++;
}
}
}
float completed = (float) count / ((width / speed) * (height / speed)) * 100;
return completed;
}
public void setOnScratchCallback(OnScratchCallback callback) {
mOnScratchCallback = callback;
}
public static abstract class OnScratchCallback{
public abstract void onScratch(float percentage);
}
#Override
public void setScratchAll(boolean scratchAll) {
// TODO Auto-generated method stub
}
#Override
public void setBackgroundClickable(boolean clickable) {
// TODO Auto-generated method stub
} }
I noticed that in your onDraw() routine, you are setting the stroke width of every path to mRevealSize. Also, this mRevealSize is what is changed by the SeekBar.
I think what you need to do is capture the stroke width mRevealSize every time an erase path is made by the user, and store that stroke width in a list that complements mPathList. Then your onDraw() would have:
for (int i = 0; i < mPathList.size(); i++) {
mOverlayPaint.setAntiAlias(mIsAntiAlias);
mOverlayPaint.setStrokeWidth(mStrokeList.get(i));
canvas.drawPath(mPathList.get(i), mOverlayPaint);
}

How to extract the Bitmap out of the onDraw() method of a View?

How can I extract a Bitmap object out of my onDraw() routine in my CustomView?
Here is my code:
public class DrawView extends View {
private Paint paint = new Paint();
private Point point;
private LinkedList<Point> listaPontos;
private static Context context;
class Point {
public Point(float x, float y) {
this.x = x;
this.y = y;
}
float x = 0;
float y = 0;
}
public DrawView(Context context) {
super(context);
this.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
this.context = context;
paint.setColor(Color.YELLOW);
this.listaPontos = new LinkedList<Point>();
}
#Override
public void onDraw(Canvas canvas) {
if(listaPontos.size() != 0){
for(Point point : listaPontos){
canvas.drawCircle(point.x, point.y, 25, paint);
}
}
calculateAmount(canvas);
}
private void calculateAmount(Canvas canvas) {
LinkedList<Integer> colors = new LinkedList<Integer>();
for(int i = 0 ; i != canvas.getWidth(); i++)
{
for(int j = 0; j != canvas.getHeight(); j++){
int color = BITMAP.getPixel(i,j); //How can I get the bitmap generated on onDraw ?
colors.add(color);
}
}
int yellow = 0;
int white = 0;
for(Integer cor : colors) {
if(cor == Color.WHITE) {
white++;
}
if(cor == Color.YELLOW) {
yellow++;
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
listaPontos.add(new Point(event.getX(), event.getY()));
break;
}
invalidate();
return true;
}
}
Thanks alot in advance ;)
EDIT: The bitmap thing is to calculate each pixel color, how can I add a background image to my DrawView ? I tested this.setBackgroundResource(R.drawable.a); at constructor but didn't work, thanks again ;)
There is no way to extract a Bitmap out of a Canvas. At least not directly.
However, it is possible to draw on a Bitmap with the Canvas and then use the Bitmap.
Bitmap mDrawBitmap;
Canvas mBitmapCanvas;
Paint drawPaint = new Paint();
#Override
public void onDraw(Canvas canvas) {
drawPaint.setColor(Color.RED);
if (mDrawBitmap == null) {
mDrawBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
mBitmapCanvas = new Canvas(mDrawBitmap);
}
// clear previously drawn stuff
mBitmapCanvas.drawColor(Color.WHITE);
// draw on the btimapCanvas
mBitmapCanvas.drawStuff(...);
//... and more
// after drawing with the bitmapcanvas,
//all drawn information is stored in the Bitmap
// draw everything to the screen
canvas.drawBitmap(mDrawBitmap, 0, 0, drawPaint);
}
After the onDraw() method has finished, all drawn information will be drawn on the screen (by calling canvas.drawBitmap(...), and also be stored in your Bitmap object (because all draw operations have been done on the Canvas that was created with the Bitmap).

Categories