How to make Circular Mask and Clip GLSurfaceView in android? - android

I work with an SDK that provides a rectangular GLSurfaceView through a callback.
I want to be able to render this view in a circular layout. (i.e.) I would like to display the view on a circular view
It's showing Circle shape when I overlay GLSurfaceView over ImageView
GLSurfaceView over ImageView
It's showing Square shape when I overlay GLSurfaceView over VideoView.
GLSurfaceView over VideoView
I have tried below code for making circle GLSurfaceView
public class SampleGLView extends GLSurfaceView implements View.OnTouchListener {
private Path clippingPath;
public SampleGLView(Context context) {
this(context, null);
}
public SampleGLView(Context context, AttributeSet attrs) {
super(context, attrs);
setOnTouchListener(this);
}
private TouchListener touchListener;
#Override
public boolean onTouch(View v, MotionEvent event) {
final int actionMasked = event.getActionMasked();
if (actionMasked != MotionEvent.ACTION_DOWN) {
return false;
}
if (touchListener != null) {
touchListener.onTouch(event, v.getWidth(), v.getHeight());
}
return false;
}
public interface TouchListener {
void onTouch(MotionEvent event, int width, int height);
}
public void setTouchListener(TouchListener touchListener) {
this.touchListener = touchListener;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != oldw || h != oldh) {
int radius = Math.min(w, h)/2;
clippingPath = new Path();
clippingPath.addCircle(w/2, h/2, radius, Path.Direction.CW);
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
int count = canvas.save();
canvas.clipPath(clippingPath);
super.dispatchDraw(canvas);
canvas.restoreToCount(count);
}
}
Question:
How do I go about clipping and rendering this as a circle?
(The background is constantly changing, so i cant overlay a transparent view on top of this video view. The aim is to have a rectangular glsurface view on top of which there is a circular glsurface view)
Is any one have idea how to solve please comment. Thanks in advance.

Related

How to make Circular Mask and Clip GLSurfaceView?

I work with an SDK that provides a rectangular GLSurfaceView through a callback.
I want to be able to render this view in a circular layout. (i.e.) I would like to display the view on a circular view
It's showing Circle shape when I overlay GLSurfaceView over ImageView
GLSurfaceView over ImageView
It's showing Square shape when I overlay GLSurfaceView over VideoView.
GLSurfaceView over VideoView
I have tried below code for making circle GLSurfaceView
public class SampleGLView extends GLSurfaceView implements View.OnTouchListener {
private Path clippingPath;
public SampleGLView(Context context) {
this(context, null);
}
public SampleGLView(Context context, AttributeSet attrs) {
super(context, attrs);
setOnTouchListener(this);
}
private TouchListener touchListener;
#Override
public boolean onTouch(View v, MotionEvent event) {
final int actionMasked = event.getActionMasked();
if (actionMasked != MotionEvent.ACTION_DOWN) {
return false;
}
if (touchListener != null) {
touchListener.onTouch(event, v.getWidth(), v.getHeight());
}
return false;
}
public interface TouchListener {
void onTouch(MotionEvent event, int width, int height);
}
public void setTouchListener(TouchListener touchListener) {
this.touchListener = touchListener;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != oldw || h != oldh) {
int radius = Math.min(w, h)/2;
clippingPath = new Path();
clippingPath.addCircle(w/2, h/2, radius, Path.Direction.CW);
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
int count = canvas.save();
canvas.clipPath(clippingPath);
super.dispatchDraw(canvas);
canvas.restoreToCount(count);
}
}
Question:
How do I go about clipping and rendering this as a circle?
(The background is constantly changing, so i cant overlay a transparent view on top of this video view. The aim is to have a rectangular glsurface view on top of which there is a circular glsurface view)
Is any one have idea how to solve please comment. Thanks in advance.

How can I make circle GLSurfaceView on Videoview?

I'm using camera recorder library for video recording it's use GLSurfaceView. In my layout on VideoView I overlay GLSurfaceView.
It's showing Circle shape when I overlay GLSurfaceView over ImageView
It's showing Square shape when I overlay GLSurfaceView over VideoView.
I have tried below code for making circle GLSurfaceView.
public class SampleGLView extends GLSurfaceView implements
View.OnTouchListener {
private Path clippingPath;
public SampleGLView(Context context) {
this(context, null);
}
public SampleGLView(Context context, AttributeSet attrs) {
super(context, attrs);
setOnTouchListener(this);
}
private TouchListener touchListener;
#Override
public boolean onTouch(View v, MotionEvent event) {
final int actionMasked = event.getActionMasked();
if (actionMasked != MotionEvent.ACTION_DOWN) {
return false;
}
if (touchListener != null) {
touchListener.onTouch(event, v.getWidth(), v.getHeight());
}
return false;
}
public interface TouchListener {
void onTouch(MotionEvent event, int width, int height);
}
public void setTouchListener(TouchListener touchListener) {
this.touchListener = touchListener;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != oldw || h != oldh) {
int radius = Math.min(w, h)/2;
clippingPath = new Path();
clippingPath.addCircle(w/2, h/2, radius, Path.Direction.CW);
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
int count = canvas.save();
canvas.clipPath(clippingPath);
super.dispatchDraw(canvas);
canvas.restoreToCount(count);
} }
Is any one have idea how to solve it.

Android SurfaceView draws bitmap multiple times

I'm trying to draw a bitmap into surfaceView I can successfully draw but I need to move that bitmap around the screen based on some other user movements but when I set
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(bitmap, left, top, null);
It draws same bitmap multiple times in screen.
But when I do this way
canvas.drawColor(Color.GREEN);
canvas.drawBitmap(bitmap, left, top, null);
It works correctly draws just one bitmap and moves it , but I need transparent background not colored.
CODE
public class DotsSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holder;
private boolean created;
Bitmap bitmap;
#Override
public void surfaceCreated(SurfaceHolder holder) {
// draw();
created = true;
}
#Override
// This is always called at least once, after surfaceCreated
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// draw();
created = true;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public DotsSurfaceView(Context context) {
super(context);
holder = getHolder();
holder.addCallback(this);
holder.setFormat(PixelFormat.TRANSPARENT);
Drawable drawable = ARTrackingActivity.contexti.getDrawable(R.drawable.ic_tune_black_24px);
bitmap =Utils.drawableToBitmap(drawable);
}
public void draw(float left, float top) {
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
synchronized (holder) {
draw2(canvas, left, top);
}
} finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
public void draw2(Canvas canvas, float left, float top) {
if (created) {
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(bitmap, left, top, null);
}
}
}

Android - Google Maps inside CircleView

I wanted to show map inside a circle view where circle's outside area filled with a color. I referred a post Draw transparent circle filled outside. But now the problem is touch events. Map can be touched through outside circle view while I need map can be touched (zoom or move) only form inside Circle view (where the map is visible).
What I tried,
setEnabled=false
clickable=false
but still map is touched from outside circle view.
Is that possible to achieve that map can be touched from inside circle view.
public class RadiusOverlayView extends LinearLayout {
private Bitmap windowFrame;
public RadiusOverlayView(Context context) {
super(context);
}
public RadiusOverlayView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RadiusOverlayView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public RadiusOverlayView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (windowFrame == null) {
createWindowFrame(); // Lazy creation of the window frame, this is needed as we don't know the width & height of the screen until draw time
}
canvas.drawBitmap(windowFrame, 0, 0, null);
}
#Override
public boolean isEnabled() {
return false;
}
#Override
public boolean isClickable() {
return false;
}
protected void createWindowFrame() {
windowFrame = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); // Create a new image we will draw over the map
Canvas osCanvas = new Canvas(windowFrame); // Create a canvas to draw onto the new image
RectF outerRectangle = new RectF(0, 0, getWidth(), getHeight());
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); // Anti alias allows for smooth corners
paint.setColor(Color.CYAN); // This is the color of your activity background
osCanvas.drawRect(outerRectangle, paint);
//paint.setColor(Color.TRANSPARENT); // An obvious color to help debugging
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)); // A out B http://en.wikipedia.org/wiki/File:Alpha_compositing.svg
float centerX = getWidth() / 2;
float centerY = getHeight() / 2;
float radius = Math.min(getWidth(), getHeight()) / 2 - 50;
osCanvas.drawCircle(centerX, centerY, radius, paint);
}
#Override
public boolean isInEditMode() {
return true;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
windowFrame = null; // If the layout changes null our frame so it can be recreated with the new width and height
}
}
XML layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--loading map in container-->
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<mypackage.RadiusOverlayView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
/>
</RelativeLayout>
Result:
Any help will be appreciated.
You could set a View.OnTouchListener to your RadiusOverlayView and calculate whether the RadiusOverlayView needs to manage the touch events or not.
In this example I calculate this by testing if the RadiusOverlayView color touched is != 0 (maybe you want to improve this):
final RadiusOverlayView radiusOverlayView = (RadiusOverlayView) findViewById(R.id.radiusView);
radiusOverlayView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(final View view, final MotionEvent motionEvent) {
view.setDrawingCacheEnabled(true);
Bitmap bmp = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
return bmp.getPixel((int) motionEvent.getX(), (int) motionEvent.getY()) != 0;
}
});

Draw a shape over existing view

I have a view and I want to draw a shape on it (circle for example) after click.
I've tried to do this but there are two problems -
onDraw is never called.
Not sure the setLayoutParams(v.getLayoutParams) will give me the result I want.
#Override
public void onClick(View v) {
CircleView circle = new CircleView(GameXoActivity.this, v.getWidth(), v.getHeight());
circle.setLayoutParams(v.getLayoutParams());
circle.startDrawing();
}
CircleView:
public CircleView(Context context, int width, int height) {
super(context);
this.width = width;
this.height = height;
}
protected void startDrawing() {
this.postInvalidate();
}
#Override
protected void onDraw(Canvas canvas) {
Log.d("TAG", "onDraw");
// draw circle
}
}
}
UPDATE:
The shape is not an image and I want to draw it with animation (I didn't write the entire code).
Also, the shape is not always a circle, so using a drawable-state is not an option.
Because there is not just one view, but 9, I don't think the making 9 more on top of them would be right.
As I'm sure you'll need to customize this quite a bit, I've left things rather generic. The following example will animate a blue circle being drawn clockwise, starting from the east (0 degrees), on top of the View's content when the View is clicked.
public class CircleView extends View
{
private static final int MARGIN = 50;
Handler handler = new Handler();
Paint paint = new Paint();
RectF rect = new RectF();
boolean drawing = false;
float sweep = 0;
public CircleView(Context context)
{
this(context, null);
}
public CircleView(Context context, AttributeSet attrs)
{
super(context, attrs);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(15);
paint.setColor(Color.BLUE);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawArc(rect, 0, sweep, false, paint);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
rect.set(MARGIN, MARGIN, w - MARGIN, h - MARGIN);
}
public void startAnimation()
{
drawing = true;
handler.post(runnable);
}
Runnable runnable = new Runnable()
{
#Override
public void run()
{
sweep += 10;
if (!(sweep > 360))
{
invalidate();
handler.postDelayed(this, 20);
}
else
{
drawing = false;
sweep = 0;
}
}
};
}
In this Activity example, I used an image that most developers would already have in their project, but it can obviously be changed to your custom image. Also, for the sake of simplicity and brevity, the CircleView is set as the entire content of the Activity, but it can easily be listed in an xml layout, as well.
public class MainActivity extends Activity
{
CircleView circle;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
circle = new CircleView(this);
circle.setBackgroundResource(R.drawable.ic_launcher);
circle.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
circle.startAnimation();
}
}
);
setContentView(circle);
}
}
I suggest, create two imageView with same dimensions, set the image you want to display on image view and then make the second image invisible .
For example :
circleimage.setVisibility(View.INVISIBLE);//now its hidden(do it OnCreate)
and then show 2ndimage when 1stimage is clicked(do it in onclick of 1st image)
circleimage.setVisibility(View.VISIBLE);
If you want to mess with drawing of the object you should overridepublic void draw(Canvas canvas) and not protected void onDraw(Canvas canvas)
EDIT:Please read comments, this first statement of my answer is probably wrong
but I would use a FrameLayout or a RelativeLayout and put the images one on top of another.
Then you can play with the visibility of the overlaying image in order to hide/show it.
EDIT:
In case your circle is not an image and needs to be drawn, make your own circle class extending View and use it as a component in the FrameLayout or RelativeLayout as you would do if it were an image

Categories

Resources