关闭

一些你需要知道的布局优化技巧

标签: 布局优化android
6637人阅读 评论(58) 收藏 举报
分类:

转载请注明出处:http://blog.csdn.net/qq_17766199/article/details/52863741

今天分享一些layout布局书写中的一些技巧,希望看过之后你也一样可以写出性价比高的布局。我个人的目标是用最少的View写出一样效果的布局。因为我相信View的数量减少伴随着的就是层级的减少。从而达到结构清晰,渲染速度快的效果。顺着这个逻辑,我将优化分为重用、合并、按需载入。

重用

< include/>

< include>标签可以在一个布局中引入另外一个布局,这个的好处显而易见。类似于我们经常用到的工具类,随用随调。便于统一修改使用。

举例说明:首先写一个公共的布局title_bar.xml,app中常用的标题栏。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:background="@color/background"
    android:layout_height="48dp">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        android:src="@drawable/icon_back"/>

    <TextView
        tools:text="标题"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="18sp"
        android:textColor="@color/white" />

    <TextView
        tools:text="确定"
        android:layout_width="wrap_content"
        android:gravity="center"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        android:textSize="16sp"
        android:textColor="@color/white" />

</RelativeLayout>

预览:

这里写图片描述

下来activity_main.xml调用它:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include
        layout="@layout/title_bar"/>

</RelativeLayout>

运行后效果和预览一样一样的。当然我们也可以在< include>标签当中重新设置宽高等layout属性。

合并

减少嵌套

首先我们心中要有一个大原则:尽量保持布局层级的扁平化。在这个大原则下我们要知道:

  • 在不影响层级深度的情况下,使用LinearLayout而不是RelativeLayout。因为RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,才会让子View调用2次onMeasure。Measure的耗时越长那么绘制效率就低。

  • 如果非要是嵌套,那么尽量避免RelativeLayout嵌套RelativeLayout。这简直就是恶性循环,丧心病狂。

实现方法就不细说了,大家都是明白人。

< merge/>

< merge/>主要用来去除不必要的FrameLayout。它的使用最理想的情况就是你的根布局是FrameLayout,同时没有使用background等属性。这时可以直接替换。因为我们布局外层就是FrameLayout,直接“合并”

举例说明:比如上面用到的activity_main.xml文件,我们通过View Hierarchy工具看一下,如图:

这里写图片描述

可以看到,最外层是FrameLayout,下来我们修改一下。

<?xml version="1.0" encoding="utf-8"?>
<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include
        layout="@layout/title_bar"/>

</merge>

再次查看:

这里写图片描述

很明显少了一层RelativeLayout,当然运行效果是一样的。当然如果我们不需要title_bar.xml中的绿色背景,那么可以这样修改。

<?xml version="1.0" encoding="utf-8"?>
<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        android:src="@drawable/icon_back_1"/>

    <TextView
        android:layout_gravity="center_horizontal"
        android:text="标题"
        android:gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:layout_centerInParent="true"
        android:textSize="18sp"
        android:textColor="@color/black" />

    <TextView
        android:text="确定"
        android:layout_gravity="right"
        android:layout_width="wrap_content"
        android:gravity="center"
        android:layout_height="48dp"
        android:layout_alignParentRight="true"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        android:textSize="16sp"
        android:textColor="@color/black" />

</merge>

运行效果:

这里写图片描述

运行查看层级,如下图:

这里写图片描述

结果很明显。

用TextView同时显示图片和文字

这个我就不细说了,举一个我们项目中的一个例子,代码一看便知。

首先要完成的效果是如下图:

这里写图片描述

这种效果很常见,一般实现方法是这样。(貌似没人这样写吧,哈哈)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:orientation="horizontal"
        android:background="@color/white"
        android:layout_width="match_parent"
        android:layout_height="50dp">

        <ImageView
            android:layout_marginLeft="10dp"
            android:layout_width="wrap_content"
            android:src="@drawable/icon_1"
            android:layout_height="match_parent" />

        <TextView
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:textSize="16sp"
            android:text="我的卡券"
            android:gravity="center_vertical"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent" />

        <ImageView
            android:layout_marginRight="10dp"
            android:src="@drawable/icon_4"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"/>
    </LinearLayout>

</LinearLayout>

效果图:

这里写图片描述

那么我们优化一下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:drawableLeft="@drawable/icon_1"
        android:drawableRight="@drawable/icon_4"
        android:drawablePadding="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textSize="16sp"
        android:text="我的卡券"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

</LinearLayout>

你没有看错,少了两个ImageView和去除嵌套LinearLayout。效果不用说一样一样的。当然EditView等也一样的,还有属性drawableBottom和drawableTop供你使用。同时利用代码setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)可以让我们动态去设置图片。

使用TextView的行间距

先上我们需要实现的效果图:

这里写图片描述

效果很简单,实现代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="100dp"
    android:background="@color/white"
    android:layout_width="match_parent"
    xmlns:tools="http://schemas.android.com/tools">

    <ImageView
        android:padding="25dp"
        android:src="@drawable/kd_1"
        android:layout_width="100dp"
        android:layout_height="100dp"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:layout_height="100dp">

        <TextView
            tools:text="揽件方式:上门取件"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="25dp"/>

        <TextView
            tools:text="快递公司:顺丰快递"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="25dp"/>

        <TextView
            tools:text="预约时间:9月6日 立即取件"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="25dp"/>

        <TextView
            tools:text="快递费用:等待称重确定价格"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="25dp"/>

    </LinearLayout>

</LinearLayout>

这里我偷懒了多嵌套了一层LinearLayout,但。。。这不重要,我先直接修改。

优化后代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="100dp"
    android:background="@color/white"
    android:layout_width="match_parent">

    <ImageView
        android:padding="25dp"
        android:src="@drawable/kd_1"
        android:layout_width="100dp"
        android:layout_height="match_parent"/>

    <TextView
        android:textSize="14dp"
        android:lineSpacingExtra="8dp"
        android:gravity="center_vertical"
        android:text="揽件方式:上门取件\n快递公司:顺丰快递\n预约时间:9月6日 立即取件\n快递费用:等待称重确定价格"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

老规矩,效果一样一样的。可以看到我们仅仅利用android:lineSpacingExtra="8dp"这一行代码就省去了3个TextView,如果行数更多呢?是不是方便多了。

其中:lineSpacingExtra属性代表的是行间距,他默认是0,是一个绝对高度值。同时还有lineSpacingMultiplier属性,它代表行间距倍数,默认为1.0f,是一个相对高度值。我们来使用一下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="100dp"
    android:background="@color/white"
    android:layout_width="match_parent">

    <ImageView
        android:padding="25dp"
        android:src="@drawable/kd_1"
        android:layout_width="100dp"
        android:layout_height="100dp"/>

    <TextView
        android:textSize="14dp"
        android:lineSpacingMultiplier="1.3"
        android:gravity="center_vertical"
        android:text="揽件方式:上门取件\n快递公司:顺丰快递\n预约时间:9月6日 立即取件\n快递费用:等待称重确定价格"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

当然了这两条属性可以同时使用,查看源码可以知道,他们的高度计算规则为mTextPaint.getFontMetricsInt(null) * 行间距倍数 + 行间距。

使用Spannable或Html.fromHtml

这里也是举例说明,比如下图效果:

这里写图片描述

如果实现上图红框中的效果,笨办法就是写三个TextView,“¥”,“价格”,“门市价”分别实现,其实用一个TextVIew就可以实现,类似如下代码:

 String text = String.format("¥%1$s  门市价:¥%2$s", 18.6, 22);
 int z = text.lastIndexOf("门");
 SpannableStringBuilder style = new SpannableStringBuilder(text);
 style.setSpan(new AbsoluteSizeSpan(DisplayUtil.dip2px(mContext,14)), 0, 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //字号
 style.setSpan(new ForegroundColorSpan(Color.parseColor("#afafaf")), z, text.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //颜色
 style.setSpan(new AbsoluteSizeSpan(DisplayUtil.dip2px(mContext,14)), z, text.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //字号

 tv.setText(style);

同样Html.fromHtml也可以实现。这样不就减少了两个TextView了。

按需载入

ViewStub

在开发中经常会遇到这样的情况,会在程序运行时动态根据条件来决定显示哪个View或某个布局。那么通常做法就是把用到的View都写在布局中,然后在代码中动态的更改它的可见性。但是它的这样仍然会创建View,会影响性能。

这时就可以用到ViewStub了,ViewStub是一个轻量级的View,不占布局位置,占用资源非常小。

例子:比如我们请求网络加载列表,如果网络异常或者加载失败我们可以显示一个提示View,上面可以点击重新加载。当然一直没有错误时,我们就不显示。

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    ……
    <ViewStub
        android:layout_gravity="center"
        android:id="@+id/hint_view"
        android:layout_width="match_parent"
        android:inflatedId="@+id/hint_view"
        android:layout_height="wrap_content"
        android:layout="@layout/hint_view"/>
</merge>

hint_view.xml就是这个提示View,可以根据情况自己写。

用法:

private View hintView;

if (网络异常。。。) {
    if (hintView == null) {
        ViewStub viewStub = (ViewStub)this.findViewById(R.id.hint_view);
        hintView = viewStub.inflate();
        TextView textView = (TextView) hintView.findViewById(R.id.tv);
        textView.setText("网络异常!");
    }
    hintView.setVisibility(View.VISIBLE);
}else{
    if (hintView != null) {
        hintView.setVisibility(View.GONE);
    }
}

用法很简单,记得一旦ViewStub可见或是被inflate了,ViewStub就不存在了,取而代之的是被inflate的Layout。所以它也被称做惰性控件。

其他小技巧

用LinearLayout自带的分割线

还记得上文用TextView同时显示图片和文字中的例子吗?我们可以看到每个条目之间都是有一根分隔线的,那么怎么实现呢?别人我不知道,反正我原来是用一个View设置高度实现的。相信一定有人和我一样。

那么老办法我就不演示了,直接上代码:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:divider="@drawable/divider"
    android:showDividers="middle">

    <TextView
        android:drawableLeft="@drawable/icon_1"
        android:drawableRight="@drawable/icon_4"
        android:drawablePadding="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textSize="16sp"
        android:text="我的卡券"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

    <TextView
        android:drawableLeft="@drawable/icon_2"
        android:drawableRight="@drawable/icon_4"
        android:drawablePadding="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textSize="16sp"
        android:text="地址管理"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

    <TextView
        android:drawableLeft="@drawable/icon_3"
        android:drawableRight="@drawable/icon_4"
        android:drawablePadding="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textSize="16sp"
        android:text="检查更新"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

</LinearLayout>

效果图:

这里写图片描述

实现的核心部分其实是LinearLayout的这两行。

android:divider="@drawable/divider"
android:showDividers="middle"

其中divider.xml是分隔线样式。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">

    <size android:width="1dp"
          android:height="1dp"/>

    <solid android:color="#e1e1e1"/>

</shape>

showDividers 是分隔线的显示位置,beginning、middle、end分别代表显示在开始位置,中间,末尾。

还有dividerPadding属性这里没有用到,意思很明确给divider添加padding。感兴趣可以试试。

Space控件

还是接着上面的例子,如果要给条目中间添加间距,怎么实现呢?当然也很简单,比如添加一个高10dp的View,或者使用android:layout_marginTop="10dp"等方法。但是增加View违背了我们的初衷,并且影响性能。使用过多的margin其实会影响代码的可读性。

这时你就可以使用Space,他是一个轻量级的。我们可以看下源码:

/**
 * Space is a lightweight View subclass that may be used to create gaps between components
 * in general purpose layouts.
 */
public final class Space extends View {
    /**
     * {@inheritDoc}
     */
    public Space(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        if (getVisibility() == VISIBLE) {
            setVisibility(INVISIBLE);
        }
    }

    /**
     * {@inheritDoc}
     */
    public Space(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    /**
     * {@inheritDoc}
     */
    public Space(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    /**
     * {@inheritDoc}
     */
    public Space(Context context) {
        //noinspection NullableProblems
        this(context, null);
    }

    /**
     * Draw nothing.
     *
     * @param canvas an unused parameter.
     */
    @Override
    public void draw(Canvas canvas) {
    }

    /**
     * Compare to: {@link View#getDefaultSize(int, int)}
     * If mode is AT_MOST, return the child size instead of the parent size
     * (unless it is too big).
     */
    private static int getDefaultSize2(int size, int measureSpec) {
        int result = size;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        switch (specMode) {
            case MeasureSpec.UNSPECIFIED:
                result = size;
                break;
            case MeasureSpec.AT_MOST:
                result = Math.min(size, specSize);
                break;
            case MeasureSpec.EXACTLY:
                result = specSize;
                break;
        }
        return result;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(
                getDefaultSize2(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize2(getSuggestedMinimumHeight(), heightMeasureSpec));
    }
}

可以看到在draw方法没有绘制任何东西,那么性能也就几乎没有影响。

实现代码与效果:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:divider="@drawable/divider"
    android:showDividers="middle|beginning|end">

    <TextView
        android:drawableLeft="@drawable/icon_1"
        android:drawableRight="@drawable/icon_4"
        android:drawablePadding="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textSize="16sp"
        android:text="我的卡券"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

    <TextView
        android:drawableLeft="@drawable/icon_2"
        android:drawableRight="@drawable/icon_4"
        android:drawablePadding="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textSize="16sp"
        android:text="地址管理"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

    <Space
        android:layout_width="match_parent"
        android:layout_height="15dp"/>

    <TextView
        android:drawableLeft="@drawable/icon_3"
        android:drawableRight="@drawable/icon_4"
        android:drawablePadding="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textSize="16sp"
        android:text="检查更新"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

</LinearLayout>

这里写图片描述

防止过度绘制

这个完全可以看鸿洋大神这篇 《Android UI性能优化实战 识别绘制中的性能问题》:http://blog.csdn.net/lmj623565791/article/details/45556391

参考

总结

最后想想如果没有用这些技巧,我们要写多少代码,多少View?效果是不是杠杠的!其实上面说了这么多,具体的情景使用还是要看项目的具体情况,在性能面前有些还是要取舍的,但千万不能为了优化而优化。优化也是不断积累的过程,不要指望立竿见影。愿大家都能写出一手漂亮的布局。最后觉得不错的点个赞哈!

53
0
查看评论

Android最佳性能实践(四)——布局优化技巧

在前面几篇文章当中,我们学习了如何通过合理管理内存,以及高性能编码技巧的方式来提升应用程序的性能。然而实际上界面布局也会对应用程序的性能产生比较大的影响,如果布局写得糟糕的话,那么程序加载UI的速度就会非常慢,从而造成不好的用户体验。那么本篇文章我们就来学习一下,如何通过优化布局来提供应用程序的性能...
  • sinyu890807
  • sinyu890807
  • 2015-03-19 09:21
  • 59211

Android开发学习之路--性能优化之布局优化

Android性能优化方面也有很多文章了,这里就做一个总结,从原理到方法,工具等做一个简单的了解,从而可以慢慢地改变编码风格,从而提高性能。一、Android系统是如何处理UI组件的更新操作的  既然和布局相关,那么我们需要了解Android系统是如何处理UI组件的更新操作的。   1、Andro...
  • eastmoon502136
  • eastmoon502136
  • 2016-12-31 21:27
  • 1402

Android性能优化系列之布局优化

在Android开发中,UI布局可以说是每个App使用频率很高的,随着UI越来越多,布局的重复性、复杂度也会随之增长,这样使得UI布局的优化,显得至关重要,UI布局不慎,就会引起过度绘制,从而造成UI卡顿的情况,本篇博客,我就来总结一下UI布局优化的相关技巧。学会使用布局标签优化布局(1)<i...
  • u012124438
  • u012124438
  • 2017-01-15 22:20
  • 7405

Android中的布局优化方法

Android开发中的布局很重要吗?那是当然。一切的显示样式都是由这个布局决定的,你说能不重要吗。要实现一个好的布局,不只是实现了、显示出来就完了,不管层次,堆砌代码也可以实现功能,但是这显然违背了Android布局设计的原则。可能你会说,Android布局设计哪有什么原则,我可以明确告诉你,当然有...
  • rwecho
  • rwecho
  • 2013-05-20 16:06
  • 18648

Android性能优化(二),Layout布局优化

原文地址:
  • boyupeng
  • boyupeng
  • 2015-08-20 13:53
  • 1432

Android 布局优化之include与merge

官方提供了三个用来优化布局的标签,分别是include、merge与ViewStub,其中ViewStub是动态加载视图到内存,大家可以查阅:Android UI布局优化之ViewStub 一、include布局重用:在Android的应用程序开发
  • a740169405
  • a740169405
  • 2016-01-15 11:30
  • 10878

Android性能优化之布局优化篇

怎样才能写出优秀的Android App,是每一个程序员追求的目标。那么怎么才能写出一个优秀的App呢?相信很多初学者也会有这种迷茫。一句话来回答这个问题:细节很重要。今天我们就从最基础的XML布局来谈谈怎么提高Android性能问题吧! 也许你经常会遇到比较复杂的布局,这种情况下,最简单的方法就...
  • feidu804677682
  • feidu804677682
  • 2015-06-29 16:28
  • 3442

Android开发——布局性能优化的一些技巧(二)

0. 前言上一篇我们介绍了布局性能优化里常用的技巧,比如减少布局层级、按需加载、合并等技巧。这篇是受唯鹿的博客的启发,总结的一些Android布局优化的小技巧,虽然不能达到立竿见影的布局优化效果,毕竟优化是一个持之以恒的过程,但是看完一定会带给你耳目一新的感觉,定会有所收获。本文原创,转载...
  • SEU_Calvin
  • SEU_Calvin
  • 2016-11-30 10:17
  • 1468

Android UI布局优化之ViewStub

在设计模式的单利模式中,懒汉式和饿汉式是其中两种。 一种是在类被加载的时候就完成单例对象的初始化,一种是在需要使用该单例的时候才初始化。 在android的视图设计中,同样需要使用的这样的设计模式。 这样的视图加载起来需要耗费很多的时间。在这几百个视图里面,可能有部分视图是在点击某一按钮也就是...
  • a740169405
  • a740169405
  • 2016-01-15 13:50
  • 2897

Android 性能优化之布局优化 (二)

Android 性能优化之布局优化 (二)
  • u014608640
  • u014608640
  • 2016-09-12 10:28
  • 985
    个人资料
    • 访问:217404次
    • 积分:3261
    • 等级:
    • 排名:第12367名
    • 原创:70篇
    • 转载:10篇
    • 译文:0篇
    • 评论:228条
    多多支持
    博客专栏
    最新评论