Create image mask in android with 9png - android

So I have this 9png :
And I have this image :
I need to achieve something like this:
This is the closest I can get to it:
This is how I tried to do it:
public class CustomView extends ImageView {
private Bitmap mImage;
private Bitmap mMask;
private int mPosX = 0;
private int mPosY = 0;
private final Paint maskPaint;
private final Paint imagePaint;
public CustomView(Context context) {
super(context);
maskPaint = new Paint();
maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
imagePaint = new Paint();
imagePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
mImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.dummy_video);
mMask = BitmapFactory.decodeResource(context.getResources(), R.drawable.friend_bubble);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.drawBitmap(mMask, 0, 0, maskPaint);
canvas.drawBitmap(mImage, mPosX, mPosY, imagePaint);
canvas.restore();
}
}
My guess is that the 9png just keeps on drawing and doesn't know when to stop.
Can anyone help? :)

Related

How to add a imageView in the centre of a customView?

I have a custom view that is a circle. Here is the code for my CircleView:
public class CircleView extends View {
private static final int START_ANGLE_POINT = 90;
private final Paint paint;
private final RectF rect;
private float angle;
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
final int strokeWidth = 40;
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(strokeWidth);
//Circle color
paint.setColor(Color.RED);
rect = new RectF(strokeWidth, strokeWidth, 1000 + strokeWidth, 1000 + strokeWidth);
//Initial angle is zero
angle = 0;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(rect, START_ANGLE_POINT, angle, false, paint);
}
public float getAngle() {
return angle;
}
public void setAngle(float angle) {
this.angle = angle;
} }
and here is how I declare it in the xml layout of an activity:
<com.my_package.ui.recording.CircleView
android:id="#+id/circleView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
All standard stuff. This is how my custom image looks like
Now, I want to place an imageView in the centre on the circleView? Does any one know how can I achieve that?
This is ideally what I would like to end up with:
Thank you in advance.
If you aren't set on using an ImageView and really just want to draw the bitmap in the center then have a look at canvas' drawBitmap method. This will allow you to draw it however/wherever you want.

Make Image view rounded (not the image)

Requirement is to:
Req 1 : Fetch images from url
R2: save them in cache
R3: make ImageView rounded not the image
So for R1 & R2 I found a library:
http://loopj.com/android-smart-image-view/
For R3 I've done a lot of R&D , & everything I found converts the image not the ImageView. This is what I've searched:
Mask ImageView with round corner background
How to make an ImageView with rounded corners?
https://github.com/vinc3m1/RoundedImageView
https://github.com/lopspower/CircularImageView
I know it's possible to use the ImageView bitmap & get the image rounded but with the specific library I want to use that isn't possible(maybe possible with very complex threading).
So please help me to get the ImageView rounded not the image.
so this is the minimalistic version:
class RoundImageView extends ImageView {
private static final int RADIUS = 32;
private Paint mPaint;
private Paint mSrcIn;
private RectF mRect;
public RoundImageView(Context context) {
super(context);
// setBackgroundColor(0xffffffff);
mSrcIn = new Paint();
mSrcIn.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRect = new RectF();
}
#Override
public void onDraw(Canvas canvas) {
Drawable dr = getDrawable();
if (dr != null) {
mRect.set(dr.getBounds());
getImageMatrix().mapRect(mRect);
mRect.offset(getPaddingLeft(), getPaddingTop());
int rtc = canvas.saveLayer(mRect, null, Canvas.ALL_SAVE_FLAG);
// draw DST
canvas.drawRoundRect(mRect, RADIUS, RADIUS, mPaint);
canvas.saveLayer(mRect, mSrcIn, Canvas.ALL_SAVE_FLAG);
// draw SRC
super.onDraw(canvas);
canvas.restoreToCount(rtc);
}
}
}
or use even shorter one when hardware acceleration is not used and you can use Canvas.clipPath:
class RoundImageViewClipped extends ImageView {
private static final int RADIUS = 32;
private RectF mRect;
private Path mClip;
public RoundImageViewClipped(Context context) {
super(context);
// setBackgroundColor(0xffffffff);
mRect = new RectF();
mClip = new Path();
}
#Override
public void onDraw(Canvas canvas) {
Drawable dr = getDrawable();
if (dr != null) {
mRect.set(dr.getBounds());
getImageMatrix().mapRect(mRect);
mRect.offset(getPaddingLeft(), getPaddingTop());
mClip.reset();
mClip.addRoundRect(mRect, RADIUS, RADIUS, Direction.CCW);
canvas.clipPath(mClip);
super.onDraw(canvas);
}
}
}
I'm pretty sure you can't "make the ImageView round," since all Views are actually rectangular, so what you're going to have to do is fake it.
Use a method like this to cut a circle from the image:
public Bitmap getRoundedBitmap(Bitmap scaleBitmapImage) {
int targetRadius = scaleBitmapImage.getWidth();
if(targetRadius > scaleBitmapImage.getHeight()) targetRadius = scaleBitmapImage.getHeight();
Bitmap targetBitmap = Bitmap.createBitmap(targetRadius, targetRadius, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(targetBitmap);
Path path = new Path();
path.addCircle(((float) scaleBitmapImage.getWidth() - 1) / 2, ((float) scaleBitmapImage.getHeight() - 1) / 2, (Math.min(((float) scaleBitmapImage.getWidth()), ((float) scaleBitmapImage.getHeight())) / 2), Path.Direction.CCW);
canvas.clipPath(path);
Bitmap sourceBitmap = scaleBitmapImage;
canvas.drawBitmap(sourceBitmap, new Rect(0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight()), new Rect(0, 0, scaleBitmapImage.getWidth(), scaleBitmapImage.getHeight()), null);
return targetBitmap;
}
Since the clipped part is transparent, it will appear as if the actual View is a circle. Also make sure that the bounds of the View are squared (or that adjustViewBounds="true") else you may get visual distortions in terms of width or height.
Pretty sure that's as close to a "rounded View" as you can actually get.
How about the solution give by Romain Guy to use a custom Drawable. You're ImageView will not be round and your source image will be untouched.
class StreamDrawable extends Drawable {
private final float mCornerRadius;
private final RectF mRect = new RectF();
private final BitmapShader mBitmapShader;
private final Paint mPaint;
private final int mMargin;
StreamDrawable(Bitmap bitmap, float cornerRadius, int margin) {
mCornerRadius = cornerRadius;
mBitmapShader = new BitmapShader(bitmap,
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShader(mBitmapShader);
mMargin = margin;
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRect.set(mMargin, mMargin, bounds.width() - mMargin, bounds.height() - mMargin);
}
#Override
public void draw(Canvas canvas) {
canvas.drawRoundRect(mRect, mCornerRadius, mCornerRadius, mPaint);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
#Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}
}
You can add rounded corners in a android view with the GradientDrawable.
So ,
GradientDrawable gd = new GradientDrawable();
gd.setColor(Color.TRANSPARENT);
gd.setCornerRadius(15f);
gd.setStroke(1f,Color.BLACK);
yourImageView.setBackground(gd);
SmartImageView extends from ImageView .. so you just have to extend from SmartImageView
Here is a working solution (based on pskink code & smartImageView lib )
Create a new Class
public class RoundedCornersSmartImageView extends SmartImageView{
private int RADIUS = 0;
private RectF mRect;
private Path mClip;
public RoundedCornersSmartImageView(Context context) {
super(context);
init();
}
public RoundedCornersSmartImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundedCornersSmartImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
#Override
public void onDraw(Canvas canvas) {
Drawable dr = getDrawable();
if (dr != null) {
mRect.set(dr.getBounds());
getImageMatrix().mapRect(mRect);
mRect.offset(getPaddingLeft(), getPaddingTop());
mClip.reset();
mClip.addRoundRect(mRect, RADIUS, RADIUS, Path.Direction.CCW);
canvas.clipPath(mClip);
super.onDraw(canvas);
}
}
public void setRadius(int radius){
this.RADIUS = radius;
}
private void init(){
mRect = new RectF();
mClip = new Path();
}
}
USAGE
in your layout file your SmartimageView should look like this
<your.package.path.RoundedCornersSmartImageView
android:id="#+id/list_image"
android:layout_width="60dip"
android:layout_height="60dip"
android:src="#drawable/profile_anonyme_thumb"/>
..and init the view in your code this way
RoundedCornersSmartImageView thumb_image=(RoundedCornersSmartImageView) findViewById(R.id.list_image);
thumb_image.setRadius(4);
//SmartImageView methode
thumb_image.setImageUrl(bla.MY_THUMB_URL));
Edit your radius for a round image ..

Android, Why my custom square ImageView on emulator has curve corner while on real device doesn't have?

I need to have square image view with curved corner. Everything seems okay and Preview of IntelliJ Idea shows it's working fine. However corners are not curve when I run it on real device.
My custom ImgeView:
public class SquareImageView extends ImageView {
private static final String TAG = "SquareImageView";
public SquareImageView(Context context) {
super(context);
}
public SquareImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int h = this.getMeasuredHeight();
int w = this.getMeasuredWidth();
setMeasuredDimension(w, w);
}
#Override
protected void onDraw(Canvas canvas) {
Path clipPath = new Path();
float radius = 20.0f;
float padding = radius / 2;
int w = this.getWidth();
int h = this.getHeight();
clipPath.addRoundRect(new RectF(padding, padding, w - padding, h - padding), radius, radius, Path.Direction.CW);
canvas.clipPath(clipPath);
canvas.drawColor(Color.RED);
super.onDraw(canvas);
}
}
XML of layout:
<com.belldigital.widget.SquareImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/ivProfilePicture"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_alignParentTop="true"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:background="#color/Black"
android:contentDescription="#string/general_content_description"
android:src="#drawable/ic_default_logo"
android:layout_marginTop="#dimen/side_margin"/>
Screenshot of emulator:
Screenshot of real device:
How to make an ImageView with rounded corners?
public class MainActivity extends Activity {
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView1);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.photo1);
imageView.setImageBitmap(getRoundedCornerBitmap(bitmap, 10));
}
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}

Android: Draw image on canvas where the user touches

so I have a canvas, and I would like a certain image (Lets say image.png) to appear where the user touches. What would I use? OnTouch?
Can someone help me out? Here is my canvas class below. Right now I have a few random images and shapes drawn, but they happen right away, not when someone touches like I would like it.
Thanks in advance!
public class MyView extends View
private Canvas canvas;
private Bitmap bitmap;
public MyView(Context context) {
super(context);
}
protected void onSizeChanged(int curw, int curh, int oldw, int oldh) {
if (bitmap != null) {
bitmap .recycle();
}
canvas= new Canvas();
bitmap = Bitmap.createBitmap(curw, curh, Bitmap.Config.ARGB_8888);
canvas.setBitmap(bitmap);
}
public void destroy() {
if (bitmap != null) {
bitmap.recycle();
}
}
public void onTouch(Canvas canvas) {
Bitmap _scratch = BitmapFactory.decodeResource(getResources(), R.drawable.test);
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(_scratch, 0, 0, null);
}
public void onDraw(Canvas canvas) {
//draw onto the canvas
Bitmap _scratch1 = BitmapFactory.decodeResource(getResources(), R.drawable.spacecat);
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(_scratch1, 0, 0, null);
Paint myPaint = new Paint();
myPaint.setStrokeWidth(4);
myPaint.setColor(0xFF097286);
canvas.drawCircle(240, 40, 30, myPaint);
myPaint.setColor(0xFFF07222);
Point p1 = new Point();
Point p2 = new Point();
p1.x = 0;
p1.y = 0;
p2.x = 40;
p2.y = 55;
canvas.drawLine(p1.x, p1.y, p2.x, p2.y, myPaint);
float[] pts = new float[8];
pts[0] = 100;
pts[1] = 5;
pts[2] = 97;
pts[3] = 9;
pts[4] = 90;
pts[5] = 15;
pts[6] = 84;
pts[7] = 20;
myPaint.setColor(0xFF40FF40);
myPaint.setStrokeWidth(9);
myPaint.setAntiAlias(true);
canvas.drawPoints(pts, myPaint);
myPaint.setColor(0xFFF0FF00);
myPaint.setStrokeWidth(4);
myPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(110, 150, 100, myPaint);
}}
I wrote an example for you :
public class MyView extends View {
boolean touching = false;
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas); //To change body of overridden methods use File | Settings | File Templates.
if (touching) {
//You can draw other thing here. just draw bitmap for example.
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
Rect source = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
Rect bitmapRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
canvas.drawBitmap(bitmap, source, bitmapRect, new Paint());
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touching = true;
invalidate();
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
touching = false;
invalidate();
break;
}
return super.onTouchEvent(event); //To change body of overridden methods use File | Settings | File Templates.
}
}

Erase bitmap parts using PorterDuff mode

I try to erase parts of a bitmap in my Android application by using Porter-Duff Xfermodes.
I have a green background which is overlayed by a blue bitmap. When I touch the screen a "hole" in the overlaying bitmap is supposed to be created making the green background visible. Instead of a hole my current code produces a black dot.
Below is my code. Any ideas, what I am doing wrong here?
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new DrawView(this));
}
public class DrawView extends View implements OnTouchListener {
private int x = 0;
private int y = 0;
Bitmap bitmap;
Canvas bitmapCanvas;
private final Paint paint = new Paint();
private final Paint eraserPaint = new Paint();
public DrawView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
// Set background
this.setBackgroundColor(Color.GREEN);
// Set bitmap
bitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.RGB_565);
bitmapCanvas = new Canvas();
bitmapCanvas.setBitmap(bitmap);
bitmapCanvas.drawColor(Color.BLUE);
// Set eraser paint properties
eraserPaint.setAlpha(0);
eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
eraserPaint.setAntiAlias(true);
}
#Override
public void onDraw(Canvas canvas) {
bitmapCanvas.drawColor(Color.BLUE);
bitmapCanvas.drawCircle(x, y, 10, eraserPaint);
canvas.drawBitmap(bitmap, 0, 0, paint);
}
public boolean onTouch(View view, MotionEvent event) {
x = (int) event.getX();
y = (int) event.getY();
invalidate();
return true;
}
}
Here is working code... may help somebody
public class ImageDemo extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new Panel(this));
}
class Panel extends View {
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mPaint;
Bitmap bitmap;
Canvas pcanvas;
int x = 0;
int y =0;
int r =0;
public Panel(Context context) {
super(context);
Log.v("Panel", ">>>>>>");
setFocusable(true);
setBackgroundColor(Color.GREEN);
// setting paint
mPaint = new Paint();
mPaint.setAlpha(0);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAntiAlias(true);
// getting image from resources
Resources r = this.getContext().getResources();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.mickey);
// converting image bitmap into mutable bitmap
bitmap = bm.createBitmap(295, 260, Config.ARGB_8888);
pcanvas = new Canvas();
pcanvas.setBitmap(bitmap); // drawXY will result on that Bitmap
pcanvas.drawBitmap(bm, 0, 0, null);
}
#Override
protected void onDraw(Canvas canvas) {
// draw a circle that is erasing bitmap
pcanvas.drawCircle(x, y, r, mPaint);
canvas.drawBitmap(bitmap, 0, 0,null);
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// set parameter to draw circle on touch event
x = (int) event.getX();
y = (int) event.getY();
r =20;
// At last invalidate canvas
invalidate();
return true;
}
}
}
First thought, I'm not sure if setting alpha to 0 on your erase paint object is a good idea. That might make the whole thing ineffective.
Also, you should always use Bitmap.Config.ARGB_8888 if you're dealing with alphas.
If you're having trouble with the PorterDuff stuff, though, I would suggest simplifying your approach to ONLY do that (temporarily). That will help you narrow down the part which isn't working. Comment out everything to do with touch and view updates.
Then you can single out what part of the drawing isn't working right. Set up your constructor like this:
DrawView()
{
/* Create the background green bitmap */
...
/* Create foreground transparent bitmap */
...
/* Draw a blue circle on the foreground bitmap */
...
/* Apply the foreground to the background bitmap
using a PorterDuff method */
...
}
onDraw()
{
/* Simply draw the background bitmap */
...
}
If you set things up like that, you should be able to tell how your PD method is affecting the green bitmap, and change things accordingly.
Here is another advancement for your solution ... See Demo example
public class MainActivity extends Activity {
Bitmap bp;
Canvas bitmapCanvas;
DrawView drawImg;
LinearLayout ln1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ln1 = (LinearLayout) findViewById(R.id.ln1);
drawImg = new DrawView(this);
ln1.addView(drawImg);
}
public class DrawView extends View implements View.OnTouchListener {
private int x = 0;
private int y = 0;
Bitmap bitmap;
Path circlePath;
Paint circlePaint;
private final Paint paint = new Paint();
private final Paint eraserPaint = new Paint();
public DrawView(Context context){
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
// Set background
this.setBackgroundColor(Color.CYAN);
bp = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
// Set bitmap
bitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas();
bitmapCanvas.setBitmap(bitmap);
bitmapCanvas.drawColor(Color.TRANSPARENT);
bitmapCanvas.drawBitmap(bp, 0, 0, null);
circlePath = new Path();
circlePaint = new Paint();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
// Set eraser paint properties
eraserPaint.setAlpha(0);
eraserPaint.setStrokeJoin(Paint.Join.ROUND);
eraserPaint.setStrokeCap(Paint.Cap.ROUND);
eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
eraserPaint.setAntiAlias(true);
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, paint);
bitmapCanvas.drawCircle(x, y, 30, eraserPaint);
canvas.drawPath(circlePath, circlePaint);
}
public boolean onTouch(View view, MotionEvent event) {
x = (int) event.getX();
y = (int) event.getY();
bitmapCanvas.drawCircle(x, y, 30, eraserPaint);
circlePath.reset();
circlePath.addCircle(x, y, 30, Path.Direction.CW);
int ac=event.getAction();
switch(ac){
case MotionEvent.ACTION_UP:
Toast.makeText(MainActivity.this, String.valueOf(x), Toast.LENGTH_SHORT).show();
circlePath.reset();
break;
}
invalidate();
return true;
}
}
}
read more

Categories

Resources