In this tutorial, we’ll discuss and implement Android Percent Layout Support Library. Furthermore, we’ll be creating a Vertical TextView. Finally, we’ll merge the two concepts to code an interesting Login Screen design concept in our application.
Android Percent Layout Support Overview
Android Percent Layout support were introduced with the Android API 23. This library allows us to specify a percentage value for layout_width
, layout_height
and layout_margin
.
Therefore, a PercentRelativeLayout is a RelativeLayout with an added functionality of assigning weights to the child view(similarly PercentFrameLayout), a feature which has been always there in LinearLayouts.
Hence, we can put a percentage(out of 100) on child view components present in Percent Layout in terms of width, height, margins.
PercentRelativeLayout
and PercentFrameLayout
help us in reducing the view complexity since we’re no longer forced to encapsulate our child view with a LinearLayout and use weights for child views.
To use Percent Layout support, add the following dependency to the build.gradle file.
compile 'com.android.support:percent:25.3.1'
Adding the above dependency allows us to use android.support.percent.PercentRelativeLayout
and android.support.percent.PercentFrameLayout
in our application.
As a result, we can now replace the RelativeLayout and FrameLayout tags in our xml with PercentRelativeLayout and PercentFrameLayout respectively.
Android Percent Support Layout Example
Let’s see a sample implementation of layout_widthPercent
.
app:layout_widthPercent
: Here we set our views width in percentage.
Note: In PercentRelativeLayout, layout_width
and layout_height
attributes are optional if we have specified layout_widthPercent
or layout_heightPercent
attribute.
sample.xml Code
<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentRelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.journaldev.percentlayouts.MainActivity">
<TextView
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="20sp"
app:layout_widthPercent="75%" />
</android.support.percent.PercentRelativeLayout>
Output :
We’ve set the layout_widthPercent
to 75 in the above implementation. In addition, setting it to 100 would be equivalent to match_parent. We can implement the other layout params that are given below in a similar manner.
layout_heightPercent
layout_marginPercent
layout_marginLeftPercent
layout_marginRightPercent
layout_marginTopPercent
layout_marginBottomPercent
layout_marginStartPercent
layout_marginEndPercent
Android Vertical TextView
The standard TextView widget that we use displays the text horizontally only. Hence, we’ll be creating a custom TextView that allows us to display the text vertically.
The code for the VerticalTextView.java
class is given below:
package com.journaldev.verticaltextviewandpercentlayout;
import android.content.Context;
import android.graphics.Canvas;
import android.support.v7.widget.AppCompatTextView;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.Gravity;
public class VerticalTextView extends AppCompatTextView {
final boolean topDown;
public VerticalTextView(Context context, AttributeSet attrs) {
super(context, attrs);
final int gravity = getGravity();
if (Gravity.isVertical(gravity) && (gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
setGravity((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
topDown = false;
} else
topDown = true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
@Override
protected void onDraw(Canvas canvas) {
TextPaint textPaint = getPaint();
textPaint.setColor(getCurrentTextColor());
textPaint.drawableState = getDrawableState();
canvas.save();
if (topDown) {
canvas.translate(getWidth(), 0);
canvas.rotate(90);
} else {
canvas.translate(0, getHeight());
canvas.rotate(-90);
}
canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
getLayout().draw(canvas);
canvas.restore();
}
}
- By default, rotated text is from top to bottom. If we set
android:gravity="bottom"
, then it’s drawn from bottom to top. We save the state of the rotated text (top to bottom/ bottom to top) in the boolean variabletopDown
. - In the
onMeasure()
method we swap the width and height to draw the text rotated. - Finally, in the
onDraw()
method based on thetopDown
boolean flag, we apply a rotation dependent on the gravity setting.
Going further, let’s code an interesting Login UI Concept using Percent Layout support and Vertical TextView.
Android Percent Layout and Vertical TextView Project Structure
Take note of the xml files in the anim
folder. They’ll be used to animate between the sign in and register layouts and buttons.
Android Percent Layout and Vertical TextView Code
Add the following dependency in the build.gradle
file.
compile 'com.android.support:percent:25.3.1'
The xml layout code for activity_main.xml
is given below :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
android:id="@+id/viewGroup"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:scaleType="centerCrop"
android:src="@drawable/background" />
<android.support.percent.PercentRelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccentTrans"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/llSign_in"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:orientation="horizontal"
app:layout_widthPercent="85%">
<com.journaldev.verticaltextviewandpercentlayout.VerticalTextView
android:id="@+id/txtSignIn"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:paddingTop="15dp"
android:rotation="180"
android:text="@string/sign_in"
android:textAllCaps="true"
android:textColor="#FFFFFF"
android:textSize="26sp"
android:visibility="gone" />
<include
layout="@layout/layout_sign_in"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" />
</LinearLayout>
<LinearLayout
android:id="@+id/llRegister"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:background="@color/colorYTrans"
android:orientation="horizontal"
app:layout_widthPercent="15%">
<com.journaldev.verticaltextviewandpercentlayout.VerticalTextView
android:id="@+id/txtRegister"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:paddingTop="15dp"
android:rotation="180"
android:text="@string/register"
android:textAllCaps="true"
android:textColor="#FFFFFF"
android:textSize="26sp"
android:visibility="visible" />
<include
layout="@layout/layout_register"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" />
</LinearLayout>
</android.support.percent.PercentRelativeLayout>
</RelativeLayout>
Take note of the percentages specified in the above code.
We let the layout_sign_in.xml
occupy majority portion of the screen initially. Besides we’ve hidden the VerticalTextView
for SIGN IN. Eventually, these things would be reversed when the layout_register.xml
screen is laid.
The xml layout code for layout_sign_in.xml
is given below.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="24dp">
<EditText
android:id="@+id/inEmail"
android:layout_width="match_parent"
android:layout_height="48dip"
android:background="@drawable/input_field"
android:hint="@string/email"
android:imeOptions="actionNext"
android:inputType="textEmailAddress"
android:maxLines="1"
android:paddingLeft="16.0dip"
android:paddingRight="16.0dip"
android:textColor="#FFF"
android:textColorHint="#b3ffffff"
android:textCursorDrawable="@null" />
<EditText
android:id="@+id/inPassword"
android:layout_width="match_parent"
android:layout_height="48dip"
android:layout_marginTop="@dimen/activity_horizontal_margin"
android:background="@drawable/input_field"
android:hint="@string/password"
android:imeOptions="actionDone"
android:inputType="textPassword"
android:maxLines="1"
android:paddingLeft="16.0dip"
android:paddingRight="16.0dip"
android:textColor="#FFF"
android:textColorHint="#b3ffffff"
android:textCursorDrawable="@null" />
<Button
android:id="@+id/btnSignIn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@null"
android:text="@string/sign_in"
android:textColor="#FFF"
android:textSize="28sp"
android:textStyle="bold" />
<Button
android:id="@+id/btnForgotPassword"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="@android:color/transparent"
android:focusable="true"
android:gravity="center"
android:text="@string/forgot_password"
android:textColor="#FFF"
android:textSize="16sp" />
</LinearLayout>
</RelativeLayout>
The xml layout code for layout_register.xml
is given below.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:padding="24dp">
<EditText
android:id="@+id/inFirstName"
android:layout_width="match_parent"
android:layout_height="48dip"
android:background="@drawable/input_field"
android:focusable="true"
android:focusableInTouchMode="true"
android:hint="@string/first_name"
android:imeOptions="actionNext"
android:inputType="text"
android:maxLines="1"
android:paddingLeft="16.0dip"
android:paddingRight="16.0dip"
android:textColor="#FFF"
android:textColorHint="#b3ffffff"
android:textCursorDrawable="@null" />
<EditText
android:id="@+id/inLastName"
android:layout_width="match_parent"
android:layout_height="48dip"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:background="@drawable/input_field"
android:focusable="true"
android:focusableInTouchMode="true"
android:hint="@string/last_name"
android:imeOptions="actionNext"
android:maxLines="1"
android:paddingLeft="16.0dip"
android:paddingRight="16.0dip"
android:textColor="#FFF"
android:textColorHint="#b3ffffff"
android:textCursorDrawable="@null" />
<EditText
android:id="@+id/inEmail"
android:layout_width="match_parent"
android:layout_height="48dip"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:background="@drawable/input_field"
android:focusable="true"
android:focusableInTouchMode="true"
android:hint="@string/email"
android:imeOptions="actionNext"
android:inputType="textEmailAddress"
android:maxLines="1"
android:paddingLeft="16.0dip"
android:paddingRight="16.0dip"
android:textColor="#FFF"
android:textColorHint="#b3ffffff"
android:textCursorDrawable="@null" />
<EditText
android:id="@+id/inPassword"
android:layout_width="match_parent"
android:layout_height="48dip"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:background="@drawable/input_field"
android:focusable="true"
android:focusableInTouchMode="true"
android:hint="@string/password"
android:imeOptions="actionNext"
android:inputType="textPassword"
android:maxLines="1"
android:paddingLeft="16.0dip"
android:paddingRight="16.0dip"
android:textColor="#FFF"
android:textColorHint="#b3ffffff"
android:textCursorDrawable="@null" />
<EditText
android:id="@+id/inConfirmPassword"
android:layout_width="match_parent"
android:layout_height="48dip"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:background="@drawable/input_field"
android:focusable="true"
android:focusableInTouchMode="true"
android:fontFamily="sans-serif-light"
android:hint="@string/confirm_password"
android:imeOptions="actionNext"
android:inputType="textPassword"
android:maxLines="1"
android:paddingLeft="16.0dip"
android:paddingRight="16.0dip"
android:textColor="#FFF"
android:textColorHint="#b3ffffff"
android:textCursorDrawable="@null" />
<EditText
android:id="@+id/inPhone"
android:layout_width="match_parent"
android:layout_height="48dip"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:background="@drawable/input_field"
android:focusable="true"
android:focusableInTouchMode="true"
android:hint="@string/phone"
android:imeOptions="actionNext"
android:inputType="phone"
android:maxLines="1"
android:paddingLeft="16.0dip"
android:paddingRight="16.0dip"
android:textColor="#FFF"
android:textColorHint="#b3ffffff"
android:textCursorDrawable="@null" />
<Button
android:id="@+id/btnRegister"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@null"
android:text="@string/register"
android:textColor="#FFF"
android:textSize="28sp"
android:textStyle="bold" />
</LinearLayout>
</ScrollView>
</RelativeLayout>
In addition, the background for each EditText is defined under the drawable folder in the file shape.xml
as shown below.
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="https://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#1affffff"/>
<corners android:radius="2.0dip"/>
</shape>
The code for the MainActivity.java
is given below.
package com.journaldev.verticaltextviewandpercentlayout;
import android.support.percent.PercentLayoutHelper;
import android.support.percent.PercentRelativeLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
VerticalTextView txtSignIn, txtRegister;
LinearLayout llSignIn, llRegister;
Button btnRegister, btnSignIn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
llSignIn = (LinearLayout) findViewById(R.id.llSign_in);
llRegister = (LinearLayout) findViewById(R.id.llRegister);
txtRegister = (VerticalTextView) findViewById(R.id.txtRegister);
txtSignIn = (VerticalTextView) findViewById(R.id.txtSignIn);
btnSignIn = (Button) findViewById(R.id.btnSignIn);
btnRegister = (Button) findViewById(R.id.btnRegister);
txtSignIn.setOnClickListener(this);
txtRegister.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.txtSignIn:
hideSoftKeyBoard();
showSignInForm();
break;
case R.id.txtRegister:
hideSoftKeyBoard();
showRegisterForm();
break;
}
}
private void showSignInForm() {
PercentRelativeLayout.LayoutParams paramsLogin = (PercentRelativeLayout.LayoutParams) llRegister.getLayoutParams();
PercentLayoutHelper.PercentLayoutInfo infoLogin = paramsLogin.getPercentLayoutInfo();
infoLogin.widthPercent = 0.15f;
llRegister.requestLayout();
PercentRelativeLayout.LayoutParams paramsSignup = (PercentRelativeLayout.LayoutParams) llSignIn.getLayoutParams();
PercentLayoutHelper.PercentLayoutInfo infoSignup = paramsSignup.getPercentLayoutInfo();
infoSignup.widthPercent = 0.85f;
llSignIn.requestLayout();
txtRegister.setVisibility(View.VISIBLE);
txtSignIn.setVisibility(View.GONE);
Animation translate = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.translate_left_to_right);
llSignIn.startAnimation(translate);
Animation clockwise = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotate_left_to_right);
btnSignIn.startAnimation(clockwise);
}
private void showRegisterForm() {
PercentRelativeLayout.LayoutParams paramsLogin = (PercentRelativeLayout.LayoutParams) llSignIn.getLayoutParams();
PercentLayoutHelper.PercentLayoutInfo infoLogin = paramsLogin.getPercentLayoutInfo();
infoLogin.widthPercent = 0.15f;
llSignIn.requestLayout();
PercentRelativeLayout.LayoutParams paramsSignup = (PercentRelativeLayout.LayoutParams) llRegister.getLayoutParams();
PercentLayoutHelper.PercentLayoutInfo infoSignup = paramsSignup.getPercentLayoutInfo();
infoSignup.widthPercent = 0.85f;
llRegister.requestLayout();
txtRegister.setVisibility(View.GONE);
txtSignIn.setVisibility(View.VISIBLE);
Animation translate = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.translate_right_to_left);
llRegister.startAnimation(translate);
Animation clockwise = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotate_right_to_left);
btnRegister.startAnimation(clockwise);
}
private void hideSoftKeyBoard() {
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
if (imm.isAcceptingText()) {
// verify if the soft keyboard is open
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
}
}
Few inferences drawn from the above code are:
- We interchange the percentage widths(using float values) of the LinearLayouts held inside
PercentRelativeLayout
namelylayout_sign_in
andlayout_register
. - Besides we animate the above-mentioned layouts along with showing a transition from the
VerticalTextView
to its respective Button. hideSoftKeyboard()
is invoked every time aVerticalTextView
is clicked in order to dismiss any previously opened keyboard.
Note: To hide the keyboard when the application launches, we set the windowSoftInputMode
to hidden
in the AndroidManifest.xml
file as shown below.
<activity
android:name=".MainActivity"
android:windowSoftInputMode="stateHidden">
Consequently, the output of the application in action is given below.
This brings an end to this tutorial. You can download the final Android VerticalTextViewAndPercentLayout Project from the link below.
Reference: android.support.percent
side label are not showing sir ….
AWESOME ANUPAM,
UI looks so good by using this…. u r great man!!!