LinearLayout Tutorial and Examples
LinearLayout is a viewgroup that arranges its child elements linearly in a descending column from top to bottom or left to right.
Each of these elements can then have gravity
and weight
properties. These properties denote how the elements will dynamically grow and shrink to fill space.
[lwtoc]
Elements arrange themselves in a row or column notation based on the android:orientation
parameter.
<LinearLayout
android_orientation="vertical"
android_layout_width="fill_parent"
android_layout_height="fill_parent">
<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_text="TextView 1"/>
<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_text="TextView 2"/>
<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_text="TextView 3"/>
</LinearLayout>
These three TextViews will be arranged vertically given that we've used the android:orientation="vertical"
as a layoutParam in our LinearLayout.
Example 1: Design VIBGYOR Screen with LinearLayout
VIBGYOR (Violet–Indigo–Blue–Green–Yellow–Orange–Red) is a popular mnemonic device used for memorizing the traditional optical spectrum. We want to design a screen that renders those colors. We design the Screen using LinearLayout.
Check the demo below:
Step 1: Create Project
Start by creating an empty Android Studio
project.
Step 2: Dependencies
No special dependencies are needed.
Step 3: Design Layout
Design your main activity layout as follows:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:orientation="vertical"
tools:context=".MainActivity"
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_height="74dp"
android:layout_width="match_parent"
android:id="@+id/txtred"
android:background="@color/red"
android:text="red"/>
<TextView
android:layout_height="74dp"
android:layout_width="match_parent"
android:id="@+id/txtorange"
android:background="@color/orange"
android:text="orange"/>
<TextView
android:layout_height="74dp"
android:layout_width="match_parent"
android:id="@+id/txtyellow"
android:background="@color/yellow"
android:text="yellow"/>
<TextView
android:layout_height="74dp"
android:layout_width="match_parent"
android:id="@+id/txtgreen"
android:background="@color/green"
android:text="green"/>
<TextView
android:layout_height="74dp"
android:layout_width="match_parent"
android:id="@+id/txtblue"
android:background="@color/blue"
android:text="blue"/>
<TextView
android:layout_height="74dp"
android:layout_width="match_parent"
android:id="@+id/textindigo"
android:background="@color/indigo"
android:text="indigo"/>
<TextView
android:layout_height="74dp"
android:layout_width="match_parent"
android:id="@+id/textviolet"
android:background="@color/violet"
android:text="violet"/>
</LinearLayout>
Step 4: MainActivity
We do not need to do anything in our MainActivity:
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
3. | Follow code author |
Example 2: Designing Credit Card UI using LinearLayout
In this example we will design a Credit Card UI using LinearLayout with both horizontal and vertical orientations. We will also use TextViews and Buttons as our UI components, and organize them using LinearLayout.
Here's the screenshot of the project:
Step 1: Create Project
Start by creating an empty Android Studio
project.
Step 2: Dependencies
No special or third party dependency is needed.
Step 3: Design Layout
Design your MainActivity layout as follows:
activity_main.xml
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout
tools:context=".MainActivity"
android:background="#000000"
android:orientation="vertical"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1">
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"
android:textColor="#ffffff"
android:text="Enter Card Balance($)"/>
<EditText
android:background="#D3D3D3"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1">
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"
android:textColor="#ffffff"
android:text="Enter Yearly Interest Rate(%)"/>
<EditText
android:background="#D3D3D3"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="2">
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"
android:textColor="#ffffff"
android:text="Enter Minimum Payment($)"/>
<EditText
android:background="#D3D3D3"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1">
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"
android:textColor="#ffffff"
android:text="Final Card Balance($)"/>
<EditText
android:background="#D3D3D3"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1">
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"
android:textColor="#ffffff"
android:text="Months Remaining"/>
<EditText
android:background="#D3D3D3"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="2">
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"
android:textColor="#ffffff"
android:text="Interest Paid Will Be($)"/>
<EditText
android:background="#D3D3D3"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1">
<Button
android:background="#ffffff"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="Compute"
android:layout_marginBottom="10dp"/>
<Button
android:background="#ffffff"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="Clear"/>
</LinearLayout>
</LinearLayout>
Step 4: MainActivity
Here's the code for MainActivity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
Example 3: Simple LinearLayout Example
This is a dead simple linearylayout example to organize buttons linearly in a screen.
Step 1: Dependenceis
No special dependenices are needed.
Step 2: Design Layout
Addd buttons inthe screen and arrange them using linearlayout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:weightSum="5"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:background="@color/btn1"
android:layout_weight="1"
android:text="Button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Button
android:background="@color/btn2"
android:text="Button2"
android:layout_weight="2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Button
android:background="@color/btn3"
android:layout_weight="1"
android:text="Button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Button
android:background="@color/btn4"
android:layout_weight="1"
android:text="Button4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
Step 3: Write Code
Then finish by having your kotlin:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Run
Just copy the code and run in your android studio.
Designing Registeration Page with LinearLayout and ScrollView
Let's now create a registeration page with LinearLayout helping us arrange our edittexts, imageview, button, spinner and textview.
This is code that you can copy and use as a registeration page in your android project. Clearly you can see the importance and classic application of LinearLayout, it allows us arrange items linearly either vertically or horizontally.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
android_id="@+id/content_main"
android_layout_width="match_parent"
android_layout_height="match_parent"
android_orientation="vertical"
android_background="@color/colorPrimary"
app_layout_behavior="@string/appbar_scrolling_view_behavior"
tools_context=".activities.RegisterActivity">
<LinearLayout
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_orientation="vertical"
android_paddingLeft="24dp"
android_paddingRight="24dp"
android_paddingTop="56dp">
<ImageView
android_src="@drawable/ic_local_taxi_black_24dp"
android_layout_width="72dp"
android_layout_height="72dp"
android_layout_marginBottom="24dp"
android_layout_gravity="center_horizontal" />
<!-- Email Label -->
<android.support.design.widget.TextInputLayout
android_id="@+id/user_email_wrapper_register"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_marginBottom="8dp"
android_layout_marginTop="8dp">
<EditText
android_id="@+id/input_email"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_hint="Email"
android_inputType="textEmailAddress" />
</android.support.design.widget.TextInputLayout>
<!-- Password Label -->
<android.support.design.widget.TextInputLayout
android_id="@+id/user_password_wrapper"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_marginBottom="8dp"
android_layout_marginTop="8dp">
<EditText
android_id="@+id/input_password"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_hint="Password"
android_inputType="textPassword" />
</android.support.design.widget.TextInputLayout>
<!-- Password Label -->
<android.support.design.widget.TextInputLayout
android_id="@+id/password_confirm_wrapper"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_marginBottom="8dp"
android_layout_marginTop="8dp">
<EditText
android_id="@+id/input_password_confirm"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_hint="Confirm Password"
android_inputType="textPassword" />
</android.support.design.widget.TextInputLayout>
<!--First name label-->
<android.support.design.widget.TextInputLayout
android_id="@+id/user_first_name_wrapper"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_marginBottom="8dp"
android_layout_marginTop="8dp">
<EditText
android_id="@+id/input_name"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_hint="First name"
android_inputType="textPersonName"
/>
</android.support.design.widget.TextInputLayout>
<!--Last Name label-->
<android.support.design.widget.TextInputLayout
android_id="@+id/user_last_name_wrapper"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_marginBottom="8dp"
android_layout_marginTop="8dp">
<EditText
android_id="@+id/input_last_name"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_hint="Last name"
android_inputType="textPersonName"
/>
</android.support.design.widget.TextInputLayout>
<!--Route wrapper-->
<android.support.design.widget.TextInputLayout
android_id="@+id/user_route_wrapper"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_marginBottom="8dp"
android_layout_marginTop="8dp">
<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_text="Route:"
android_textSize="20sp"
/>
<Spinner
android_id="@+id/SpinnerRoute"
android_layout_width="fill_parent"
android_layout_height="wrap_content"
android_prompt="@string/RouteType"
android_entries="@array/RouteList"
>
</Spinner>
</android.support.design.widget.TextInputLayout>
<!--Vehicle Type-->
<android.support.design.widget.TextInputLayout
android_id="@+id/vehicle_type_wrapper"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_marginBottom="8dp"
android_layout_marginTop="8dp">
<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_text="Vehicle Type:"
android_textSize="20sp"
/>
<Spinner
android_id="@+id/SpinnerVehicleType"
android_layout_width="fill_parent"
android_layout_height="wrap_content"
android_prompt="@string/VehicleType"
android_entries="@array/VehicleTypeList">
</Spinner>
</android.support.design.widget.TextInputLayout>
<android.support.v7.widget.AppCompatButton
android_id="@+id/btn_signup"
android_layout_width="fill_parent"
android_layout_height="wrap_content"
android_layout_marginBottom="24dp"
android_background="@color/colorPrimaryDark"
android_layout_marginTop="24dp"
android_padding="12dp"
android_text="Register" />
<TextView android_id="@+id/link_login"
android_layout_width="fill_parent"
android_layout_height="wrap_content"
android_layout_marginBottom="24dp"
android_textColor="#ffffff"
android_text="Already a member? Login"
android_gravity="center"
android_textSize="16dip"/>
</LinearLayout>
</ScrollView>
Programmatic Instantiation of LinearLayout
There are two important classes when thinking about working with a LinearLayout programmatically.
First is the LinearLayout
class itself and secondly the LayoutParams
class.
So we instantiate both. Take note of the parameters we are passing to our LayoutParams, the first being the width which in our case we get from the SwipeItem
, secondly is the LayoutParams.MATCH_PARENT
which specifies that the target view will match that of it's parent.
Then we set the LinearLayout parameters loke id, gravity, orientation,params, background image and even the onClickListener.
private void addItem(SwipeMenuItem item, int id) {
LayoutParams params = new LayoutParams(item.getWidth(),
LayoutParams.MATCH_PARENT);
LinearLayout parent = new LinearLayout(getContext());
parent.setId(id);
parent.setGravity(Gravity.CENTER);
parent.setOrientation(LinearLayout.VERTICAL);
parent.setLayoutParams(params);
parent.setBackgroundDrawable(item.getBackground());
parent.setOnClickListener(this);
addView(parent);
if (item.getIcon() != null) {
parent.addView(createIcon(item));
}
if (!TextUtils.isEmpty(item.getTitle())) {
parent.addView(createTitle(item));
}
}
How to create a custom bottom navigation view using a LinearLayout
Let's start by creating a layout, let's call it nav_bar.xml
.
At the root we have a LinearLayout
with vertical orientation. We'll have a generic View
obect. Then below it we define another LinearLayout
with a nested RelativeLayout
containing ImageView
for our left button and a View
for our divider.
We'll also have another ImageView with a red dot image.
We'll have a button at middle of our navigation bar and lastly an imageview to represent our right button.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android_orientation="vertical"
android_layout_width="match_parent"
android_layout_height="wrap_content">
<View
android_layout_width="match_parent"
android_layout_height="0dp"
android_background="@color/colorPrimary"/>
<LinearLayout
android_layout_width="match_parent"
android_layout_height="wrap_content">
<RelativeLayout
android_layout_width="0dp"
android_layout_weight="2"
android_layout_height="50dp">
<ImageView
android_id="@+id/nav_button_left"
android_layout_width="wrap_content"
android_layout_height="50dp"
android_layout_centerInParent="true"
android_src="@mipmap/icon_order_0"
android_clickable="true"/>
<View
android_id="@+id/nav_divider_1"
android_layout_width="8dp"
android_layout_height="match_parent"
android_layout_centerHorizontal="true"/>
<ImageView
android_id="@+id/nav_red_dot"
android_layout_width="10dp"
android_layout_height="10dp"
android_src="@mipmap/icon_red_dot"
android_layout_toRightOf="@id/nav_divider_1"
android_layout_marginTop="5dp"
/>
</RelativeLayout>
<ImageView
android_id="@+id/nav_button_middle"
android_layout_weight="1"
android_layout_width="0dp"
android_layout_height="match_parent"
android_src="@drawable/button_add_order"
android_clickable="true"/>
<RelativeLayout
android_layout_width="0dp"
android_layout_weight="2"
android_layout_height="50dp">
<ImageView
android_id="@+id/nav_button_right"
android_layout_width="wrap_content"
android_layout_height="50dp"
android_src="@mipmap/icon_me_0"
android_layout_centerInParent="true"
android_clickable="true"/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
Then we come create our class, in this case we called it NavigationView
. We'll have it derive from LinearLayout
.
As instance fields we'll have:
- Left Button - Imageview.
- Middle Button - ImageView.
- Right Button - ImageView.
- Red Dot - ImageView.
Then our constructor will receive a Context and an AttributeSet
object. Then pass them to the super class, in this case the LinearLayout
class, via the super()
method.
Then next we inflate our nav_bar.xml
layout using the LayoutInflater class.
Then we reference the imageviews we defined above.
Then set their image resources via the setImageResource()
method.
Here's the full code:
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.LinearLayout;
import with . jshaz . daigo . R ;
/**
* Bottom navigation bar View
*/
public class NavigationView extends LinearLayout {
private ImageView btnLeft, btnMiddle, btnRight, redDot;
public NavigationView(Context context, AttributeSet attr) {
super(context, attr);
LayoutInflater.from(context).inflate(R.layout.nav_bar, this);
btnLeft = (ImageView) findViewById(R.id.nav_button_left);
btnMiddle = (ImageView) findViewById(R.id.nav_button_middle);
btnRight = (ImageView) findViewById(R.id.nav_button_right);
redDot = (ImageView) findViewById(R.id.nav_red_dot);
btnLeft.setImageResource(R.mipmap.icon_order_1);
btnRight.setImageResource(R.mipmap.icon_me_0);
setRedDot ( false );
}
public void setBtnLeftDown() {
btnLeft.setImageResource(R.mipmap.icon_order_1);
btnRight.setImageResource(R.mipmap.icon_me_0);
}
public void setBtnRightDown() {
btnLeft.setImageResource(R.mipmap.icon_order_0);
btnRight.setImageResource(R.mipmap.icon_me_1);
}
public void buttonLeftSetListener(OnClickListener listener) {
btnLeft.setOnClickListener(listener);
}
public void buttonRightSetListener(OnClickListener listener) {
btnRight.setOnClickListener(listener);
}
public void buttonMiddleSetListener(OnClickListener listener) {
btnMiddle.setOnClickListener(listener);
}
public void setButtonMiddleEnabled(boolean b) {
int state = (b == true) ? VISIBLE : GONE;
btnMiddle.setVisibility(state);
}
public void setAllButtonEnabled(boolean b) {
btnLeft.setClickable(b);
btnRight.setClickable(b);
btnMiddle.setClickable(b);
}
public void setRedDot(boolean b) {
if (b) {
redDot.setVisibility(VISIBLE);
} else {
redDot.setVisibility(GONE);
}
}
public ImageView getBtnLeft() {
return btnLeft;
}
public ImageView getBtnMiddle() {
return btnMiddle;
}
public ImageView getBtnRight() {
return btnRight;
}
public ImageView getRedDot () { return redDot ; }
}
Then let's say we want to use our custom Bottom NavigationView
with a fragment.
First assume you have an activity_main.xml
layout. And that layout has our navigationView
defined as an element.
<LinearLayout
android_orientation="vertical"
android_layout_width="match_parent"
android_layout_height="match_parent">
....
<com.jshaz.daigo.ui.NavigationView
android_id="@+id/client_main_navbar"
android_layout_width="match_parent"
android_layout_height="wrap_content">
</com.jshaz.daigo.ui.NavigationView>
....
</LinearLayout>
Then inside the onCreate()
method you can start by referencing the NavigationView
:
Then continue:
/* Turn on the availability of the middle button */
navigationView . setButtonMiddleEnabled ( true );
Then:
/ * Listen for events left button of the navigation bar * /
navigationView . ButtonLeftSetListener ( new new View . OnClickListener () {
@Override public void onClick ( View View ) {
navigationView .SetBtnLeftDown ();
//replaceFragment(orderFragment, SLIDE_FROM_LEFT_TO_RIGHT);
}
});
/* Listen for click event for navigation bar middle button */
navigationView . ButtonMiddleSetListener ( new new View . OnClickListener () {
@Override public void onClick ( View View ) {
//replace fragment
}
});
/*Listening to the click event of the right button of the navigation bar*/
navigationView.buttonRightSetListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
navigationView.setBtnRightDown();
// replace fragment
}
});
Example 4: Let’s Create a Custom Percentage ProgressBar using LinearLayout
Android Custom Percentage ProgressBar Creation Tutorial based on LinearLayout
Sometimes you just want to churn out your own solutions instead of using classes that have been supplied. Those supplied classes are always generic, attempting to cover for everybody. Hence many times you need to be able to create a custom widget yourself.
In this tutorial we see how to do a custom percentage progressbar.
Demo
Here's the gif demo of the project:
Video Tutorial
Here's the video tutorial. It contains more detailed step by step explanations.:
Gradle Scripts
(a) Build.gradle
Nothing special. No third party dependency.
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
implementation 'com.android.support:appcompat-v7:28.0.0'
}
Layouts
Lets start by exploring the layouts in this project.
We have seven layouts:
1. activity_main.xml
This is our main and only layout.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
tools_context=".MainActivity">
<info.camposha.creatingpercentageprogressbar.PercentageProgressBar
android_id="@+id/mPercentageProgressBar"
android_layout_width="match_parent"
android_layout_height="wrap_content"
app_hint="Percentage ProgressBar"
app_showHint="true"/>
</RelativeLayout>
NB/= Remember to Replace info.camposha.creatingpercentageprogressbar
with your own package name.
(b). percentage_progressbar.xml
This is the XML that will define for us our custom percentage progressbar. You can redefine it as you want.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_orientation="vertical">
<RelativeLayout
android_id="@+id/wrap_hint"
android_visibility="gone"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_margin="5dp">
<TextView
android_id="@+id/text_hint"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_text="Percentage"
android_textColor="@color/colorAccentProgress"
android_textSize="12sp"/>
<TextView
android_id="@+id/text_percent"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignParentEnd="true"
android_layout_alignParentRight="true"
android_text="0%"
android_textColor="@color/colorAccentProgress"/>
</RelativeLayout>
<EditText
android_id="@+id/percentageTxt"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_hint="Percentage"
android_inputType="number"
android_visibility="visible"/>
<LinearLayout
android_id="@+id/wrap_percent"
android_layout_width="match_parent"
android_layout_height="5dp"
android_layout_margin="5dp"
android_layout_marginTop="10dp"
android_orientation="horizontal"
android_visibility="gone"
android_weightSum="100">
<LinearLayout
android_id="@+id/start_percent"
android_layout_width="0dp"
android_layout_height="match_parent"
android_layout_weight="0"
android_background="@color/colorAccentProgress"
android_orientation="horizontal"/>
<LinearLayout
android_id="@+id/end_percent"
android_layout_width="0dp"
android_layout_height="match_parent"
android_layout_weight="100"
android_background="@android:color/darker_gray"
android_orientation="horizontal"/>
</LinearLayout>
</LinearLayout>
Styles
(a). attrs.xml
Create a value resource file. I named mine attrs.xml
. Then add the following code. You can see it will contain the attributes for our PercentageProgressBar.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="PercentageProgressBar">
<attr name="hint" format="string"/>
<attr name="showHint" format="boolean"/>
<attr name="heightPercent" format="dimension"/>
<attr name="hideInputPercent" format="boolean"/>
<attr name="percent" format="integer"/>
</declare-styleable>
</resources>
Java Code.
We have the following java classes for this project:
- PercentageProgressBar.java
- MainActivity.java
PercentageProgressBar.java
This is how we create our PercentageProgressBar.
package info.camposha.creatingpercentageprogressbar;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import static android.view.Gravity.START;
public class PercentageProgressBar extends LinearLayout {
private RelativeLayout hintRelativeLayout;
private TextView hintTV;
private TextView percentageTV;
private EditText percentageTxt;
private LinearLayout mWrapPercent;
private LinearLayout mStartPercent;
private LinearLayout mEndPercent;
private boolean showHint;
private boolean hide_input_percent;
/**
* We have two constructors.
* @param context
*/
public PercentageProgressBar(Context context) {
this(context, null);
}
public PercentageProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(VERTICAL);
setGravity(START);
init(context, attrs);
this.isInEditMode();
}
/**
* We reference widgets used in this custom percentageProgressBar we
* are creating.
*/
private void referenceWidgets(){
percentageTxt = findViewById(R.id.percentageTxt);
hintTV = findViewById(R.id.text_hint);
percentageTV = findViewById(R.id.text_percent);
mWrapPercent = findViewById(R.id.wrap_percent);
mStartPercent = findViewById(R.id.start_percent);
mEndPercent = findViewById(R.id.end_percent);
hintRelativeLayout = findViewById(R.id.wrap_hint);
}
/**
* We can now use our LayoutInflater class to inflate our Percentage
* ProgressBar from a layout.
* @param context
*/
private void inflatePercentageProgressBar(Context context){
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.percentage_progressbar, this, true);
}
/**
* Let's obtain our style from attrs.xml, hold it in a typed array,
* obtain several attributes like height,percent,hint etc from that
* typedArray before recyc;ing it.
* @param context
* @param attrs
*/
private void resolveAttributes(Context context,AttributeSet attrs){
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.PercentageProgressBar, 0, 0);
String hint = typedArray.getString(R.styleable.PercentageProgressBar_hint);
showHint = typedArray.getBoolean(R.styleable.PercentageProgressBar_showHint,
false);
hide_input_percent = typedArray.getBoolean(
R.styleable.PercentageProgressBar_hideInputPercent, false);
float height = typedArray.getDimension(
R.styleable.PercentageProgressBar_heightPercent, 5f);
int percent = typedArray.getInteger(R.styleable.PercentageProgressBar_percent, 0);
typedArray.recycle();
this.referenceWidgets();
percentageTxt.setHint(hint);
hintTV.setText(hint);
if (height > 5) {setHeightPercent(Math.round(height));}
if (hide_input_percent) {hideInputPercent();}
if (percent > 0) {setPercent(percent);}
}
/**
* Let's listen to input events to our edittext, thus updating our
* percentage progressbar
*/
private void handlePercetTextChangeEvents(){
percentageTxt.addTextChangedListener(
new TextWatcher() {
@Override public void afterTextChanged(Editable s) {
if (s.length() > 0) {
showPercent(percentageTxt.getText().toString());
} else {
showPercent("0");
}
}
@Override public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
@Override public void onTextChanged(CharSequence s, int start,
int before, int count) {
}
});
}
/**
* Let's invoke the methods we've created above
* @param context
* @param attrs
*/
private void init(Context context, AttributeSet attrs) {
this.inflatePercentageProgressBar(context);
this.resolveAttributes(context,attrs);
this.handlePercetTextChangeEvents();
}
/**
* Let's create a method to set progressbar height. Height as in vertical
* height, like thickness.
* @param height
*/
public void setHeightPercent(int height) {
//LayoutParams is a static class that holds information associated
//with a given viewgroup. In this case our viewgroup is LinearLayout
LayoutParams height_params = (LayoutParams) mWrapPercent.getLayoutParams();
height_params.height = height;
mWrapPercent.setLayoutParams(height_params);
}
/**
* Let;s create a method to receive a percentage as a string, convert it
* to integer then show it.
* @param percentageString
*/
private void showPercent(String percentageString) {
//let's turn percentage string to integer
int percentage = Integer.parseInt(percentageString);
if (percentage == 0) {
mWrapPercent.setVisibility(GONE);
hintRelativeLayout.setVisibility(GONE);
} else {
setAnimatePercent(percentage, 0, mStartPercent);
LayoutParams percent_end = (LayoutParams) mEndPercent.getLayoutParams();
percent_end.weight = 100;
mEndPercent.setLayoutParams(percent_end);
mWrapPercent.setVisibility(VISIBLE);
if (showHint) {
hintRelativeLayout.setVisibility(VISIBLE);
}
}
}
/**
* Let's create a method to set our percentage to our edittext
* @param percent
*/
public void setPercent(int percent) {
showPercent("" + percent);
percentageTxt.setText("" + percent);
}
/**
* Let's create a method to set animated percentage to a textview
* @param percent
* @param position
* @param view
*/
private void setAnimatePercent(final int percent, final int position,
final LinearLayout view) {
final LayoutParams percent_start = (LayoutParams) mStartPercent.getLayoutParams();
final int index = position + 1;
new Handler().postDelayed(new Runnable() {
@Override public void run() {
if (position < percent) {
percent_start.weight = index;
view.setLayoutParams(percent_start);
percentageTV.setText("" + index + "%");
setAnimatePercent(percent, index, view);
}
}
}, 1);
}
/**
* Method to allow us show hint
*/
public void showHint() {
this.showHint = true;
}
/**
* Method to allow us hide percent
*/
public void hideInputPercent() {
percentageTxt.setVisibility(GONE);
}
}
//end
MainActivity.java
Our main activity class. It is here where we use our LoveView we had created.
package info.camposha.creatingpercentageprogressbar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PercentageProgressBar percentageProgressBar = findViewById(
R.id.mPercentageProgressBar);
percentageProgressBar.setPercent(30);
percentageProgressBar.setHeightPercent(15);
}
}
Download
You can download the full source code below or watch the video from the link provided.
No. | Location | Link |
---|---|---|
1. | GitHub | Direct Download |
2. | GitHub | Browse |
3. | YouTube | Video Tutorial |
4. | YouTube | ProgrammingWizards TV Channel |