标签: CardView

关于使用 CardView 开发过程中要注意的细节

随着 Google 推出了全新的设计语言 Material Design,还迎来了新的 Android 支持库 v7,其中就包含了 Material Design 设计语言中关于 Card 卡片概念的实现 —— CardView。经历了相当长的一段时间相信许多 Android 开发者都已经应用了这个控件,现在才写这篇文章可能有点晚,但对于刚刚开始使用的开发者以及其他已经使用了一段时间但做出来效果不好的同学应该能帮上点小忙。

1445743597932111.png

正题开始~

◆ 注意不同 SDK 版本(低于 Lollipop 21)上的边距(Margin)效果

Google 在 Android Lollipop 中引入了 Material Design 设计中的阴影(Elevation)和 Z 轴位移,其目的就是突出界面中不同元素之间的层次关系。为了统一不同系统版本的视觉效果,Google 针对 SDK 21 以下的系统给 CardView 加入一个 Elevation 兼容(即 XML 中的 app:cardElevation 和 Java 代码中的 setCardElevation)。
然而,在低版本中设置了 CardElevation 之后 CardView 会自动留出空间供阴影显示,而 Lollipop 之后则需要手动设置 Margin 边距来预留空间,导致我在设置 Margin 在 Android 5.x 机器上调试好后,在 Kitkat 机器调试时发现边距非常大,严重地浪费了屏幕控件。
因此,我们需要自定义一个 dimen 作为 CardView 的 Margin 值:

  1. 创建 /res/values 和 /res/values-v21 资源文件夹于项目对应 Module 目录下,前者放置旧版本/通用的资源文件(了解的可以跳过),后者放置 21 及更高 SDK 版本的资源文件。
  2. 在 values 内的 dimen.xml 创建一个 Dimension (<dimen> 属性),随便命个名(如 xxx_card_margin)并填入数值 0dp。
  3. 接着在 values-v21 文件夹内的 dimen.xml 创建名字相同的 Dimension,并填入你期望的预留边距(一般和 CardElevation 阴影大小相同)
  4. *后,在你布局中的 CardView 中设置 android:layout_margin="@dimen/xxx_card_margin"

这样依赖就解决了低版本中边距过大或者视觉效果不统一的问题了。

◆ 为你的 Card 添加点击效果

当使用 CardView 的场合是作为列表中的一个 Item 且直接单击 Item 有相应的操作,那么就有必要加上视觉反馈来告诉用户这个 Card 是可点击的。

%title插图%num

(此处用其他例子代替 CardView 演示)

如果你是用了 AppCompat v7 支持库:
那么你可以直接给 CardView 加上 android:foreground="?attr/selectableItemBackground" 这个属性会在 Lollipop 上自动加上 Ripple 效果,在旧版本则是一个变深/变亮的效果。

如果你没使用这个支持库或者觉得这个效果在旧版本显得有点僵硬:
你可以尝试自定义一个 Drawable,和上一条一样根据不同 SDK 版本分别编写不同的效果,在此就不多介绍自定义 Drawable 的方法。

◆ 让点击效果更加贴近 Material Design

上面曾提到过一个概念:Z 轴位移,即决定元素层次的深度,与 Elevation 大小相加构成实际显示的阴影深度。
在 Material Design Guidelines 中有建议卡片、按钮这类元素触摸时应当有一个浮起的效果,也就是增大 Z 轴位移

 

要实现这个效果并不难,我们只需要借助 Lollipop 的一个新属性 android:stateListAnimator (PS:这也意味着这个方法不可以用于旧版本系统QAQ)

首先,创建一个 TranslationZ 的变换动画放在 /res/anim,自己取一个名(如 touch_raise.xml),加入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<? xml version = "1.0" encoding = "utf-8" ?>
< selector xmlns:android = "http://schemas.android.com/apk/res/android" >
      < item android:state_enabled = "true" android:state_pressed = "true" >
           < objectAnimator
                android:duration = "@android:integer/config_shortAnimTime"
                android:propertyName = "translationZ"
                android:valueTo = "@dimen/touch_raise"
                android:valueType = "floatType" />
      </ item >
      < item >
            < objectAnimator
            android:duration = "@android:integer/config_shortAnimTime"
            android:propertyName = "translationZ"
            android:valueTo = "0dp"
            android:valueType = "floatType" />
      </ item >
</ selector >

然后为你需要添加效果的 CardView(其他 View 同理)所在的 Layout XML 复制多一份到 /res/layout-v21,然后在新的那份 XML 的 CardView 中加入属性 android:stateListAnimator="@anim/touch_raise"。
这样,你的卡片按住时就会有浮起(阴影加深)的效果了。

◆ 尽量不要用作固定高度的 List Item

除了横向滚动列表和类似 Google Play 音乐中的带封面图片卡片 Item,其他地方应该尽量避免做固定高度的卡片。
举一个错误例子,我之前写的快递查询应用「水表助手」,快递卡片就是用了固定宽度(误人子弟系列QAQ)

 

不需要用卡片的地方也不应该使用,滥用只会让用户更快地厌倦你的界面设计。

1445743798116099.png

(这个是复制自官方的错误范例)

◆ 低版本(低于 Lollipop)的 setElevation 不是万能的

由于缺少一些系统 API(如 RenderThread),CardView 中的 Elevation 兼容实现并不完美,和真正的实现方法还是有较大的差距(不是指效果),所以调用 setCardElevation 也不能随心所欲地传入一个 Float 型,在低版本系统使用时应当处理一下传入的数值(似乎只能是整数,碰到过错误但是没详细研究……懒癌请原谅)或加上 try-catch (不推荐)。

————————我是分割线————————

除了本文提到的五个点,CardView 还有许多需要注意的地方,在这里就不一一列举了~

对于实现 Material Design 卡片,CardView 并不是唯一的选择,也有人通过自己写 Drawable、Layout 来实现出性能更好的卡片效果,但对在这方面不擅长的同学来说 CardView 算是*好的选择,毕竟是 Google 自家的东西,在效果、兼容性方面都十分到位。

Android开发:使用CardView实现卡片式设计

开头引用一段官网的介绍

A FrameLayout with a rounded corner background and shadow.

CardView uses elevation property on Lollipop for shadows and falls back to a custom emulated shadow implementation on older platforms.

Due to expensive nature of rounded corner clipping, on platforms before Lollipop, CardView does not clip its children that intersect with rounded corners. Instead, it adds padding to avoid such intersection (See setPreventCornerOverlap(boolean) to change this behavior).

Before Lollipop, CardView adds padding to its content and draws shadows to that area. This padding amount is equal to maxCardElevation + (1 - cos45) * cornerRadius on the sides and maxCardElevation * 1.5 + (1 - cos45) * cornerRadius on top and bottom.

Since padding is used to offset content for shadows, you cannot set padding on CardView. Instead, you can use content padding attributes in XML or setContentPadding(int, int, int, int) in code to set the padding between the edges of the CardView and children of CardView.

Note that, if you specify exact dimensions for the CardView, because of the shadows, its content area will be different between platforms before Lollipop and after Lollipop. By using api version specific resource values, you can avoid these changes. Alternatively, If you want CardView to add inner padding on platforms Lollipop and after as well, you can callsetUseCompatPadding(boolean) and pass true.

To change CardView’s elevation in a backward compatible way, use setCardElevation(float). CardView will use elevation API on Lollipop and before Lollipop, it will change the shadow size. To avoid moving the View while shadow size is changing, shadow size is clamped by getMaxCardElevation(). If you want to change elevation dynamically, you should call setMaxCardElevation(float)when CardView is initialized.

简单的效果图:

%title插图%num

简略版介绍

Apps often need to display data in similarly styled containers. These containers are often used in lists to hold each item’s information. The system provides the CardView API as an easy way for you show information inside cards that have a consistent look across the platform. These cards have a default elevation above their containing view group, so the system draws shadows below them. Cards provide an easy way to contain a group of views while providing a consistent style for the container.

开始使用

  1. Add the dependencies

The CardView widget is part of the v7 Support Libraries. To use it in your project, add the following dependency to your app module’s build.gradle file:

Cardview 是Android 5.0 才引入的,所以需要导入这个依赖包。

  1. dependencies {
  2. implementation ‘com.android.support:cardview-v7:27.1.1’
  3. }
  1. Create Cards

In order to use the CardView you need to add it to your layout file. Use it as a view group to contain other views. In this example, the CardView contains a single TextView to display some information to the user.

XML代码就是前面分析的那个,这里不再重复了。

The cards are drawn to the screen with a default elevation, which causes the system to draw a shadow underneath them. You can provide a custom elevation for a card with the card_view:cardElevation attribute. This will draw a more pronounced shadow with a larger elevation, and a lower elevation will result in a lighter shadow. CardView uses real elevation and dynamic shadows on Android 5.0 (API level 21) and above and falls back to a programmatic shadow implementation on earlier versions.

Use these properties to customize the appearance of the CardView widget:

  • To set the corner radius in your layouts, use the card_view:cardCornerRadius attribute.
  • To set the corner radius in your code, use the CardView.setRadius method.
  • To set the background color of a card, use the card_view:cardBackgroundColor attribute.

For more information, see the API reference for CardView.

关于Cards的设计规范可以参考官网介绍:https://material.google.com/components/cards.html#

为了更好地实现这种 Cards UI 的设计,Google在v7包中引进了一种全新的控件:CardVew,本文将从开发的角度介绍CardView的一些常见使用细节。

Google用一句话介绍了CardView:一个带圆角和阴影背景的FrameLayout。CardView在Android Lollipop(API 21)及以上版本的系统中适配较好,本文我们以一个具体的例子来学习CardView的基本使用和注意事项,效果图如下:

%title插图%num

这是一个list列表,列表中的item使用了卡片式设计,主要利用CardView控件实现,下面来分析一下布局文件的核心代码。

  1. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
  2. xmlns:tools=“http://schemas.android.com/tools”
  3. xmlns:card_view=“http://schemas.android.com/apk/res-auto”
  4. >
  5. <!– A CardView that contains a TextView –>
  6. <android.support.v7.widget.CardView
  7. xmlns:card_view=“http://schemas.android.com/apk/res-auto”
  8. android:id=“@+id/card_view”
  9. android:layout_gravity=“center”
  10. android:layout_width=“200dp”
  11. android:layout_height=“200dp”
  12. card_view:cardCornerRadius=“4dp”>
  13. <TextView
  14. android:id=“@+id/info_text”
  15. android:layout_width=“match_parent”
  16. android:layout_height=“match_parent” />
  17. </android.support.v7.widget.CardView>
  18. </LinearLayout>

可以看出,核心部分在于CardView的属性使用,下面我们针对几个特殊的属性逐一分析,深化了解。

关于Z轴

Android5.0 引入了Z轴的概念,可以让组件呈现3D效果.

%title插图%num

排版技巧

前面我们说过,CardView从本质上属于FrameLayout,而CardView通常包含了较多的内容元素,为了方便地排版布局中的各个元素,一般借助于其他基本布局容器,比如这里我们使用了一个RelativeLayout作为CardView的唯一Child。

Shadow Padding

在Android Lollipop之前的系统,CardView会自动添加一些额外的padding空间来绘制阴影部分,这也导致了以Lollipop为分界线的不同系统上CardView的尺寸大小不同。为了解决这个问题,有两种方法:*种,使用不同API版本的dimension资源适配(也就是借助values和values-21文件夹中不同的dimens.xml文件);第二种,就是使用cardUseCompatPadding属性,设置为true(默认值为false),让CardView在不同系统中使用相同的padding值。

圆角覆盖

这也是一个解决系统兼容的问题。在pre-Lollipop平台(API 21版本之前)上,CardView不会裁剪内容元素以满足圆角需求,而是使用添加padding的替代方案,从而使内容元素不会覆盖CardView的圆角。而控制这个行为的属性就是cardPreventCornerOverlap,默认值为true。在本例中我们设置了该属性为false。这里我们看一下,在pre-Lollipop平台中,不同cardPreventCornerOverlap值的效果对比图(左false,右true):

%title插图%num

显然,默认值下自动添加padding的方式不可取,所以需要设置该属性值为false。需要注意的一点是,该属性的设置在Lollipop及以上版本的系统中没有任何影响,除非cardUseCompatPadding的值为true。

Ripple效果

Cards一般都是可点击的,为此我们使用了foreground属性并使用系统的selectableItemBackground值,同时设置clickable为true(如果在java代码中使用了cardView.setOnClickListener,就可以不用写clickable属性了),从而达到在Lollipop及以上版本系统中实现点击时的涟漪效果(Ripple)。在pre-Lollipop版本中,则是一个普通的点击变暗的效果。

lift-on-touch

根据官网Material motion部分对交互动作规范的指导,Cards、Button等视图应该有一个触摸抬起(lift-on-touch)的交互效果,也就是在三维立体空间上的Z轴发生位移,从而产生一个阴影加深的效果,与Ripple效果共同使用,官网给了一个很好的示例图:

%title插图%num

 

在实现这个效果也很简单,可以在res/drawable目录下建立一个lift_on_touch.xml文件,内容如下:

  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2. <!– animate the translationZ property of a view when pressed –>
  3. <selector xmlns:android=“http://schemas.android.com/apk/res/android”>
  4. <item
  5. android:state_enabled=“true”
  6. android:state_pressed=“true”>
  7. <set>
  8. <objectAnimator
  9. android:duration=“@android:integer/config_shortAnimTime”
  10. android:propertyName=“translationZ”
  11. android:valueTo=“6dp”
  12. android:valueType=“floatType”/>
  13. </set>
  14. </item>
  15. <item>
  16. <set>
  17. <objectAnimator
  18. android:duration=“@android:integer/config_shortAnimTime”
  19. android:propertyName=“translationZ”
  20. android:valueTo=“0”
  21. android:valueType=“floatType”/>
  22. </set>
  23. </item>
  24. </selector>

即通过属性动画动态改变translationZ值,沿着Z轴,从0dp到6dp变化。这里的6dp值也是有出处的,参考Google I/O 2014 app和Assign Elevation to Your Views。然后将其赋值给android:stateListAnimator属性即可。由于stateListAnimator属性只适用于Lollipop及以上版本,为了隐藏xml中的版本警告,可以指定tools:targetApi="lollipop"

关于这个功能,需要补充说明一点。这里的lift_on_touch.xml,严格意义上来讲,属于anim资源,同时适用于API 21及以上版本,所以按道理上来讲应该将其放置在res/anim-v21目录下,然后使用@anim/lift_on_touch赋值给stateListAnimator属性,而不是例子中的@drawable/lift_on_touch方法。但是放置在res/anim-v21目录下会产生一个“错误”提示:

<selector style="box-sizing: border-box;">XML file should be in either “animator” or “drawable”,not “anim”</selector>

虽然这个“错误”不影响编译运行,但是对于追求完美主义的程序员们来说还是碍眼,所以本例中我选择将其放在了res/drawable目录下,大家可以自行斟酌使用。

关于对lift-on-touch效果的理解,YouToBe网站有个视频解说,感兴趣的话可以参看看,地址如下:
DesignBytes: Paper and Ink: The Materials that Matter

总结说明

CardView还有一些其他属性可供使用,比如cardElevation设置阴影大小,contentPadding代替普通android:padding属性等,比较基础,本文就不一一介绍了,大家可以在官网上参考学习。从上面的介绍可以看出,在使用CardView时基本上都会用到一些标准配置的属性,我们可以借助style属性,将其封装到styles.xml文件中,统一管理,比如:

  1. <style name=“AppCardView” parent=“@style/CardView.Light”>
  2. <item name=“cardPreventCornerOverlap”>false</item>
  3. <item name=“cardUseCompatPadding”>true</item>
  4. <item name=“android:foreground”>?attr/selectableItemBackground</item>
  5. <item name=“android:stateListAnimator” tools:targetApi=“lollipop”>@anim/lift_up</item>
  6. ……
  7. </style>

 

CardView的layout_margin属性不起作用

使用CardView作为适配器的Item布局的根View,在RecyclerView.Adapter中的onCreateViewHolder中加载Item布局的时候,如果使用的LayoutInflater.from(Context).inflate(layoutId,null)这个方法来加载布局的话,那么Item布局中的CardView中的有些属性是无法起作用的,比如:android:layout_margin=”xxdp”,就算设置了这个属性,但是在5.1系统是不能显示为卡片式的,但是在4.4系统是可以显示为卡片式的。

如果要在5.1系统中也能显示为卡片式布局,那么需要更换inflate加载布局的方法,更换为LayoutInflater.from(Context).inflate(layoutId,parent,false),

使用这个方法,就能在5.1系统显示卡片式布局,同时在4.4系统同样能够显示卡片式。

从源码层面查看两个方法的区别:

调用这两个方法都会执行到LayoutInflater的inflate方法中:

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
final Resources res = getContext().getResources();
if (DEBUG) {
Log.d(TAG, “INFLATING from resource: \”” + res.getResourceName(resource) + “\” (”
+ Integer.toHexString(resource) + “)”);
}

final XmlResourceParser parser = res.getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
}
两个方法的区别:
1、LayoutInflater.from(Context).inflate(layoutId,null)

会先调用方法

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
return inflate(resource, root, root != null);
}
*终调用inflate方法时,三个参数分别是 inflate(layoutId,null,false)。

2、LayoutInflater.from(Context).inflate(layoutId,parent,false)

这个方法会直接执行上面的方法,此时参数分别是inflate(layoutId,parent,false),在这个例子中parent为RecyclerView的实例。

这里采用加载布局的方法不同,其实*终是传入inflate的参数不同,那么参数不同会导致什么结果呢?

进入下面的方法查看:

inflate(parser, root, attachToRoot)
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
//省略其他代码,直接看相关的代码
if (root != null) {//第二种方法
final View temp = createViewFromTag(root, name, attrs, false);//temp就是CardView

// Create layout params that match root, if supplied
params = root.generateLayoutParams(attrs);
if (!attachToRoot) {
// Set the layout params for temp if we are not
// attaching. (If we are, we use addView, below)
temp.setLayoutParams(params);//给temp设置ViewGroup.LayoutParams的属性(在本例中是GridLayoutManager)
}
}

// 这个方法会将temp下的所有子控件全部加载进来。
rInflate(parser, temp, attrs, true, true);

if (root != null && attachToRoot) {//第二种方法会执行
root.addView(temp, params);
}

if (root == null || !attachToRoot) {
result = temp;//*终会返回这个result
}
}
*种方法是进入上面的方法后,加载完子控件后直接返回CardView,没有添加到root中,所以layout_margin属性不起作用,因为layout_margin属性是需要一个父控件作为参照物的,没有添加到root就没有参照物了。
第二种方法是加载完所有子控件并且添加到root后,再返回CardView,CardView已经有参照物父控件root,所以属性能起到作用。

在做的时候,因为采用的是*种方法,一直android:layout_margin=”xx”的值,但是一直都没起任何作用。在更换为第二种方法后,才显示正常。

写在*后的话:

本来想着能实现了就行了,但是作为一个有追求(…)的程序猿,必须得知道为什么会这样才行,所以才想看看源码,看能不能找到原因,看了这一点点源码后,就把自己的理解写出来了,正确与否还有待验证哈。

*次涉及源码的解读分析,才发现还是看源码看得少,虽然是个简单的分析,但还是有收获的。

遗留问题:

还有一个问题是,为什么*种方法在4.4系统时就可以显示想要的效果,在5.1系统就不能显示那种效果呢。

如果有人知道,能够知会一声就更好了。

————————————————

CardView使用与兼容

1.5.0版本:

%title插图%num

2.细节:margin与阴影(5.0+)

4.4因为阴影比较大,所以需要设置android:layout_margin=”0dp”,减小阴影

%title插图%num

3.按压下沉,阴影加重效果:

5.0以上才有

4.4需要自己自定义

1 android:stateListAnimator="@drawable/z_translation"

%title插图%num

4.关于app:contentPadding:

5.0上面需要设置这个,不然里面TextView会贴到圆角上

%title插图%num

图1

%title插图%num

图2

%title插图%num

图3

4.4上面不需要设置这个

5.关于app:cardCornerRadius边框圆角:

5.0+ 图片和布局都可以很好的呈现圆角效果,图片也变圆角了

%title插图%num

4.x 图不能变成圆角,如果要做成5.x一样的效果:通过加载图片的时候自己去处理成圆角

 

6.关于app:cardElevation:

app:cardElevation=”10dp” 阴影效果 (值越大阴影效果越明显)

 

7.5.0效果图:

%title插图%num

 

快速讲解CardView的使用

CardView和RecyclerView一样是Android5.0以后新出现的控件,伴随着Material Design设计而诞生。

一、引入CardView

在AS新建项目中需要使用CardView组件,和RecyclerView一样,需要在Gradle里面提前加入CardView的

包,直接在Gradle中加入:

compile ‘com.android.support:cardview-v7:25.3.1’(CardView版本号与项目里面V7版本号相同即可)

或者在Library dependence中输入CardView,选择V7包下那个即可。

二、为何使用CardView

CardView是继承自FramLayout的一个布局控件,官网里对CardView的注释为:

A FrameLayout with a rounded corner background and shadow.(CardView为带圆角和阴影的FramLayout)

以往,我们需要自定义Shape来实现圆角和阴影效果;现在,这些效果集成到了CardView的属性里。同时,

CardView应该被使用在显示层次性的内容时,在显示列表或网格时更应该被选择,因为这些边缘可以使得用户

更容易去区分这些内容。

三、CardView属性

app:cardBackgroundColor      设置背景颜色

app:cardCornerRadius         设置圆角大小

app:cardElevation            设置z轴阴影高度

app:cardMaxElevation         设置z轴*大高度值

app:contentPadding           内容与边距的间隔

app:contentPaddingLeft       内容与左边的间隔

app:contentPaddingTop        内容与顶部的间隔

app:contentPaddingRight      内容与右边的间隔

app:contentPaddingBottom     内容与底部的间隔

app:paddingStart             内容与边距的间隔起始

app:paddingEnd               内容与边距的间隔终止

app:cardUseCompatPadding     设置内边距,在API21及以上版本和之前的版本仍旧具有一样的计算方式

app:cardPreventConrerOverlap 在API20及以下版本中添加内边距,这个属性为了防止内容和边角的重叠

注意:CardView中使用android:background设置背景颜色无效。

Ps:多说一句,有时候部分人为了突出这些属性是在CardView中使用的,会在CardView内重新命名属性名,

如:xmlns:card_view=”http://schemas.android.com/apk/res-auto”,那么app就会变成card_view,但是

直接使用app不影响什么,只是一个属性前缀名的变化。

四、点击CardView出现波纹(Ripple)效果

在CardView布局中加入:android:foreground=”?android:attr/selectableItemBackground”即可实现

点击CardView出现波纹效果。

 

友情链接:

CardView更多使用细节

http://www.open-open.com/lib/view/open1476847497671.html
————————————————

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速