Android百分比布局支持和垂直TextView
在本教程中,我们将讨论并实现Android Percent Layout支持库。
此外,我们将创建一个垂直TextView。
最后,我们将把这两个概念合并在一起,在我们的应用程序中编写有趣的登录屏幕设计概念。
Android百分比布局支持概述
Android API 23引入了对Android Percent Layout的支持。
该库使我们可以为" layout_width"," layout_height"和" layout_margin"指定百分比值。
因此,PercentRelativeLayout是一个RelativeLayout,具有为子视图分配权重的附加功能(类似PercentFrameLayout),这是LinearLayouts中一直存在的功能。
因此,我们可以对百分比布局中存在的子视图组件的宽度,高度,边距设置一个百分比(满分为100)。
PercentRelativeLayout和PercentFrameLayout帮助我们降低了视图的复杂度,因为我们不再被迫使用LinearLayout封装子视图并为子视图使用权重。
要使用百分比布局支持,请将以下依赖项添加到build.gradle文件中。compile'com.android.support:percent:25.3.1'
添加以上依赖项后,我们就可以在应用程序中使用" android.support.percent.PercentRelativeLayout"和" android.support.percent.PercentFrameLayout"。
结果,我们现在可以分别用PercentRelativeLayout和PercentFrameLayout替换xml中的RelativeLayout和FrameLayout标记。
Android百分比支持布局示例
让我们看一看" layout_widthPercent"的示例实现。
app:layout_widthPercent:其中我们以百分比设置视图宽度。
注意:在PercentRelativeLayout中,如果我们指定了layout_widthPercent或者layout_heightPercent属性,那么layout_width和layout_height属性是可选的。
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.theitroad.percentlayouts.MainActivity">
<TextView
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="20sp"
app:layout_widthPercent="75%"
</android.support.percent.PercentRelativeLayout>
输出:
We've set the layout_widthPercentto 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垂直TextView
我们使用的标准TextView小部件仅水平显示文本。
因此,我们将创建一个自定义TextView,使我们可以垂直显示文本。
下面是VerticalTextView.java类的代码:
package com.theitroad.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();
}
}
默认情况下,旋转的文本是从上到下。
如果我们设置" android:gravity =" bottom"",那么它是从下往上绘制的。
我们将旋转文本的状态(从上到下/从下到上)保存在布尔变量" topDown"中。在" onMeasure()"方法中,我们交换宽度和高度以绘制旋转的文本。
最后,在基于topDown布尔标志的onDraw()方法中,我们根据重力设置应用旋转。
更进一步,让我们使用百分比布局支持和Vertical TextView编写有趣的登录UI概念代码。
Android百分比布局和垂直TextView项目结构
记下" anim"文件夹中的xml文件。
它们将用于在登录之间设置动画,并注册布局和按钮。
Android百分比布局和垂直TextView代码
在build.gradle文件中添加以下依赖项。
compile 'com.android.support:percent:25.3.1'
下面给出了" 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.theitroad.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.theitroad.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>
注意上面代码中指定的百分比。
首先,让" layout_sign_in.xml"占据屏幕的大部分。
此外,我们还为登录隐藏了" VerticalTextView"。
最终,当放置" layout_register.xml"屏幕时,这些事情将被颠倒。
下面给出了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>
下面给出了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>
另外,每个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>
下面给出了MainActivity.java的代码。
package com.theitroad.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);
}
}
}
从上面的代码得出的推论很少是:
我们交换在PercentRelativeLayout内部保存的LinearLayouts的百分比宽度(使用浮点值),即layout_sign_in和layout_register。
除此之外,我们还为上述布局设置了动画,并显示了从" VerticalTextView"到其相应Button的过渡。
每次单击" VerticalTextView"时都会调用" hideSoftKeyboard()",以关闭任何先前打开的键盘。
注意:要在应用程序启动时隐藏键盘,我们将AndroidManifest.xml文件中的" windowSoftInputMode"设置为" hidden",如下所示。
<activity
android:name=".MainActivity"
android:windowSoftInputMode="stateHidden">

