Android 提升用户体验之骨架屏

7,536 阅读3分钟

前几天公司app做优化,提出了不要菊花图,原因是用户进入界面的时候弹出对话框压迫感太强并且在ios端由于没有返回按钮要等请求完才能操作,很坑爹。恰巧那天又看到《玉刚说》的公众号推了一篇骨架屏的文章,看了一下并且自己尝试了一下其他的接入总结一下坑点。

关于这方面的第三方库

一个封装了Recycview的遮罩控件,使用起来比下面的要方便。

一个封装了遮罩层的库

一个使布局闪烁的库,很多第三方库都依赖于它


遮罩库

仅仅支持图片跟文本,设置值时会去除遮罩。具体实现可以看看源码,

遮罩控件,支持多种控件,但是需要嵌套多层会影响一点性能

实现方法

-c

如效果图,实现的思想有两种。一种是写多一个遮罩布局,请求成功后再替换。这个也是上面第三方库的实现方法另一种是遮罩控件嵌套在原布局里,显示成功后调用方法隐藏。无论那种方式最好叫设计师给好一个遮罩item的原型尺寸,否则遇到复杂布局时自己很难调节大小。

最简单的方法

只需要把RecyclerView换成ShimmerRecyclerView调用显示、隐藏方法即可。这种方法也需要写一个遮罩布局,否则是默认的。

  • 接入
repositories {
    jcenter()
    maven { url "https://jitpack.io" }
}

dependencies {
    implementation 'com.github.sharish:ShimmerRecyclerView:v1.3'
}
  • 使用
<com.cooltechworks.views.shimmer.ShimmerRecyclerView
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/shimmer_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:shimmer_demo_child_count="10"
        app:shimmer_demo_grid_child_count="2"
        app:shimmer_demo_layout="@layout/layout_demo_grid"
        app:shimmer_demo_layout_manager_type="grid"
        app:shimmer_demo_angle="20"
        />

调用对应的显示隐藏方法

shimmerRecycler.showShimmerAdapter();

shimmerRecycler.hideShimmerAdapter();

Skeleton+布局

这种方法比较自由,除了RecyclerView以外还能用在其他布局上

  • 接入
repositories {
    jcenter()
    maven { url "https://jitpack.io" }
}

dependencies {
    implementation 'com.github.sharish:ShimmerRecyclerView:v1.3'
}
  • 使用
    RecyclerView:
skeletonScreen = Skeleton.bind(recyclerView)
                              .adapter(adapter)
                              .load(R.layout.item_skeleton_news)
                              .show();

其他View:

skeletonScreen = Skeleton.bind(rootView)
                              .load(R.layout.layout_img_skeleton)
                              .show();

提供的方法

.shimmer(true)      // whether show shimmer animation.                      default is true
.count(10)          // the recycler view item count.                        default is 10
.color(color)       // the shimmer color.                                   default is #a2878787
.angle(20)          // the shimmer angle.                                   default is 20;
.duration(1000)     // the shimmer animation duration.                      default is 1000;
.frozen(false)      // whether frozen recyclerView during skeleton showing  default is true; 

消失时调用

skeletonScreen.hide()

遮罩控件

上面的方法都要写一个布局,如果不想写多一个布局的可以使用遮罩控件

  1. github.com/elye/loader…
    -c

在setText或者给src设值时自动去除遮罩。可以设置默认遮罩的百分比长度还可以设置带一点点的闪烁动画等等。但是只有文本跟图片控件可用,以及不能根据文本长度来设置遮罩,因为setText之后会自动消失,所以在某些比较复杂的布局里如果没有设计师提供尺寸图是做不出效果的。

  • 接入
dependencies {
    implementation 'com.elyeproj.libraries:loaderviewlibrary:1.5.0'
}
  • 使用
<com.elyeproj.loaderviewlibrary.LoaderImageView
     android:layout_width="100dp"
     android:layout_height="100dp" />
<com.elyeproj.loaderviewlibrary.LoaderTextView
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     app:width_weight="0.4" 
     app:height_weight="0.8"
     app:use_gradient="true"
      app:corners="16"
       app:custom_color="@android:color/holo_green_dark" />

如果需要重新加载

myLoaderTextView.resetLoader();

2.github.com/rasoulmiri/…

-c

除了上图的效果外还支持其他效果,并且支持任意布局,因为它的使用方法是在原有布局上包裹一层。这种方式的好处是,可以不用设计师出遮罩图,套一层布局在外面后设置包裹内容即可,只是会比较耗费一点渲染性能。

  • 接入
allprojects {
    repositories {
	    ...
	    maven { url 'https://jitpack.io' }
    }
}
dependencies {
      compile 'com.github.rasoulmiri:Skeleton:v1.0.9'
}
  • 使用
<io.rmiri.skeleton.SkeletonGroup
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

         <io.rmiri.skeleton.SkeletonView ...>
            <View ... />
        </io.rmiri.skeleton.SkeletonView>

        <io.rmiri.skeleton.SkeletonView ...>
            <View ... />
        </io.rmiri.skeleton.SkeletonView>

</io.rmiri.skeleton.SkeletonGroup>

支持动画监听

skeletonGroup.setSkeletonListener(new SkeletonGroup.SkeletonListener() {
      @Override
      public void onStartAnimation() {
	...
      }

      @Override
      public void onFinishAnimation() {
	...
      }
 });

建议阅读

骨架屏 (Skeleton Screen) 在 Android 中的应用


最开始坚持的地方,记录学习与生活的点点滴滴