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支持库。 此外,我们将创建一个Vertical TextView 。 最后,我们将把这两个概念合并在一起,以在我们的应用程序中编写有趣的登录屏幕设计概念。
Android百分比布局支持概述 (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
.
Android API 23引入了对Android Percent Layout的支持。该库使我们可以为layout_width
, layout_height
和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.
因此, PercentRelativeLayout是一个RelativeLayout,具有为子视图分配权重的附加功能(类似PercentFrameLayout ),此功能在LinearLayouts中一直存在。
Hence, we can put a percentage(out of 100) on child view components present in Percent Layout in terms of width, height, margins.
因此,我们可以对百分比布局中存在的子视图组件的宽度,高度,边距设置一个百分比(满分为100)。
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.
PercentRelativeLayout
和PercentFrameLayout
帮助我们降低了视图的复杂度,因为我们不再被迫使用LinearLayout封装子视图并为子视图使用权重。
To use Percent Layout support, add the following dependency to the build.gradle file.
compile 'com.android.support:percent:25.3.1'
要使用百分比布局支持,请将以下依赖项添加到build.gradle文件中。
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.
添加上述依赖项后,我们就可以在应用程序中使用android.support.percent.PercentRelativeLayout
和android.support.percent.PercentFrameLayout
。
As a result, we can now replace the RelativeLayout and FrameLayout tags in our xml with PercentRelativeLayout and PercentFrameLayout respectively.
结果,我们现在可以分别用PercentRelativeLayout和PercentFrameLayout替换xml中的RelativeLayout和FrameLayout标记。
Android百分比支持布局示例 (Android Percent Support Layout Example)
Let’s see a sample implementation of layout_widthPercent
.
我们来看一下layout_widthPercent
的示例实现。
app:layout_widthPercent
: Here we set our views width in percentage.
app:layout_widthPercent
:这里我们以百分比设置视图宽度。
Note: In PercentRelativeLayout, layout_width
and layout_height
attributes are optional if we have specified layout_widthPercent
or layout_heightPercent
attribute.
注意 :在PercentRelativeLayout中,如果我们指定了layout_widthPercent
或layout_heightPercent
属性,则layout_width
和layout_height
属性是可选的。
sample.xml Code
sample.xml代码
<?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_widthPercent
设置为75 。 另外,将其设置为100等同于match_parent。 我们可以类似的方式实现下面给出的其他布局参数。
layout_heightPercent
layout_heightPercent
layout_marginPercent
layout_marginPercent
layout_marginLeftPercent
layout_marginLeftPercent
layout_marginRightPercent
layout_marginRightPercent
layout_marginTopPercent
layout_marginTopPercent
layout_marginBottomPercent
layout_marginBottomPercent
layout_marginStartPercent
layout_marginStartPercent
layout_marginEndPercent
layout_marginEndPercent
Android垂直TextView (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.
我们使用的标准TextView小部件仅水平显示文本。 因此,我们将创建一个自定义TextView,它允许我们垂直显示文本。
The code for the VerticalTextView.java
class is given below:
下面给出了VerticalTextView.java
类的代码:
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
. 默认情况下,旋转的文本是从上到下。 如果我们设置android:gravity="bottom"
,那么它是从下到上绘制的。 我们将旋转文本的状态(从上到下/从下到上)保存在布尔变量topDown
。 - In the
onMeasure()
method we swap the width and height to draw the text rotated. 在onMeasure()
方法中,我们交换宽度和高度以绘制旋转的文本。 - Finally, in the
onDraw()
method based on thetopDown
boolean flag, we apply a rotation dependent on the gravity setting. 最后,在基于topDown
布尔标志的onDraw()
方法中,我们根据重力设置应用旋转。
Going further, let’s code an interesting Login UI Concept using Percent Layout support and Vertical TextView.
更进一步,让我们使用百分比布局支持和Vertical TextView编写一个有趣的Login UI Concept。
Android百分比布局和垂直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.
注意anim
文件夹中的xml文件。 它们将用于在登录之间创建动画,并注册布局和按钮。
Android百分比布局和垂直TextView代码 (Android Percent Layout and Vertical TextView Code)
Add the following dependency in the build.gradle
file.
在build.gradle
文件中添加以下依赖build.gradle
。
compile 'com.android.support:percent:25.3.1'
The xml layout code for activity_main.xml
is given below :
下面给出了activity_main.xml
的xml布局代码:
<?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.
我们首先让layout_sign_in.xml
占据屏幕的大部分。 此外,我们还隐藏了VerticalTextView
用于登录。 最终,当放置layout_register.xml
屏幕时,这些事情将被颠倒。
The xml layout code for layout_sign_in.xml
is given below.
下面给出了layout_sign_in.xml
的xml布局代码。
<?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.
下面给出了layout_register.xml
的xml布局代码。
<?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.
此外,每个EditText的背景都在shape.xml
文件的drawable文件夹下定义,如下所示。
<?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.
MainActivity.java
的代码如下。
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
. 我们交换layout_sign_in
内部PercentRelativeLayout
的LinearLayouts的百分比宽度(使用浮点值),即layout_sign_in
和layout_register
。 - Besides we animate the above-mentioned layouts along with showing a transition from the
VerticalTextView
to its respective Button. 此外,我们还为上述布局设置了动画,并显示了从VerticalTextView
到其相应Button的过渡。 hideSoftKeyboard()
is invoked every time aVerticalTextView
is clicked in order to dismiss any previously opened keyboard. 每次单击VerticalTextView
时,都会调用hideSoftKeyboard()
,以消除以前打开的任何键盘。Note: To hide the keyboard when the application launches, we set the
windowSoftInputMode
tohidden
in theAndroidManifest.xml
file as shown below.注意 :要在应用程序启动时隐藏键盘,我们将
windowSoftInputMode
设置为在AndroidManifest.xml
文件中hidden
,如下所示。<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.
本教程到此结束。 您可以从下面的链接下载最终的Android VerticalTextViewAndPercentLayout项目 。
Reference: android.support.percent
翻译自: https://www.journaldev.com/13937/android-percent-layout-support-vertical-textview