Android百分比布局支持和垂直TextView

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_widthlayout_heightlayout_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.

PercentRelativeLayoutPercentFrameLayout帮助我们降低了视图的复杂度,因为我们不再被迫使用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.PercentRelativeLayoutandroid.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中的RelativeLayoutFrameLayout标记。

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_widthPercentlayout_heightPercent属性,则layout_widthlayout_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。 我们可以类似的方式实现下面给出的其他布局参数。

  1. layout_heightPercent

    layout_heightPercent
  2. layout_marginPercent

    layout_marginPercent
  3. layout_marginLeftPercent

    layout_marginLeftPercent
  4. layout_marginRightPercent

    layout_marginRightPercent
  5. layout_marginTopPercent

    layout_marginTopPercent
  6. layout_marginBottomPercent

    layout_marginBottomPercent
  7. layout_marginStartPercent

    layout_marginStartPercent
  8. 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 variable topDown.

    默认情况下,旋转的文本是从上到下。 如果我们设置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 the topDown 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:

从以上代码得出的推论很少是:

  1. We interchange the percentage widths(using float values) of the LinearLayouts held inside PercentRelativeLayout namely layout_sign_in and layout_register.

    我们交换layout_sign_in内部PercentRelativeLayout的LinearLayouts的百分比宽度(使用浮点值),即layout_sign_inlayout_register
  2. Besides we animate the above-mentioned layouts along with showing a transition from the VerticalTextView to its respective Button.

    此外,我们还为上述布局设置了动画,并显示了从VerticalTextView到其相应Button的过渡。
  3. hideSoftKeyboard() is invoked every time a VerticalTextView is clicked in order to dismiss any previously opened keyboard.

    每次单击VerticalTextView时,都会调用hideSoftKeyboard() ,以消除以前打开的任何键盘。
  4. Note: To hide the keyboard when the application launches, we set the windowSoftInputMode to hidden in the AndroidManifest.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.

    android-percent-layout-vertical-textview-output

    因此,下面给出了实际应用程序的输出。

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

参考: android.support.percent

翻译自: https://www.journaldev.com/13937/android-percent-layout-support-vertical-textview

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值