I am trying to clip paths in my imageview. But nothing is happening.
My ImageView
public static class CliptImageView extends ImageView {
Path path = new Path();
public CliptImageView(Context context) {
super(context);
}
public CliptImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CliptImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
path.reset();
float y = getMeasuredHeight() / 2.0f;
float x = getMeasuredWidth() / 2.0f;
path.addCircle(x,y, 20,Path.Direction.CW);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.clipPath(path, Region.Op.DIFFERENCE);
super.onDraw(canvas);
canvas.restore();
}
}
I add the imageview programatically to a linearLayout like this
private View getMiddleArea() {
CliptImageView imageView = new CliptImageView(getContext());
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(
0, ViewGroup.LayoutParams.MATCH_PARENT, 2);
imageView.setLayoutParams(params);
imageView.setBackgroundColor(ContextCompat.getColor(getContext(),R.color.white));
// imageView.setBackgroundResource(R.drawable.bottom_bar_semicircle);
// imageView.getBackground().setLevel(5000);
return imageView;
}
Nothing happens. The view is kept white. So i am obviously doing something wrong. But i have no idea what. I have had a lot of trial and error the latest 2 days. But nothing seems to work.
So any help that would get me in the right path is appreciated
Edit update
This is what i am trying to achieve. a transparent circle that clips the view and makes everything transparent
Related
I want to make a circular suface view (porthole effect). Surface view is inside a Frame layout. I want to make a custom view that i can add to Frame layout on top of surface view and mask whole Frame layout to produce porthole effect so that surface view will be shown as circle.
I searched and a lot for answer on Web and Stackoverflow but failed.
Then i saw this question and i tried this custom view to mask frame layout(and hence surfaceview) but i am not getting the desired result.
What i want is a custom view that can take height and width of it's parent (parent is square in shape) and make a transparent circle at it's center touching all four sides at middle of the boundaries, rest(view - circle) of the view will be of color that i can set.
public class FocusView extends View {
private Paint mTransparentPaint;
private Paint mSemiBlackPaint;
private Path mPath = new Path();
public static float radius , xCor , yCor;
public FocusView(Context context) {
super(context);
initPaints();
}
public FocusView(Context context, AttributeSet attrs) {
super(context, attrs);
initPaints();
}
public FocusView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaints();
}
private void initPaints() {
mTransparentPaint = new Paint();
mTransparentPaint.setColor(Color.GREEN);
mTransparentPaint.setStrokeWidth(10);
mSemiBlackPaint = new Paint();
mSemiBlackPaint.setColor(Color.TRANSPARENT);
mSemiBlackPaint.setStrokeWidth(10);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPath.reset();
mPath.addCircle(xCor,yCor,radius, Path.Direction.CW);
mPath.setFillType(Path.FillType.INVERSE_EVEN_ODD);
canvas.drawCircle(xCor,yCor,radius, mTransparentPaint);
canvas.drawPath(mPath, mSemiBlackPaint);
canvas.clipPath(mPath);
canvas.drawColor(Color.parseColor("#FFFFFF")); //A6000000
}
}
Please if somebody can help me. Thanks in advance.
This is an example of a view that paints the whole view pink and cuts a centered, circular hole making the parent visible:
public class FocusView extends View {
private Paint mCutPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Bitmap mBitmap;
private Canvas mInternalCanvas;
public FocusView(Context context) {
super(context);
init();
}
public FocusView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public FocusView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mCutPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mInternalCanvas != null) {
mInternalCanvas.setBitmap(null);
mInternalCanvas = null;
}
if (mBitmap != null) {
mBitmap.recycle();
mBitmap = null;
}
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mInternalCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
if (mInternalCanvas == null || mBitmap == null) {
return;
}
final int width = getWidth();
final int height = getHeight();
// make the radius as large as possible within the view bounds
final int radius = Math.min(width, height) / 2;
mInternalCanvas.drawColor(0xFFFF00FF);
mInternalCanvas.drawCircle(width / 2, height / 2, radius, mCutPaint);
canvas.drawBitmap(mBitmap, 0, 0, null);
}
}
The reason for drawing to an internal Bitmap first is that if you apply PorterDuff.Mode.CLEAR to the original Canvas it will cut away everything that's been previously drawn to the canvas, including the parent view.
There may be better solutions out there, but this one is simple enough to understand.
I'm trying to use vector drawables to draw into canvas. Everything is fine and dandy till I rotate the canvas object by 90 or 270 degrees. Closer I get to 90 or 270 degrees, more blurry the drawable shown in canvas appears. Finally at 90 or 270 degrees, the vector drawable on canvas disappears completely. Is there some sort of fix or workaround for this? Or should I approach drawing into canvas with svg's with some other library? Thanks!
Here's the code:
public class CanvasView extends View {
private static final String TAG = "CanvasView";
private VectorDrawableCompat vectorDrawableCompat;
private int angle;
public CanvasView(Context context) {
super(context);
init();
}
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
vectorDrawableCompat = VectorDrawableCompat.create(getResources(),
R.drawable.ic_android_black_24dp, null);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
vectorDrawableCompat.setBounds((getWidth()/2) - 50, (getHeight()/2) - 50, (getWidth()/2) + 50, (getHeight()/2) + 50);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.rotate(angle, getWidth()/2, getHeight()/2);
vectorDrawableCompat.draw(canvas);
canvas.restore();
}
public void setAngle(int angle){
Log.i(TAG, "setAngle: " + angle);
this.angle = angle;
invalidate();
}
}
Here's the project: https://github.com/danskiess/VectorTest
This has been fixed in the android framework.
https://code.google.com/p/android/issues/detail?id=192413
One possible workaround for this rotation case could be just draw the VectorDrawable into a Bitmap, then rotate the bitmap.
I am using a RoundedNetworkImageView.I want to add an border of 1 dp to it.If i create a separated drawable and put it as background to RoundedNetworkImageView then it replaces the roundedness of view.How can i update below code to add border to imageview?
Below is the code I am using-
public class RoundedNetworkImageView extends NetworkImageView {
public CWRoundedNetworkImageView(Context context) {
super(context);
}
public CWRoundedNetworkImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CWRoundedNetworkImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
#Override
public ScaleType getScaleType() {
return ScaleType.CENTER_CROP;
}
#Override
protected void onDraw(Canvas canvas) {
float radius = 12.0f;
Path clipPath = new Path();
RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight());
clipPath.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(clipPath);
super.onDraw(canvas);
}
}
I want to increase height of my custom TextView so I can draw some lines below TextView. Can anyone help me how can I do that? Here is my custom textview.
CustomTextView
public class CustomTextView extends TextView{
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);init();
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs); init();
}
public CustomTextView(Context context) {
super(context);init();
}
private Paint mStrokeBrush;
private void init(){
mStrokeBrush= new Paint();
mStrokeBrush.setStrokeWidth(5f);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(0f, getHeight());
canvas.drawLine(0, 0, getWidth(), 0, mStrokeBrush);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Edit: I removed a bunch of code which wasn't relevant to your question. Sorry if it caused confusion.
This is a modification of my own code, which adds 20dp to the view's height.
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int viewWidth = MeasureSpec.getSize(widthMeasureSpec);
int viewHeight = MeasureSpec.getSize(heightMeasureSpec);
//
// Set view dimensions. Add 20dp.
//
int dp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics());
setMeasuredDimension(viewWidth, viewHeight + dp);
}
I have extended class from ImageView and want some text to be drawn on it. This doesn't work, do you know why? Thank you.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int imgWidth = getMeasuredWidth();
int imgHeight = getMeasuredHeight();
float txtWidth = mTextPaint.measureText("your text");
int x = Math.round(imgWidth/2 - txtWidth/2);
int y = imgHeight/2 - 6; // 6 is half of the text size
canvas.drawText("your text", x, y, mTextPaint);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
mTextPaint = new Paint();
mTextPaint.setColor(android.R.color.black);
mTextPaint.setTextSize(12);
mTextPaint.setTextAlign(Paint.Align.LEFT);}
I ran your code, and immediately got a Lint error. In init() you are setting your mTextPaint to android.R.color.black. Because it's a static value, I could immediately see that the actual int value of that variable is 0x0106000c, which is almost completely transparent. You should use getResources().getColor(android.R.color.black) or plain ol' Color.BLACK.
Note that a textSize of 12 is very, very small. This code shows 12 (albeit very small).
public class MyImageView extends ImageView {
public MyImageView(Context context, AttributeSet attributeSet, int defStyle) {
super(context, attributeSet, defStyle);
init();
}
public MyImageView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
init();
}
public MyImageView(Context context) {
super(context);
init();
}
Paint mTextPaint;
private void init() {
mTextPaint = new Paint();
mTextPaint.setColor(Color.BLACK);
mTextPaint.setTextSize(12);
mTextPaint.setTextAlign(Paint.Align.LEFT);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int imgWidth = getMeasuredWidth();
int imgHeight = getMeasuredHeight();
float txtWidth = mTextPaint.measureText("your text");
int x = Math.round(imgWidth/2 - txtWidth/2);
int y = imgHeight/2 - 6;
canvas.drawText("12", x, y, mTextPaint);
}
}
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.mytest.MyImageView
android:layout_width="100dp"
android:layout_height="100dp"/>
</RelativeLayout>
Copy/paste, if problem persist, start logging. Again, this code works, I see 12 on my screen.
You should be able to accomplish the desire effect without creating your own class. Just set the background of a TextView with an image drawable. See my example with a text in a speech bubble.
<TextView
android:id="#+id/textOverImage"
android:background="#drawable/speech_bubble"
android:text="#string/hello_world"
android:gravity="center"
android:layout_width="..."
android:layout_height="..."
/>