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_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垂直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">