Skip to content

Commit

Permalink
add Skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
youlookwhat committed Mar 9, 2020
1 parent b6fd6e5 commit b367087
Show file tree
Hide file tree
Showing 15 changed files with 1,045 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package me.jingbin.library.skeleton;


import android.support.annotation.ArrayRes;
import android.support.annotation.ColorRes;
import android.support.annotation.IntRange;
import android.support.annotation.LayoutRes;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;

import me.jingbin.library.ByRecyclerView;
import me.jingbin.library.R;


/**
* @author jingbin
* item 骨架图显示
*/
public class ByRVItemSkeletonScreen implements SkeletonScreen {

private final RecyclerView mRecyclerView;
private final RecyclerView.Adapter mActualAdapter;
private final SkeletonAdapter mSkeletonAdapter;
private final boolean mRecyclerViewFrozen;
private boolean isShow = false;
private boolean loadMoreEnabled = false;
private boolean refreshEnabled = false;

private ByRVItemSkeletonScreen(Builder builder) {
mRecyclerView = builder.mRecyclerView;
mActualAdapter = builder.mActualAdapter;
mSkeletonAdapter = new SkeletonAdapter();
mSkeletonAdapter.setItemCount(builder.mItemCount);
mSkeletonAdapter.setLayoutReference(builder.mItemResID);
mSkeletonAdapter.setArrayOfLayoutReferences(builder.mItemsResIDArray);
mSkeletonAdapter.shimmer(builder.mShimmer);
mSkeletonAdapter.setShimmerColor(builder.mShimmerColor);
mSkeletonAdapter.setShimmerAngle(builder.mShimmerAngle);
mSkeletonAdapter.setShimmerDuration(builder.mShimmerDuration);
mRecyclerViewFrozen = builder.mFrozen;
}

/**
* 只能显示一次
*/
@Override
public void show() {
mRecyclerView.setAdapter(mSkeletonAdapter);
if (!mRecyclerView.isComputingLayout() && mRecyclerViewFrozen) {
mRecyclerView.setLayoutFrozen(true);
}
if (!mRecyclerViewFrozen && mRecyclerView instanceof ByRecyclerView) {
ByRecyclerView byRecyclerView = (ByRecyclerView) this.mRecyclerView;
loadMoreEnabled = byRecyclerView.isLoadMoreEnabled();
refreshEnabled = byRecyclerView.isRefreshEnabled();
byRecyclerView.setLoadMoreEnabled(false);
byRecyclerView.setRefreshEnabled(false);
}
isShow = true;
}

/**
* 只能显示一次
*/
@Override
public void hide() {
if (isShow) {
mRecyclerView.setAdapter(mActualAdapter);
if (!mRecyclerViewFrozen && mRecyclerView instanceof ByRecyclerView) {
ByRecyclerView byRecyclerView = (ByRecyclerView) this.mRecyclerView;
byRecyclerView.setRefreshEnabled(refreshEnabled);
byRecyclerView.setLoadMoreEnabled(loadMoreEnabled);
}
isShow = false;
}
}

public static class Builder {
private RecyclerView.Adapter mActualAdapter;
private final RecyclerView mRecyclerView;
private boolean mShimmer = true;
private int mItemCount = 10;
private int mItemResID = R.layout.layout_by_default_item_skeleton;
private int[] mItemsResIDArray;
private int mShimmerColor;
private int mShimmerDuration = 1000;
private int mShimmerAngle = 20;
private boolean mFrozen = true;

public Builder(RecyclerView recyclerView) {
this.mRecyclerView = recyclerView;
this.mShimmerColor = ContextCompat.getColor(recyclerView.getContext(), R.color.by_skeleton_shimmer_color);
}

/**
* @param adapter the target recyclerView actual adapter
*/
public Builder adapter(RecyclerView.Adapter adapter) {
this.mActualAdapter = adapter;
return this;
}

/**
* @param itemCount the child item count in recyclerView
*/
public Builder count(int itemCount) {
this.mItemCount = itemCount;
return this;
}

/**
* @param shimmer whether show shimmer animation
*/
public Builder shimmer(boolean shimmer) {
this.mShimmer = shimmer;
return this;
}

/**
* the duration of the animation , the time it will take for the highlight to move from one end of the layout
* to the other.
*
* @param shimmerDuration Duration of the shimmer animation, in milliseconds
*/
public Builder duration(int shimmerDuration) {
this.mShimmerDuration = shimmerDuration;
return this;
}

/**
* @param shimmerColor the shimmer color
*/
public Builder color(@ColorRes int shimmerColor) {
this.mShimmerColor = ContextCompat.getColor(mRecyclerView.getContext(), shimmerColor);
return this;
}

/**
* @param shimmerAngle the angle of the shimmer effect in clockwise direction in degrees.
*/
public Builder angle(@IntRange(from = 0, to = 30) int shimmerAngle) {
this.mShimmerAngle = shimmerAngle;
return this;
}

/**
* @param skeletonLayoutResID the loading skeleton layoutResID
*/
public Builder load(@LayoutRes int skeletonLayoutResID) {
this.mItemResID = skeletonLayoutResID;
return this;
}

/**
* @param skeletonLayoutResIDs the loading array of skeleton layoutResID
*/
public Builder loadArrayOfLayouts(@ArrayRes int[] skeletonLayoutResIDs) {
this.mItemsResIDArray = skeletonLayoutResIDs;
return this;
}

/**
* @param frozen whether frozen recyclerView during skeleton showing
* @return
*/
public Builder frozen(boolean frozen) {
this.mFrozen = frozen;
return this;
}

public ByRVItemSkeletonScreen show() {
ByRVItemSkeletonScreen recyclerViewSkeleton = new ByRVItemSkeletonScreen(this);
recyclerViewSkeleton.show();
return recyclerViewSkeleton;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package me.jingbin.library.skeleton;


import android.support.v7.widget.RecyclerView;

import me.jingbin.library.ByRecyclerView;

/**
* Created by jingbin on 2020-03-06.
* 骨架图处理,在设置完 ByRV 的一切配置后执行
*/
public class BySkeleton {

/**
* 设置item骨架图:通过额外setAdapter实现 【在之前 不能 setAdapter()】
* 配置方法:
* adapter 必须!
* load item骨架图 默认 layout_by_default_item_skeleton
* shimmer 是否有微光动画 默认 true
* angle 微光角度 默认 20
* frozen 是否不可滑动 默认 true不可滑动
* color 微光的颜色 默认 R.color.by_skeleton_shimmer_color
* duration 微光一次显示时间 默认 1000
* count item个数 默认 10
*/
public static ByRVItemSkeletonScreen.Builder bindItem(RecyclerView recyclerView) {
return new ByRVItemSkeletonScreen.Builder(recyclerView);
}

/**
* 设置view骨架图:通过setStateView实现 【在之前 需要 setAdapter()】
* 配置方法:
* load 必须!view骨架图
* shimmer 是否有微光动画 默认 true
* angle 微光角度 默认 20
* color 微光的颜色 默认 R.color.by_skeleton_shimmer_color
* duration 微光一次显示时间 默认 1000
*/
public static ByStateViewSkeletonScreen.Builder bindView(ByRecyclerView recyclerView) {
return new ByStateViewSkeletonScreen.Builder(recyclerView);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package me.jingbin.library.skeleton;

import android.support.annotation.ColorRes;
import android.support.annotation.IntRange;
import android.support.annotation.LayoutRes;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import me.jingbin.library.ByRecyclerView;
import me.jingbin.library.R;

/**
* Created by jingbin on 2020/03/07.
* view 骨架图显示,通过StateView处理
*/
public class ByStateViewSkeletonScreen implements SkeletonScreen {

private static final String TAG = ByStateViewSkeletonScreen.class.getName();
private final ByRecyclerView mByRecyclerView;
private final int mSkeletonResID;
private final int mShimmerColor;
private final boolean mShimmer;
private final int mShimmerDuration;
private final int mShimmerAngle;
private boolean loadMoreEnabled;
private boolean refreshEnabled;
private boolean isShow = false;

private ByStateViewSkeletonScreen(Builder builder) {
mByRecyclerView = builder.mByRecyclerView;
mSkeletonResID = builder.mSkeletonLayoutResID;
mShimmer = builder.mShimmer;
mShimmerDuration = builder.mShimmerDuration;
mShimmerAngle = builder.mShimmerAngle;
mShimmerColor = builder.mShimmerColor;
}

private ShimmerLayout generateShimmerContainerLayout(ViewGroup parentView) {
final ShimmerLayout shimmerLayout = (ShimmerLayout) LayoutInflater.from(mByRecyclerView.getContext()).inflate(R.layout.layout_by_skeleton_shimmer, parentView, false);
shimmerLayout.setShimmerColor(mShimmerColor);
shimmerLayout.setShimmerAngle(mShimmerAngle);
shimmerLayout.setShimmerAnimationDuration(mShimmerDuration);
View innerView = LayoutInflater.from(mByRecyclerView.getContext()).inflate(mSkeletonResID, shimmerLayout, false);
ViewGroup.LayoutParams lp = innerView.getLayoutParams();
if (lp != null) {
shimmerLayout.setLayoutParams(lp);
}
shimmerLayout.addView(innerView);
shimmerLayout.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
shimmerLayout.startShimmerAnimation();
}

@Override
public void onViewDetachedFromWindow(View v) {
shimmerLayout.stopShimmerAnimation();
}
});
shimmerLayout.startShimmerAnimation();
return shimmerLayout;
}

private View generateSkeletonLoadingView() {
ViewParent viewParent = mByRecyclerView.getParent();
if (viewParent == null) {
Log.e(TAG, "the source view have not attach to any view");
return null;
}
ViewGroup parentView = (ViewGroup) viewParent;
if (mShimmer) {
return generateShimmerContainerLayout(parentView);
}
return LayoutInflater.from(mByRecyclerView.getContext()).inflate(mSkeletonResID, parentView, false);
}

@Override
public void show() {
loadMoreEnabled = mByRecyclerView.isLoadMoreEnabled();
refreshEnabled = mByRecyclerView.isRefreshEnabled();

mByRecyclerView.setRefreshEnabled(false);
mByRecyclerView.setLoadMoreEnabled(false);
mByRecyclerView.setStateView(generateSkeletonLoadingView());
isShow = true;
}

@Override
public void hide() {
if (isShow) {
mByRecyclerView.setStateViewEnabled(false);
mByRecyclerView.setLoadMoreEnabled(loadMoreEnabled);
mByRecyclerView.setRefreshEnabled(refreshEnabled);
isShow = false;
}
}


public static class Builder {
private final ByRecyclerView mByRecyclerView;
private int mSkeletonLayoutResID;
private boolean mShimmer = true;
private int mShimmerColor;
private int mShimmerDuration = 1000;
private int mShimmerAngle = 20;

public Builder(ByRecyclerView byRecyclerView) {
this.mByRecyclerView = byRecyclerView;
this.mShimmerColor = ContextCompat.getColor(mByRecyclerView.getContext(), R.color.by_skeleton_shimmer_color);
}

/**
* @param skeletonLayoutResID the loading skeleton layoutResID
*/
public Builder load(@LayoutRes int skeletonLayoutResID) {
this.mSkeletonLayoutResID = skeletonLayoutResID;
return this;
}

/**
* @param shimmerColor the shimmer color
*/
public Builder color(@ColorRes int shimmerColor) {
this.mShimmerColor = ContextCompat.getColor(mByRecyclerView.getContext(), shimmerColor);
return this;
}

/**
* @param shimmer whether show shimmer animation
*/
public Builder shimmer(boolean shimmer) {
this.mShimmer = shimmer;
return this;
}

/**
* the duration of the animation , the time it will take for the highlight to move from one end of the layout
* to the other.
*
* @param shimmerDuration Duration of the shimmer animation, in milliseconds
*/
public Builder duration(int shimmerDuration) {
this.mShimmerDuration = shimmerDuration;
return this;
}

/**
* @param shimmerAngle the angle of the shimmer effect in clockwise direction in degrees.
*/
public Builder angle(@IntRange(from = 0, to = 30) int shimmerAngle) {
this.mShimmerAngle = shimmerAngle;
return this;
}

public ByStateViewSkeletonScreen show() {
ByStateViewSkeletonScreen skeletonScreen = new ByStateViewSkeletonScreen(this);
skeletonScreen.show();
return skeletonScreen;
}

}
}
Loading

0 comments on commit b367087

Please sign in to comment.