Skip to main content
Version: Next

ShimmerFlexLayout

API Reference: UI.ShimmerFlexLayout

ShimmerFlexLayout helps load a user interface gradually, a little at a time. While doing that, the labels and pictures have some gray colored placeholders on them with some moving gradient animation. Shimmer effect was created by Facebook to indicate a loading status, so instead of using ProgressBar or usual loader.

Shimmering On Android

Android includes build method which build the shimmer FlexLayout with given enum.

note

The components in the example are added from the code for better showcase purposes. To learn more about the subject you can refer to:

Adding Component From Code

As a best practice, Smartface recommends using the WYSIWYG editor in order to add components and styles to your page or library. To learn how to use UI Editor better, please refer to this documentation

UI Editor Basics
import PageSampleDesign from "generated/pages/pageSample";
import { Route, Router } from "@smartface/router";
import { styleableComponentMixin, styleableContainerComponentMixin } from '@smartface/styling-context';
import Button from "@smartface/native/ui/button";
import ShimmerFlexLayout from "@smartface/native/ui/shimmerflexlayout";
import ImageView from "@smartface/native/ui/imageview";
import Application from "@smartface/native/application";
import FlexLayout from "@smartface/native/ui/flexlayout";
import { themeService } from "theme";

class StyleableImageView extends styleableComponentMixin(ImageView) {}
class StyleableFlexLayout extends styleableContainerComponentMixin(FlexLayout) {}
class StyleableShimmerFlexLayout extends styleableComponentMixin(ShimmerFlexLayout) {}

//You should create new Page from UI-Editor and extend with it.
export default class Sample extends PageSampleDesign {
myShimmerFlexLayout: StyleableShimmerFlexLayout;
imageViews: ImageView[] = new Array<ImageView>();
flex: StyleableFlexLayout;

constructor(private router?: Router, private route?: Route) {
super({});
}


// The page design has been made from the code for better
// showcase purposes. As a best practice, remove this and
// use WYSIWYG editor to style your pages.
centerizeTheChildrenLayout() {
this.dispatch({
type: "updateUserStyle",
userStyle: {
flexProps: {
flexDirection: 'ROW',
justifyContent: 'CENTER',
alignItems: 'CENTER'
}
}
})
}

onShow() {
super.onShow();
const { headerBar } = this;
Application.statusBar.visible = false;
headerBar.visible = false;

setTimeout(() => {
this.myShimmerFlexLayout.stopShimmering();

this.myShimmerFlexLayout.baseAlpha = 1;
this.myShimmerFlexLayout.android.build(
ShimmerFlexLayout.Android.Shimmer.AlphaHighlight
);

for (let index = 0; index < this.imageViews.length; index++) {
this.imageViews[index].loadFromUrl({
url: "https://picsum.photos/200/300/?image=10" + index,
});
}
}, 4000);
}

onLoad() {
super.onLoad();
this.centerizeTheChildrenLayout();

this.flex = new StyleableFlexLayout();
themeService.addGlobalComponent(this.flex, "flex");

this.flex.dispatch({
type: "updateUserStyle",
userStyle: {
width: 350,
height: 750,
marginLeft: 20,
flexProps: {
positionType: "ABSOLUTE",
flexDirection: "ROW",
flexWrap: "WRAP",
alignContent: "AUTO",
},
},
});

for (let index = 1; index <= 6; index++) {
let imageViewName = "img" + index;
this[imageViewName] = new StyleableImageView();

this.flex.addChild(this[imageViewName], imageViewName, ".sf-imageView", {
height: 150,
width: 150,
marginLeft: 20,
marginBottom: 20,
marginTop: 10,
backgroundColor: "#a1a1a1",
imageFillType: "ASPECTFILL",
});
this.imageViews.push(this[imageViewName]);
}

this.myShimmerFlexLayout = new StyleableShimmerFlexLayout();

this.addChild(
this.myShimmerFlexLayout,
"myShimmerFlexLayout",
".sf-shimmerFlexLayout",
{
height: 500,
width: 400,
baseAlpha: 0.5,
pauseDuration: 500,
android: {
highlightAlpha: 1,
},
ios: {
animationAlpha: 0.2,
},
}
);

this.myShimmerFlexLayout.android.build(
ShimmerFlexLayout.Android.Shimmer.AlphaHighlight
);
this.myShimmerFlexLayout.contentLayout = this.flex;

this.myShimmerFlexLayout.startShimmering();

this.dispatch({
type: "updateUserStyle",
userStyle: {
flexProps: {
paddingTop: 0,
paddingLeft: 0,
paddingBottom: 0,
paddingRight: 0,
},
},
});
}
}
Reconstructing Components

After stopping shimmering effect; baseAlpha value must be set again and Android only builder function must be triggered.

Adding ShimmerFlexLayout Using UI Editor

Shimmer FlexLayouts can be created by using UI Editor all the way. When created it starts to shimmer from the very beginning, stopping and loading views need managed programmatically.

ShimmerFlexLayout properties can be added on UI Editor.

Simple example of ShimmerFlexLayout with custom component


import ShimmerGridviewExampleDesign from 'generated/pages/shimmerGridviewExample';
import { Route, Router } from '@smartface/router';
import { withDismissAndBackButton } from '@smartface/mixins';
import SimpleGridviewItem from 'components/Simple_gridviewItem';
type DatasetType = { title: string; subTitle: string; image: string; isLoaded: boolean };
export default class ShimmerGridviewExample extends withDismissAndBackButton(ShimmerGridviewExampleDesign) {
private disposeables: (() => void)[] = [];
myDataSet: DatasetType[] = Array.from({ length: 10 }).map((_, index: number) => ({
title: ``,
subTitle: ``,
image: '',
isLoaded: false
}));
constructor(private router?: Router, private route?: Route) {
super({});
}
initGridView() {
this.gridViewMain.onItemBind = (gridViewItem: SimpleGridviewItem, index) => {
const { title, subTitle, image, isLoaded } = this.myDataSet[index];
gridViewItem.gridTitle = title;
gridViewItem.gridSubTitle = subTitle;
gridViewItem.gridImage = image;
isLoaded ? gridViewItem.stopShimmering() : gridViewItem.startShimmering();
};
}
refreshGridView() {
this.gridViewMain.itemCount = this.myDataSet.length;
this.gridViewMain.refreshData();
}

initData() {
this.myDataSet = this.myDataSet.map((_, index: number) => ({
title: `Smartface Title ${index}`,
subTitle: `Smartface subtitle ${index}`,
image: 'images://swiper_image_1.png',
isLoaded: true
}));
}
/**
* @event onShow
* This event is called when a page appears on the screen (everytime).
*/
onShow() {
super.onShow();
this.refreshGridView();
setTimeout(() => {
this.initData();
this.refreshGridView();
}, 3000);
}
/**
* @event onLoad
* This event is called once when page is created.
*/
onLoad() {
super.onLoad();
this.headerBar.leftItemEnabled = false;
this.initGridView();
}
onHide(): void {
this.dispose();
}
dispose(): void {
this.disposeables.forEach((item) => item());
}
}