Read the original article:Tabs index persistent storage problem
Context
When using the Tabs component, clicking on a tab in the navigation bar displays the corresponding TabContent page.
Description
It is required that the next time the user logs in, the app automatically opens the TabContent page that was last viewed before exiting.
Solution
- Step 1: Create a user preferences object. For detailed guidance on implementing user preferences, see: Persisting Data with User Preferences.
import { preferences } from '@kit.ArkData';
export class PreferencesUtil {
preference?: preferences.Preferences;
getIndex(context: Context) {
this.preference = preferences.getPreferencesSync(context, { name: 'TabsIndex' });
}
saveIndex(currentIndex: number) {
this.preference?.putSync('currentIndex', currentIndex);
this.preference?.flush();
}
getChangeIndex() {
let currentIndex: number = 0;
currentIndex = this.preference?.getSync('currentIndex', 0) as number;
return currentIndex;
}
}
let preferenceUtilsObject: PreferencesUtil = new PreferencesUtil();
export default preferenceUtilsObject;
- Step 2: Get the stored user preferences when the app starts.
import preferenceUtilsObject from '../pages/Preferences';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// ...
preferenceUtilsObject.getIndex(this.context);
}
// ...
}
- Step 3: Get the real-time index position of the clicked tab through the onChange method and store it. Get the index position of the last exit from the Tabs page before the page is displayed through the aboutToAppear method.
import preferenceUtilsObject from '../pages/Preferences';
@Entry
@Component
struct Demo {
@State
private currentIndex: number = 0
private controller: TabsController = new TabsController()
aboutToAppear(): void {
this.currentIndex = preferenceUtilsObject.getChangeIndex()
}
@Builder
tabBuilder(index: number, name: string) {
RelativeContainer() {
Text(name)
.fontColor(this.currentIndex === index ? '#007DFF' : '#182431')
.fontSize(16)
.fontWeight(this.currentIndex === index ? 500 : 400)
.height('auto')
.padding({
left: 8,
right: 8,
top: 6,
bottom: 6
})
.id('textTitle')
.alignRules({
middle: { anchor: '__container__', align: HorizontalAlign.Center },
center: { anchor: '__container__', align: VerticalAlign.Center }
})
Divider()
.strokeWidth(1)
.color('#C3C3C3')
.width(100)
.alignRules({ bottom: { anchor: '__container__', align: VerticalAlign.Bottom } })
Divider()
.strokeWidth(2)
.color('#007DFF')
.opacity(this.currentIndex === index ? 1 : 0)
.width(100)
.alignRules({ bottom: { anchor: '__container__', align: VerticalAlign.Bottom } })
}
.width(100)
.backgroundColor('#F0F1F3')
}
build() {
RelativeContainer() {
Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
TabContent() {
Text('Page 1')
}.tabBar(this.tabBuilder(0, 'Page one'))
.backgroundColor('#ff808188')
TabContent() {
Text('Page 2')
}
.tabBar(this.tabBuilder(1, 'Page two'))
.backgroundColor('#ff817001')
TabContent() {
Text('Page 3')
}
.tabBar(this.tabBuilder(2, 'Page 3'))
.backgroundColor('#ff007c6e')
}
.barMode(BarMode.Scrollable)
.backgroundColor('#fff3f3f3')
.onChange((index) => {
this.currentIndex = index
preferenceUtilsObject.saveIndex(this.currentIndex)
})
.animationDuration(400)
.scrollable(true)
.vertical(false)
.width('100%')
.fadingEdge(false)
}
}
}
When you kill your app and then come back, last selected tab is saved and app continues from there. The effect is as follows:
Key Takeaways
The Tabs component does not support custom components as children; it only allows TabContent as a child component, along with rendering control types such as if/else and ForEach. However, only TabContent is supported under if/else and ForEach—custom components are not supported in those cases either.
The TabsOptions type includes four elements, among which the index parameter allows you to specify the initially displayed tab by its index when creating the Tabs component. The default value is 0.
The Preferences module can provide key-value data handling interfaces, enabling querying, modifying, and persisting lightweight data.

Top comments (0)