Custom Views: make your android app stand out

CustomViews are always seen like a tailed beast, especially when you check the developer site on how you can create your custom view widgets, you see a lot of things that don’t really do what your looking for. Most of the tutorials on the developer site for creating custom views rely on you drawing your own layout which can be quiet confusing and difficult especially when you think of how to get a reference to the objects you draw. Here is an easier way to quickly get you through a custom view and still satisfy your ui concern.

One thing you need to know about creating a custom view is the FrameLayout is your friend. This ViewGroup isn’t commonly used by many developers especially since its hard to understand its role in the view heir achy well for one FrameLayout is one of the most convenient views to extend and start hacking away your custom widget. Below is an example of what we are trying to achieve.

https://youtu.be/PqYy0TG9_QY

STEP 1:

Create a new java file lets name it “Custom.java”, extend the FrameLayout and override the necessary constructors.

    public RevealView(@NonNull Context context) {
super(context);
}

public RevealView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

public RevealView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}

STEP 2:

Lets create our xml layout file, this is where all the construction will take place. So for this tutorial we will create an Accordion which reveals extra content on touch. So head over to the res folder and create our custom.xml layout file. Now before you add the xml code you need to download and add two icons to your drawable folder, 1. an arrow facing up and 2. the other facing down. You can get them from the google material design icon pack

If you look closely you will notice the last ViewGroup which is a LinearLayout we are hiding the view by setting visibility:gone just put this in your head as a side note we will come back to this view later.

STEP 3:

So here’s where the fun begins, you know all those properties you set on Views in your xml file? Well we are going to define some for our customView. To do that head over to the res directory then look for a folder called values there should be a file called attrs.xml in there if its not available then create it in other words the full path your looking for should be res/values/attrs.xml. Now add this block of code to the file to define each property we can set from any xml file where we use our customview.

<declare-styleable name="RevealView">
<attr name="colorBar" format="color|reference" />
<attr name="contentBar" format="color|reference"/>
<attr name="barTitle" format="string" localization="suggested"/>
<attr name="message" format="string" localization="suggested"/>
<attr name="showMessage" format="boolean"/>
</declare-styleable>
</resources>

Your file should look like the one above. So lets briefly go through the properties:

  1. colorBar: Defines the color for the header
  2. contentBar: Defines the color for the body/content(the part of the view that will be visible or hidden by user interaction.
  3. barTitle: Title text that will appear on the view header.
  4. message: Body text of the bottoview
  5. showMessage: A value that determines if the view should show the body container or not.

STEP 4:

Lets head over to our Custom.java and initialise some variables we’ll use in constructing our view.

//init properties
protected boolean toggle;
protected Drawable lessArrow = getResources().getDrawable(R.drawable.ic_expand_less);
protected Drawable moreArrow = getResources().getDrawable(R.drawable.ic_expand_more_white);
private TextView topBarText, bottomBarText;
protected View topBar;
protected ViewGroup bottomBar;
protected ImageView toggleBottom;
public RevealView(@NonNull Context context) {
super(context);
}

public RevealView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

public RevealView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}

Now lets create our helper methods that will control the view. Add these methods to the bottom of the file.

i.e I know we haven’t initialised these properties yet don’t worry we are coming to that, we don’t want null pointers.

Lets create our onClickListener so ever time someone touches the top bar the bottom part of the view is either revealed or hidden. You can add this to the bottom of the file.

Remember that view we added visibility:gone to? this listener will take care of enabling or hiding it.

Alright so now lets wrap them all together in an init method that the view will call every time an action is performed on it.

Now we need to call the init() in our constructors defined earlier. Note that whenever a view is updated the constructors are called hence our method will be called and we can perform actions on our view.

Now you can see how we reference the attrs.xml file we created earlier to see which value is set and modify our view based on that. So lets add our view to a layout file and see if we did good. So lets create reveal_tester.xml To add your view just call the class name of the custom view and android studio autocomplete should help you with the full package name.

Now if you notice a namespace is added automatically for use app: we use this to access our custom properties, and we set the showMessage property to true so the body can be shown on default.

So head over to main activity and set this layout as the layout for the activity so we can test what we’ve done.

thats all no need for extra inits since the view widget is already taking care of click/touch interactions.

Thanks for reading, hope this helps you when creating more complex custom views for your android apps.

Remember that you can set the color of the title and body through xml or your java code where you declared the view. The function is part of the attributes we set on the attrs.xml and also the methods we defined earlier to setTitle() and etc.

technology lover, mobile developer, travel enthusiast

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store