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.
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.
I'm trying to achieve a visual effect, that if I could make would look awesome! The login of the app that I'm doing looks like this:
Keep in mind that the image on the background is an animation, that makes a slightly transition from that image to another.
What I want is make the title of the app "Akrasia" be transparent, but transparent meaning that you can see the image in background through the title letters, this means that in some way I must override the onDraw method of the RelativeLayout that contains this form. I tried to do that, but the only thing that I got was errors. Maybe I'm wrong trying to override the onDraw method in boths, the TextView and the RelativeLayout, maybe there's an easiest way to do it. What do you think? Or maybe is impossible to achive this effect?
UPDATE:
This is how it should look like.
Also I tried to make a custom view extending from TextView wich has a method setBackgroundView wich stores a view instance into a field. Later on the onDraw method and I managed to get the bitmap from the background image. But I don't know how draw it using canvas.
UPDATE:
I make it work! Now I only need change that blue-like background by the drawable of the background.
The view:
final public class SeeThroughTextView extends TextView
{
Bitmap mMaskBitmap;
Canvas mMaskCanvas;
Paint mPaint;
Drawable mBackground;
Bitmap mBackgroundBitmap;
Canvas mBackgroundCanvas;
boolean mSetBoundsOnSizeAvailable = false;
public SeeThroughTextView(Context context)
{
super(context);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
public SeeThroughTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SeeThroughTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#Override
#Deprecated
public void setBackgroundDrawable(Drawable bg)
{
mBackground = bg;
int w = bg.getIntrinsicWidth();
int h = bg.getIntrinsicHeight();
// Drawable has no dimensions, retrieve View's dimensions
if (w == -1 || h == -1)
{
w = getWidth();
h = getHeight();
}
// Layout has not run
if (w == 0 || h == 0)
{
mSetBoundsOnSizeAvailable = true;
return;
}
mBackground.setBounds(0, 0, w, h);
invalidate();
}
#Override
public void setBackgroundColor(int color)
{
setBackgroundDrawable(new ColorDrawable(color));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mBackgroundBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mBackgroundCanvas = new Canvas(mBackgroundBitmap);
mMaskBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mMaskCanvas = new Canvas(mMaskBitmap);
if (mSetBoundsOnSizeAvailable)
{
mBackground.setBounds(0, 0, w, h);
mSetBoundsOnSizeAvailable = false;
}
}
#Override
protected void onDraw(Canvas canvas)
{
// Draw background
mBackground.draw(mBackgroundCanvas);
// Draw mask
mMaskCanvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
super.onDraw(mMaskCanvas);
mBackgroundCanvas.drawBitmap(mMaskBitmap, 0.f, 0.f, mPaint);
canvas.drawBitmap(mBackgroundBitmap, 0.f, 0.f, null);
}
}
And in my fragment I have this because the animation in the background:
vBackground.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
vTitle.setBackgroundDrawable(new BitmapDrawable(vBackground.getDrawingCache()));
vTitle.invalidate();
}
});
Nailed!
The view:
final public class SeeThroughTextView extends TextView
{
Bitmap mMaskBitmap;
Canvas mMaskCanvas;
Paint mPaint;
Drawable mBackground;
Bitmap mBackgroundBitmap;
Canvas mBackgroundCanvas;
boolean mSetBoundsOnSizeAvailable = false;
public SeeThroughTextView(Context context)
{
super(context);
init();
}
private void init() {
Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/gillsans.ttf");
setTypeface(myTypeface);
mPaint = new Paint();
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
public SeeThroughTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SeeThroughTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#Override
#Deprecated
public void setBackgroundDrawable(Drawable bg)
{
mBackground = bg;
int w = bg.getIntrinsicWidth();
int h = bg.getIntrinsicHeight();
// Drawable has no dimensions, retrieve View's dimensions
if (w == -1 || h == -1)
{
w = getWidth();
h = getHeight();
}
// Layout has not run
if (w == 0 || h == 0)
{
mSetBoundsOnSizeAvailable = true;
return;
}
mBackground.setBounds(0, 0, w, h);
invalidate();
}
#Override
public void setBackgroundColor(int color)
{
setBackgroundDrawable(new ColorDrawable(color));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mBackgroundBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mBackgroundCanvas = new Canvas(mBackgroundBitmap);
mMaskBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mMaskCanvas = new Canvas(mMaskBitmap);
if (mSetBoundsOnSizeAvailable)
{
mBackground.setBounds(0, 0, w, h);
mSetBoundsOnSizeAvailable = false;
}
}
#Override
protected void onDraw(Canvas canvas)
{
// Draw background
mBackground.draw(mBackgroundCanvas);
// Draw mask
mMaskCanvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
super.onDraw(mMaskCanvas);
mBackgroundCanvas.drawBitmap(mMaskBitmap, 0.f, 0.f, mPaint);
canvas.drawBitmap(mBackgroundBitmap, 0.f, 0.f, null);
}
}
In my fragment:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
vLoginBtn = (Button) view.findViewById(R.id.btn_login);
vRegistrationBtn = (Button) view.findViewById(R.id.btn_registration);
vForgotBtn = (Button) view.findViewById(R.id.btn_forgot);
vBackground = (KenBurnsView) view.findViewById(R.id.login_background);
vTitle = (SeeThroughTextView) view.findViewById(R.id.txt_view_login_title);
vBackground.setResourceUrls(
"http://www.youwall.com/papel/peaceful_place_wallpaper_4f3f3.jpg",
"http://www.fwallpaper.net/wallpapers/P/E/Peaceful-Scenary_1920x1200.jpg",
"http://p1.pichost.me/i/39/1620902.jpg"
);
vBackground.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
vTitle.setBackgroundDrawable(getResources().getDrawable(R.drawable.drawable_background_login_top));
vTitle.invalidate();
vBackground.removeOnLayoutChangeListener(this);
}
});
}
The drawables are just two shapes, one with the top-left corner and top-right corner with radius 10dp and the another one with the radius in the bottoms.
The custom TextView with the top drawable shape is alligned above the RelativeLayout wich contains the EditTexts.
No much rocket science. Thanks a lot to #Klotor for suggesting the idea!
Specify a new color in your res/values/colors.xml file (create one if it doesn't exist), the file might look like:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ltGray">#33999999</color>
</resources>
where the first two numbers are transparency (00 - fully transparent, FF - fully opaque).
Then simply set the text color of desired TextView to #color/ltGray in the xml of that layout, or go
tvTitle.setTextColor(getResources().getColor(R.color.ltGray))
after instatiating the TextView.
I have created a class from SurfaceView.I wanted it that when i touch on the screen then the screen will be refreshed by calling invalidate() function. But in my implementation invalidate () is not called when i touched on the screen.
Here is my code.
public class GameBoard extends SurfaceView implements Callback {
private SurfaceHolder holder;
int clicked =0;
public GameBoard(Context context)
{
super(context);
holder = getHolder();
holder.addCallback(this);
setFocusable(true);
requestFocus();
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
Canvas c = holder.lockCanvas(null);
onDraw(c);
holder.unlockCanvasAndPost(c);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
// TODO Auto-generated method stub
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
}
public boolean onTouchEvent(MotionEvent event)
{
int action = event.getAction();
if (action==MotionEvent.ACTION_UP)
{
clicked++;
// Canvas c = holder.lockCanvas(null);
// onDraw(c);
// holder.unlockCanvasAndPost(c);
invalidate();
}
return true;
}
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawColor(0xFF00ff00);
Paint p = new Paint();
p.setTextSize(20);
p.setColor( Color.RED );
p.setAntiAlias(true);
canvas.drawText(""+clicked, 100, 500, p);
}
}
I have been developing the application for drawing, and there is the code:
public class PainterView extends View implements DrawingListener {
private GestureDetector detector;
private Context context;
private Painter painter;
private Bitmap background;
private Bitmap bitmap;
private Paint bitmapPaint;
private Path path;
private Paint paint;
private float x;
private float y;
public PainterView(Context context, Painter painter) {
super(context);
this.context = context;
this.painter = painter;
detector = new GestureDetector(context, new GestureListener());
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
if (bitmap != null) {
canvas.drawBitmap(background, 0, 0, bitmapPaint);
canvas.drawBitmap(bitmap, 0, 0, bitmapPaint);
canvas.drawPath(path, paint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
detector.onTouchEvent(event);
x = event.getX();
y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
painter.touchStart(x, y);
break;
case MotionEvent.ACTION_MOVE:
painter.touchMove(x, y);
break;
case MotionEvent.ACTION_UP:
painter.touchUp();
break;
}
return true;
}
#Override
public void onPictureUpdate(Bitmap background, Bitmap bitmap, Paint bitmapPaint, Path path,
Paint paint) {
this.background=background;
this.bitmap = bitmap;
this.bitmapPaint = bitmapPaint;
this.path = path;
this.paint = paint;
invalidate();
}
public void setPainter(Painter painter) {
this.painter = painter;
}
So, the background bitmap is image (ruled paper), and I need to know how can I emulate the eraser in order to allow to user erase his notes?
you could do something like this:
public class Eraser
{
public void erase(int locX, int locY, int brushsize)
{
for(int x = locX - brushsize;x < locX + brushsize;x++)
{
for(int y = locY - brushsize;y < locY + brushsize;y++)
{
map.setPixle(x,y,Color.white);
}
}
}
private Bitmap map;
}
This is a square eraser, I'm sure you could figure out a way to make it a circle if you really wanted to. I hope his helped!