Adding Transparent Section to Your View Android

Adding Transparent Section to Your View – Android

 

In today’s lesson, we will create a view which has a transparent section(s). This view can be used in many ways, you can use it as an overlay to other views or in any other way. The idea for this demo is to create a view, which has transparent areas which are in different shapes. By combining many areas together you can give a beautiful look to a view.

 

For e.g. you can see the following image.

 

 

In the above image, you can see the background has a beautiful photo of coconut trees & above that we have a layer of custom view. BTW I captured that beautiful photo from my phone. In the custom view, I have used rectangles & circles. One rectangle & one circle set as transparent so it can get the above look it has. You can create your own shapes for transparent areas. You can see the full source code at Github repo TrasparentSectionCard.

Now let’s see the code for the same custom view.

 

/**
  * Copyright (C) 2018 Arun Badole.
  *
  * Custom view, which uses different transparent shapes to create a beautiful view. In this particular rectangles & circles are used.
  *
  * @author arunbadole
  */
  public class TransparentCardView extends View {
   
  private final static String TAG = TransparentCardView;
   
  private int cardTopMargin = 0;
  private int cardWidth = 0;
  private int cardHeight = 0;
  private int cardRadiusInner = 0;
  private int cardRadiusOuter = 0;
  private int stroke = 0;
  private int transparentHeight = 0;
  private float centerX = 0;
  private float centerY = 0;
  private int mainWidth = 0;
  private int mainHeight = 0;
   
  private int cardColor;
   
  //Flag for checking whether view is drawn or not.
  private boolean isDrawn = false;
   
  private OnLayoutListener layoutListener;
   
  public TransparentCardView(Context context) {
  super(context);
  }
   
  public TransparentCardView(Context context, @Nullable AttributeSet attrs) {
  super(context, attrs);
  init(context, attrs);
  }
   
  public TransparentCardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  init(context, attrs);
  }
   
  public TransparentCardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
  super(context, attrs, defStyleAttr, defStyleRes);
  init(context, attrs);
  }
   
  private void init(Context context, AttributeSet attrs) {
  Log.i(TAG,init);
  TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TransparentCardView);
  cardTopMargin = a.getInt(R.styleable.TransparentCardView_cardTopMargin, cardTopMargin);
  cardWidth = a.getInt(R.styleable.TransparentCardView_cardWidth, cardWidth);
  cardHeight = a.getInt(R.styleable.TransparentCardView_cardHeight, cardHeight);
  cardRadiusInner = a.getInt(R.styleable.TransparentCardView_cardRadiusInner, cardRadiusInner);
  cardRadiusOuter = a.getInt(R.styleable.TransparentCardView_cardRadiusOuter, cardRadiusOuter);
  cardColor = a.getInt(R.styleable.TransparentCardView_cardColor, cardColor);
  a.recycle();
  }
   
  /**
  * Calculates required parameters for TransparentCardView creation
  */
  private void defaultAttributes() {
  Log.i(TAG,defaultAttributes);
  mainWidth = getWidth();
  mainHeight = getHeight();
  cardTopMargin = mainHeight / 10;
  cardWidth = mainWidth - (mainWidth / 5);
  cardHeight = mainHeight / 2;
  cardRadiusInner = cardWidth / 6;
  cardRadiusOuter = cardRadiusInner + (cardRadiusInner / 10);
  stroke = (cardRadiusInner / 3);
  transparentHeight = cardRadiusOuter;
  centerX = cardWidth / 2;
  centerY = transparentHeight + (cardRadiusOuter / 6);
  cardColor = R.color.colorPrimary;
  }
   
  @Override
  protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  Log.v(TAG, onDraw : getWidth: + getWidth() + , getHeight: + getHeight());
  if (!isDrawn)
  defaultAttributes();
  isDrawn = true;
  Bitmap bitmap = bitmapDraw();
  if (bitmap != null)
  canvas.drawBitmap(bitmap, getWidth() / 2 - cardWidth / 2, cardTopMargin, null);
  }
   
  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
  super.onLayout(changed, left, top, right, bottom);
  Log.i(TAG, onLayout);
  defaultAttributes();
   
  if (this.layoutListener != null && !isDrawn)
  this.layoutListener.onLayout();
   
  isDrawn = true;
  }
   
  /**
  * Creates a bitmap with transparent circle & a card with dynamic height.
  *
  * @return
  */
  private Bitmap bitmapDraw() {
  Bitmap bitmap = Bitmap.createBitmap(cardWidth, cardHeight, Bitmap.Config.ARGB_8888);
  bitmap.eraseColor(Color.TRANSPARENT);
   
  Canvas canvasBitmap = new Canvas(bitmap);
  canvasBitmap.drawColor(getResources().getColor(cardColor));
   
  Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
  paint.setStyle(Paint.Style.FILL);
  paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
   
  canvasBitmap.drawCircle(centerX, centerY, cardRadiusInner, paint);
   
  RectF outerRectangle = new RectF(0, 0, cardWidth, transparentHeight);
  canvasBitmap.drawRect(outerRectangle, paint);
   
  paint.setColor(getResources().getColor(cardColor));
  paint.setStyle(Paint.Style.STROKE);
  paint.setStrokeWidth(stroke);
  paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
  canvasBitmap.drawCircle(centerX, centerY, cardRadiusOuter, paint);
  return bitmap;
  }
   
  public int getCardTopMargin() {
  return cardTopMargin;
  }
   
  public void setCardTopMargin(int cardTopMargin) {
  this.cardTopMargin = cardTopMargin;
  }
   
  public int getCardWidth() {
  return cardWidth;
  }
   
  public void setCardWidth(int cardWidth) {
  this.cardWidth = cardWidth;
  }
   
  public int getCardHeight() {
  return cardHeight;
  }
   
  public void setCardHeight(int cardHeight) {
  this.cardHeight = cardHeight;
  invalidate();
  }
   
  public int getCardRadiusInner() {
  return cardRadiusInner;
  }
   
  public void setCardRadiusInner(int cardRadiusInner) {
  this.cardRadiusInner = cardRadiusInner;
  }
   
  public int getCardRadiusOuter() {
  return cardRadiusOuter;
  }
   
  public void setCardRadiusOuter(int cardRadiusOuter) {
  this.cardRadiusOuter = cardRadiusOuter;
  }
   
  public int getStroke() {
  return stroke;
  }
   
  public void setStroke(int stroke) {
  this.stroke = stroke;
  }
   
  public int getTransparentHeight() {
  return transparentHeight;
  }
   
  public void setTransparentHeight(int transparentHeight) {
  this.transparentHeight = transparentHeight;
  }
   
  public float getCenterX() {
  return centerX;
  }
   
  public void setCenterX(float centerX) {
  this.centerX = centerX;
  }
   
  public float getCenterY() {
  return centerY;
  }
   
  public void setCenterY(float centerY) {
  this.centerY = centerY;
  }
   
  public int getMainWidth() {
  return mainWidth;
  }
   
  public void setMainWidth(int mainWidth) {
  this.mainWidth = mainWidth;
  }
   
  public int getMainHeight() {
  return mainHeight;
  }
   
  public void setMainHeight(int mainHeight) {
  this.mainHeight = mainHeight;
  }
   
  public boolean isDrawn() {
  return isDrawn;
  }
   
  public void setDrawn(boolean drawn) {
  isDrawn = drawn;
  }
   
   
  public int getCardColor() {
  return cardColor;
  }
   
  public void setCardColor(int cardColor) {
  this.cardColor = cardColor;
  invalidate();
  }
   
  public void setOnLayoutListener(OnLayoutListener layoutListener) {
  this.layoutListener = layoutListener;
  }
   
  /**
  * Listener for notifying view layout is done.
  */
  public interface OnLayoutListener {
  void onLayout();
  }
  }

For this custom view I have extended View class & in its onDraw() method I am creating my own Bitmap & setting it on view’s canvas. The bitmap is created in bitmapDraw() method, which actually has all the important drawing part. To draw the view we need the parameters like width & height of the view, center & radius of the circle to be created, top margin, color etc. For this demo, I have calculated all these parameters in method defaultAttributes(). Which actually takes the parent’s width & height as a base & then calculate other parameters accordingly. For these parameters, I have also created custom attributes. You can use these attributes to pass the values in layout XML or can set dynamically as well. For creating custom attributes one has to create attrs.xml, following is mine.

 

android

You can use these attributes in layout XML like below.

android

These attribute’s values are extracted in method init(). You can check that, but for this demo, I have used defaultAttributes() method.
Now, let’s look at the important drawing part, which is bitmapDraw()method.

android

It creates a Bitmap by provided width & height values (for this demo the values are calculated in defaultAttributes() method). It occupies a rectangular area with a specified width & height. Next, the important one is to set the erase color to the created bitmap, which actually fills the bitmap’s pixels with the specified color. Then the bitmap object is used for creating a Canvas. This canvas will be used for drawing actual shapes. First, we are filling it with color & then a paint object is created, which is actually used for drawing shapes. In shapes, first, we are drawing a circle on the canvas, which is set as transparent by using.

android

Then we draw a transparent rectangle using the same paint object. Now, in the same paint object, we are setting color, stroke & Xfermode to draw solid circle shape. Once the bitmap canvas is drawn, we return the created Bitmap object. This bitmap object is used in onDraw() method & drawn on the main View’s canvas. I have also created an interface, which tells when the view’s layout is done. Its callback method notifies the user (Activity) when the view is actually drawn. You can use this for your own use cases, in my cases I needed width & height of the custom view, so the onLayout() method notifies me then I get width & height values.

android

This tutorial gives you an idea to create a view with transparent sections. You can create any shape with any size for such views. You can tell your ideas & implementations in the comments.

I hope you learned something useful from here. You can check the full source code at Github repo TrasparentSectionCard.

Happy Coding

hire freelance android developers
No Comments

Post a Comment

Comment
Name
Email
Website