/*
* Copyright (c) 2024-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { SymbolGlyphModifier } from '@ohos.arkui.modifier';
import {
AccessibilitySelectedType,
Chip,
ChipSize,
ChipSuffixSymbolGlyphOptions,
ChipSymbolGlyphOptions,
CloseOptions,
PrefixIconOptions,
SuffixIconOptions
} from '@ohos.arkui.advanced.Chip';
import uiMaterial from '@ohos.arkui.uiMaterial';
import deviceInfo from '@ohos.deviceInfo';
import i18n from '@ohos.i18n';
interface ChipGroupTheme {
itemStyle: ChipGroupStyleTheme;
chipGroupSpace: ChipGroupSpaceOptions;
chipGroupPadding: ChipGroupPaddingOptions;
chipBackgroundSystemMaterial?: uiMaterial.Material;
chipSelectedBackgroundSystemMaterial?: uiMaterial.Material;
}
const noop = (selectedIndexes: Array<number>) => {
}
const colorStops: ([string, number])[] = [['rgba(0, 0, 0, 1)', 0], ['rgba(0, 0, 0, 0)', 1]]
const ENABLE_SYSTEM_MATERIAL_VERSION: number = 26;
const defaultTheme: ChipGroupTheme = {
itemStyle: {
size: ChipSize.NORMAL,
backgroundColor: $r('sys.color.ohos_id_color_button_normal'),
fontColor: $r('sys.color.ohos_id_color_text_primary'),
selectedFontColor: $r('sys.color.ohos_id_color_text_primary_contrary'),
selectedBackgroundColor: $r('sys.color.ohos_id_color_emphasize'),
fillColor: $r('sys.color.ohos_id_color_secondary'),
selectedFillColor: $r('sys.color.ohos_id_color_text_primary_contrary'),
},
chipGroupSpace: { itemSpace: 8, startSpace: 16, endSpace: 16 },
chipGroupPadding: { top: 14, bottom: 14 },
chipBackgroundSystemMaterial: deviceInfo.sdkApiVersion >= ENABLE_SYSTEM_MATERIAL_VERSION ?
new uiMaterial.ImmersiveMaterial({
style: uiMaterial.ImmersiveStyle.ULTRA_THIN
}) : undefined,
chipSelectedBackgroundSystemMaterial: deviceInfo.sdkApiVersion >= ENABLE_SYSTEM_MATERIAL_VERSION ?
new uiMaterial.ImmersiveMaterial({
style: uiMaterial.ImmersiveStyle.ULTRA_THIN,
materialColor: $r('sys.color.comp_background_emphasize')
}) : undefined,
}
const iconGroupSuffixTheme: IconGroupSuffixTheme = {
backgroundColor: $r('sys.color.ohos_id_color_button_normal'),
borderRadius: $r('sys.float.ohos_id_corner_radius_tips_instant_tip'),
smallIconSize: 16,
normalIconSize: 24,
smallBackgroundSize: 28,
normalBackgroundSize: 36,
marginLeft: 8,
marginRight: 16,
fillColor: $r('sys.color.ohos_id_color_primary'),
defaultEffect: -1,
iconBackgroundSystemMaterial: deviceInfo.sdkApiVersion >= ENABLE_SYSTEM_MATERIAL_VERSION ?
new uiMaterial.ImmersiveMaterial({
style: uiMaterial.ImmersiveStyle.ULTRA_THIN
}) : undefined
}
interface IconOptions {
src: ResourceStr;
size?: SizeOptions;
}
interface ChipGroupPaddingOptions {
top: Length;
bottom: Length;
}
interface ChipGroupStyleTheme {
size: ChipSize | SizeOptions;
backgroundColor: ResourceColor;
fontColor: ResourceColor;
selectedFontColor: ResourceColor;
selectedBackgroundColor: ResourceColor;
fillColor: ResourceColor;
selectedFillColor: ResourceColor;
}
interface LabelOptions {
text: string;
}
export interface SuffixImageIconOptions extends IconOptions {
action?: VoidCallback;
accessibilityText?: ResourceStr;
accessibilityDescription?: ResourceStr;
accessibilityLevel?: string;
}
export interface ChipGroupItemOptions {
prefixIcon?: IconOptions;
prefixSymbol?: ChipSymbolGlyphOptions;
label: LabelOptions;
suffixIcon?: IconOptions;
suffixImageIcon?: SuffixImageIconOptions;
suffixSymbol?: ChipSymbolGlyphOptions;
suffixSymbolOptions?: ChipSuffixSymbolGlyphOptions;
allowClose?: boolean;
closeOptions?: CloseOptions;
accessibilityDescription?: ResourceStr;
accessibilityLevel?: string;
}
export interface ChipItemStyle {
size?: ChipSize | SizeOptions;
backgroundColor?: ResourceColor;
fontColor?: ResourceColor;
selectedFontColor?: ResourceColor;
selectedBackgroundColor?: ResourceColor;
}
interface ChipGroupSpaceOptions {
itemSpace?: number | string;
startSpace?: Length;
endSpace?: Length;
}
export interface IconItemOptions {
icon: IconOptions;
action: Callback<void>;
accessibilityText?: ResourceStr;
accessibilityDescription?: ResourceStr;
accessibilityLevel?: string;
}
export interface SymbolItemOptions {
symbol: SymbolGlyphModifier;
action: VoidCallback;
accessibilityText?: ResourceStr;
accessibilityDescription?: ResourceStr;
accessibilityLevel?: string;
}
interface IconGroupSuffixTheme {
smallIconSize: number;
normalIconSize: number;
backgroundColor: ResourceColor;
smallBackgroundSize: number;
normalBackgroundSize: number;
borderRadius: Dimension;
marginLeft: number;
marginRight: number;
fillColor: ResourceColor;
defaultEffect: number;
iconBackgroundSystemMaterial?: uiMaterial.Material
}
function parseDimension<T>(
uiContext: UIContext,
value: Dimension | Length | undefined,
isValid: Callback<string, boolean>,
defaultValue: T
): T {
if (value === void (0) || value === null) {
return defaultValue;
}
const resourceManager = uiContext.getHostContext()?.resourceManager;
if (!resourceManager) {
return defaultValue;
}
if (typeof value === 'object') {
let temp: Resource = value as Resource;
if (temp.type === 10002 || temp.type === 10007) {
if (resourceManager && resourceManager.getNumber(temp.id) >= 0) {
return value as T;
}
} else if (temp.type === 10003) {
if (resourceManager && isValidDimensionString(resourceManager.getStringSync(temp.id))) {
return value as T;
}
}
} else if (typeof value === 'number') {
if (value >= 0) {
return value as T;
}
} else if (typeof value === 'string') {
if (isValid(value)) {
return value as T;
}
}
return defaultValue;
}
function isValidString(dimension: string, regex: RegExp): boolean {
const matches = dimension.match(regex);
if (!matches || matches.length < 3) {
return false;
}
const value = Number.parseFloat(matches[1]);
return value >= 0;
}
function isValidDimensionString(dimension: string): boolean {
return isValidString(dimension, new RegExp('(-?\\d+(?:\\.\\d+)?)_?(fp|vp|px|lpx|%)?$', 'i'));
}
function isValidDimensionNoPercentageString(dimension: string): boolean {
return isValidString(dimension, new RegExp('(-?\\d+(?:\\.\\d+)?)_?(fp|vp|px|lpx)?$', 'i'));
}
@Component
export struct IconGroupSuffix {
@Consume chipSize: ChipSize | SizeOptions = ChipSize.NORMAL;
@Prop items: Array<IconItemOptions | SymbolGlyphModifier | SymbolItemOptions> = [];
@Prop iconBackgroundSystemMaterial?: uiMaterial.Material;
symbolEffect: SymbolEffect = new SymbolEffect();
private getBackgroundSize(): number {
if (this.chipSize === ChipSize.SMALL) {
return iconGroupSuffixTheme.smallBackgroundSize;
} else {
return iconGroupSuffixTheme.normalBackgroundSize;
}
}
private getIconSize(val?: Length): Length {
if (val === undefined) {
return this.chipSize === ChipSize.SMALL ?
iconGroupSuffixTheme.smallIconSize :
iconGroupSuffixTheme.normalIconSize;
}
let value: Length;
if (this.chipSize === ChipSize.SMALL) {
value = parseDimension(this.getUIContext(), val, isValidDimensionString, iconGroupSuffixTheme.smallIconSize);
} else {
value = parseDimension(this.getUIContext(), val, isValidDimensionString, iconGroupSuffixTheme.normalIconSize);
}
return value;
}
@Builder
SymbolItemBuilder(item: SymbolItemOptions) {
SymbolGlyph()
.fontColor([iconGroupSuffixTheme.fillColor])
.fontSize(this.getIconSize())
.attributeModifier(item.symbol)
.focusable(true)
.effectStrategy(SymbolEffectStrategy.NONE)
.symbolEffect(this.symbolEffect, false)
.symbolEffect(this.symbolEffect, iconGroupSuffixTheme.defaultEffect)
}
@Builder
IconItemBuilder(item: IconItemOptions) {
Image(item.icon.src)
.fillColor(iconGroupSuffixTheme.fillColor)
.size({
width: this.getIconSize(item.icon.size?.width),
height: this.getIconSize(item.icon.size?.height)
})
.focusable(true)
}
@Builder
IconButtonsBuilder(material: uiMaterial.Material | undefined) {
Row({ space: 8 }) {
ForEach(this.items || [], (suffixItem: IconItemOptions | SymbolGlyphModifier | SymbolItemOptions) => {
Button() {
if (suffixItem instanceof SymbolGlyphModifier) {
SymbolGlyph()
.fontColor([iconGroupSuffixTheme.fillColor])
.fontSize(this.getIconSize())
.attributeModifier(suffixItem)
.focusable(true)
.effectStrategy(SymbolEffectStrategy.NONE)
.symbolEffect(this.symbolEffect, false)
.symbolEffect(this.symbolEffect, iconGroupSuffixTheme.defaultEffect)
} else if (this.isSymbolItem(suffixItem)) {
this.SymbolItemBuilder(suffixItem as SymbolItemOptions)
} else {
this.IconItemBuilder(suffixItem as IconItemOptions)
}
}
.size({
width: this.getBackgroundSize(),
height: this.getBackgroundSize()
})
.borderRadius(iconGroupSuffixTheme.borderRadius)
.backgroundColor(this.getBackgroundColor(material))
.systemMaterial(material)
.accessibilityText(this.getAccessibilityText(suffixItem))
.accessibilityDescription(this.getAccessibilityDescription(suffixItem))
.accessibilityLevel(this.getAccessibilityLevel(suffixItem))
.onClick(() => {
if (!(suffixItem instanceof SymbolGlyphModifier)) {
suffixItem.action();
}
})
})
}
}
private getBackgroundColor(material: uiMaterial.Material | undefined): ResourceColor | undefined {
if (!!material) {
return undefined;
}
return iconGroupSuffixTheme.backgroundColor;
}
build() {
if (deviceInfo.sdkApiVersion >= ENABLE_SYSTEM_MATERIAL_VERSION) {
if (enableEffectComponent(this.iconBackgroundSystemMaterial)) {
EffectComponent() {
this.IconButtonsBuilder(
createSubECMaterial(
withDefaultMaterial(this.iconBackgroundSystemMaterial, iconGroupSuffixTheme.iconBackgroundSystemMaterial)
)
)
}
.systemMaterial(
createECMaterial(
withDefaultMaterial(this.iconBackgroundSystemMaterial, iconGroupSuffixTheme.iconBackgroundSystemMaterial)
)
)
} else {
this.IconButtonsBuilder(
withDefaultMaterial(this.iconBackgroundSystemMaterial, iconGroupSuffixTheme.iconBackgroundSystemMaterial)
)
}
} else {
this.IconButtonsBuilder(undefined)
}
}
private isSymbolItem(item: IconItemOptions | SymbolItemOptions): boolean {
return typeof (item as SymbolItemOptions).symbol !== 'undefined';
}
private getAccessibilityLevel(item: IconItemOptions | SymbolGlyphModifier | SymbolItemOptions): string {
if (item instanceof SymbolGlyphModifier) {
return 'auto';
}
return item.accessibilityLevel ?? 'auto';
}
private getAccessibilityDescription(
item: IconItemOptions | SymbolGlyphModifier | SymbolItemOptions
): Resource | undefined {
if (item instanceof SymbolGlyphModifier || typeof item.accessibilityDescription === 'undefined') {
return undefined;
}
return item.accessibilityDescription as ESObject as Resource;
}
private getAccessibilityText(item: IconItemOptions | SymbolGlyphModifier | SymbolItemOptions): Resource | undefined {
if (item instanceof SymbolGlyphModifier || typeof item.accessibilityText === 'undefined') {
return undefined;
}
return item.accessibilityText as ESObject as Resource;
}
}
interface ChipItemsBuilderOptions {
backgroundSystemMaterial?: uiMaterial.Material;
activatedBackgroundSystemMaterial?: uiMaterial.Material;
}
@Component
export struct ChipGroup {
@Prop @Watch('onItemsChange') items: ChipGroupItemOptions[] = [];
@Prop @Watch('itemStyleOnChange') itemStyle: ChipItemStyle = defaultTheme.itemStyle;
@Provide chipSize: ChipSize | SizeOptions = defaultTheme.itemStyle.size;
@Provide inGroup: boolean = true;
@Prop selectedIndexes: Array<number> = [0];
@Prop @Watch('onMultipleChange') multiple: boolean = false;
@Prop chipGroupSpace: ChipGroupSpaceOptions = defaultTheme.chipGroupSpace;
@Prop backgroundSystemMaterial?: uiMaterial.Material = undefined;
@Prop selectedBackgroundSystemMaterial?: uiMaterial.Material = undefined;
@BuilderParam suffix?: Callback<void>;
public onChange: Callback<Array<number>> = noop;
private scroller: Scroller = new Scroller();
@State isReachEnd: boolean = this.scroller.isAtEnd();
@Prop chipGroupPadding: ChipGroupPaddingOptions = defaultTheme.chipGroupPadding;
@State isRefresh: boolean = true;
onItemsChange() {
this.isRefresh = !this.isRefresh;
}
onMultipleChange() {
this.selectedIndexes = this.getSelectedIndexes();
}
itemStyleOnChange() {
this.chipSize = this.getChipSize();
}
aboutToAppear() {
this.itemStyleOnChange();
if (this.getSelectedIndexes().length === 0) {
this.selectedIndexes = [0];
}
}
private getChipSize(): ChipSize | SizeOptions {
if (this.itemStyle && this.itemStyle.size) {
if (typeof this.itemStyle.size === 'object') {
if (!this.itemStyle.size.width || !this.itemStyle.size.height || !this.itemStyle.size) {
return defaultTheme.itemStyle.size;
}
}
return this.itemStyle.size;
}
return defaultTheme.itemStyle.size;
}
private getFontColor(): ResourceColor {
if (this.itemStyle && this.itemStyle.fontColor) {
if (typeof this.itemStyle.fontColor === 'object') {
let temp: Resource = this.itemStyle.fontColor as Resource;
if (temp == undefined || temp == null) {
return defaultTheme.itemStyle.fontColor;
}
if (temp.type === 10001) {
return this.itemStyle.fontColor;
}
return defaultTheme.itemStyle.fontColor;
}
return this.itemStyle.fontColor;
}
return defaultTheme.itemStyle.fontColor;
}
private getSelectedFontColor(): ResourceColor {
if (this.itemStyle && this.itemStyle.selectedFontColor) {
if (typeof this.itemStyle.selectedFontColor === 'object') {
let temp: Resource = this.itemStyle.selectedFontColor as Resource;
if (temp == undefined || temp == null) {
return defaultTheme.itemStyle.selectedFontColor;
}
if (temp.type === 10001) {
return this.itemStyle.selectedFontColor;
}
return defaultTheme.itemStyle.selectedFontColor;
}
return this.itemStyle.selectedFontColor;
}
return defaultTheme.itemStyle.selectedFontColor;
}
private getFillColor(): ResourceColor {
if (this.itemStyle && this.itemStyle.fontColor) {
return this.itemStyle.fontColor;
}
return defaultTheme.itemStyle.fillColor;
}
private getSelectedFillColor(): ResourceColor {
if (this.itemStyle && this.itemStyle.selectedFontColor) {
return this.itemStyle.selectedFontColor;
}
return defaultTheme.itemStyle.selectedFillColor;
}
private getBackgroundColor(): ResourceColor | undefined {
if (!!this.backgroundSystemMaterial) {
return undefined;
}
if (this.itemStyle && this.itemStyle.backgroundColor) {
if (typeof this.itemStyle.backgroundColor === 'object') {
let temp: Resource = this.itemStyle.backgroundColor as Resource;
if (temp == undefined || temp == null) {
return defaultTheme.itemStyle.backgroundColor;
}
if (temp.type === 10001) {
return this.itemStyle.backgroundColor;
}
return defaultTheme.itemStyle.backgroundColor;
}
return this.itemStyle.backgroundColor;
}
return defaultTheme.itemStyle.backgroundColor;
}
private getSelectedBackgroundColor(): ResourceColor | undefined {
if (!!this.selectedBackgroundSystemMaterial) {
return undefined;
}
if (this.itemStyle && this.itemStyle.selectedBackgroundColor) {
if (typeof this.itemStyle.selectedBackgroundColor === 'object') {
let temp: Resource = this.itemStyle.selectedBackgroundColor as Resource;
if (temp == undefined || temp == null) {
return defaultTheme.itemStyle.selectedBackgroundColor;
}
if (temp.type === 10001) {
return this.itemStyle.selectedBackgroundColor;
}
return defaultTheme.itemStyle.selectedBackgroundColor;
}
return this.itemStyle.selectedBackgroundColor;
}
return defaultTheme.itemStyle.selectedBackgroundColor;
}
private getSelectedIndexes(): Array<number> {
let temp: number[] = [];
temp = (this.selectedIndexes ?? [0]).filter(
(element, index, array) => {
return (
element >= 0 &&
element % 1 == 0 &&
element != null &&
element != undefined &&
array.indexOf(element) === index &&
element < (this.items || []).length);
});
return temp;
}
private isMultiple(): boolean {
return this.multiple ?? false;
}
private isRTL(): boolean {
return i18n.isRTL(i18n.System.getAppPreferredLanguage());
}
private getChipGroupItemSpace() {
if (this.chipGroupSpace == undefined) {
return defaultTheme.chipGroupSpace.itemSpace
}
return parseDimension(
this.getUIContext(),
this.chipGroupSpace.itemSpace,
isValidDimensionNoPercentageString,
defaultTheme.chipGroupSpace.itemSpace
);
}
private getChipGroupStartSpace() {
if (this.chipGroupSpace == undefined) {
return defaultTheme.chipGroupSpace.startSpace
}
return parseDimension(
this.getUIContext(),
this.chipGroupSpace.startSpace,
isValidDimensionNoPercentageString,
defaultTheme.chipGroupSpace.startSpace
);
}
private getChipGroupEndSpace() {
if (this.chipGroupSpace == undefined) {
return defaultTheme.chipGroupSpace.endSpace
}
return parseDimension(
this.getUIContext(),
this.chipGroupSpace.endSpace,
isValidDimensionNoPercentageString,
defaultTheme.chipGroupSpace.endSpace
);
}
private getOnChange(): (selectedIndexes: Array<number>) => void {
return this.onChange ?? noop;
}
private isSelected(itemIndex: number): boolean {
if (!this.isMultiple()) {
return itemIndex == this.getSelectedIndexes()[0];
} else {
return this.getSelectedIndexes().some((element, index, array) => {
return (element == itemIndex);
})
}
}
private getPaddingTop() {
if (!this.chipGroupPadding || !this.chipGroupPadding.top) {
return defaultTheme.chipGroupPadding.top
}
return parseDimension(
this.getUIContext(),
this.chipGroupPadding.top,
isValidDimensionNoPercentageString,
defaultTheme.chipGroupPadding.top
);
}
private getPaddingBottom() {
if (!this.chipGroupPadding || !this.chipGroupPadding.bottom) {
return defaultTheme.chipGroupPadding.bottom
}
return parseDimension(
this.getUIContext(),
this.chipGroupPadding.bottom,
isValidDimensionNoPercentageString,
defaultTheme.chipGroupPadding.bottom
);
}
@Builder
ChipItemsBuilder(options: ChipItemsBuilderOptions) {
Row({ space: this.getChipGroupItemSpace() }) {
ForEach(this.items || [], (chipItem: ChipGroupItemOptions, index) => {
if (chipItem) {
Chip({
prefixIcon: this.getPrefixIcon(chipItem),
prefixSymbol: chipItem?.prefixSymbol,
label: {
text: chipItem?.label?.text ?? ' ',
fontColor: this.getFontColor(),
activatedFontColor: this.getSelectedFontColor(),
},
suffixIcon: this.getSuffixIcon(chipItem),
suffixSymbol: chipItem?.suffixSymbol,
suffixSymbolOptions: chipItem.suffixSymbolOptions,
allowClose: chipItem.allowClose ?? false,
closeOptions: chipItem.closeOptions,
enabled: true,
activated: this.isSelected(index),
backgroundColor: this.getBackgroundColor(),
backgroundSystemMaterial: options.backgroundSystemMaterial,
activatedBackgroundSystemMaterial: options.activatedBackgroundSystemMaterial,
size: this.getChipSize(),
activatedBackgroundColor: this.getSelectedBackgroundColor(),
accessibilitySelectedType:
this.multiple ? AccessibilitySelectedType.CHECKED : AccessibilitySelectedType.SELECTED,
accessibilityDescription: chipItem.accessibilityDescription,
accessibilityLevel: chipItem.accessibilityLevel,
onClicked: () => {
if (this.isSelected(index)) {
if (!(!this.isMultiple())) {
if (this.getSelectedIndexes().length > 1) {
this.selectedIndexes.splice(this.selectedIndexes.indexOf(index), 1);
}
}
} else {
if (!this.selectedIndexes || this.selectedIndexes.length === 0) {
this.selectedIndexes = this.getSelectedIndexes();
}
if (!this.isMultiple()) {
this.selectedIndexes = [];
}
this.selectedIndexes.push(index);
}
this.getOnChange()(this.getSelectedIndexes());
}
})
}
}, () => {
return JSON.stringify(this.isRefresh);
});
}
.padding({
left: this.getChipGroupStartSpace(),
right: this.getChipGroupEndSpace()
})
.constraintSize({ minWidth: '100%' })
}
build() {
Row() {
Stack() {
Scroll(this.scroller) {
if (deviceInfo.sdkApiVersion >= ENABLE_SYSTEM_MATERIAL_VERSION) {
if (enableEffectComponent(this.backgroundSystemMaterial)) {
EffectComponent() {
this.ChipItemsBuilder({
backgroundSystemMaterial: createSubECMaterial(this.getBackgroundSystemMaterial()),
activatedBackgroundSystemMaterial: this.getSelectedBackgroundSystemMaterial()
})
}
.systemMaterial(createECMaterial(this.getBackgroundSystemMaterial())
)
} else {
this.ChipItemsBuilder({
backgroundSystemMaterial: this.getBackgroundSystemMaterial(),
activatedBackgroundSystemMaterial: this.getSelectedBackgroundSystemMaterial()
})
}
} else {
this.ChipItemsBuilder({})
}
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.align(Alignment.Start)
.width('100%')
.clip(false)
.onScroll(() => {
this.isReachEnd = this.scroller.isAtEnd();
})
if (this.suffix && !this.isReachEnd) {
Stack()
.width(iconGroupSuffixTheme.normalBackgroundSize)
.height(LayoutPolicy.matchParent)
.linearGradient({ angle: this.isRTL() ? 270 : 90, colors: colorStops })
.blendMode(BlendMode.DST_IN, BlendApplyType.OFFSCREEN)
.hitTestBehavior(HitTestMode.None)
}
}
.padding({ top: this.getPaddingTop(), bottom: this.getPaddingBottom() })
.layoutWeight(1)
.blendMode(this.getOutsideBlendMode(), this.getOutsideBlendType())
.alignContent(Alignment.End)
if (this.suffix) {
Row() {
this.suffix();
}.padding({
left: iconGroupSuffixTheme.marginLeft,
right: iconGroupSuffixTheme.marginRight
})
}
}
.align(Alignment.End)
.width('100%')
}
private getSelectedBackgroundSystemMaterial(): uiMaterial.Material | undefined {
if (deviceInfo.sdkApiVersion < ENABLE_SYSTEM_MATERIAL_VERSION) {
return undefined;
}
return withDefaultMaterial(
this.selectedBackgroundSystemMaterial,
defaultTheme.chipSelectedBackgroundSystemMaterial
);
}
private getBackgroundSystemMaterial(): uiMaterial.Material | undefined {
if (deviceInfo.sdkApiVersion < ENABLE_SYSTEM_MATERIAL_VERSION) {
return undefined;
}
return withDefaultMaterial(this.backgroundSystemMaterial, defaultTheme.chipBackgroundSystemMaterial);
}
private getOutsideBlendType(): BlendApplyType | undefined {
if (!this.suffix && (!!this.getBackgroundSystemMaterial() || !!this.getSelectedBackgroundSystemMaterial())) {
return undefined;
}
return BlendApplyType.OFFSCREEN;
}
private getOutsideBlendMode(): BlendMode | undefined {
if (!this.suffix && (!!this.getBackgroundSystemMaterial() || !!this.getSelectedBackgroundSystemMaterial())) {
return undefined;
}
return BlendMode.SRC_OVER;
}
getPrefixIcon(chipItem: ChipGroupItemOptions): PrefixIconOptions {
return {
src: chipItem.prefixIcon?.src ?? '',
size: chipItem.prefixIcon?.size ?? undefined,
fillColor: this.getFillColor(),
activatedFillColor: this.getSelectedFillColor()
};
}
private getSuffixIcon(chipItem: ChipGroupItemOptions): SuffixIconOptions {
if (typeof chipItem.suffixImageIcon !== 'undefined') {
return {
src: chipItem.suffixImageIcon.src,
size: chipItem.suffixImageIcon.size,
fillColor: this.getFillColor(),
activatedFillColor: this.getSelectedFillColor(),
action: chipItem.suffixImageIcon.action,
accessibilityText: chipItem.suffixImageIcon.accessibilityText,
accessibilityDescription: chipItem.suffixImageIcon.accessibilityDescription,
accessibilityLevel: chipItem.suffixImageIcon.accessibilityLevel,
};
}
return {
src: chipItem.suffixIcon?.src ?? '',
size: chipItem.suffixIcon?.size ?? undefined,
fillColor: this.getFillColor(),
activatedFillColor: this.getSelectedFillColor()
};
}
}
function withDefaultMaterial(
material: uiMaterial.Material | undefined, defaultMaterial: uiMaterial.Material | undefined
): uiMaterial.Material | undefined {
const info = uiMaterial.getMaterialInfo();
if (info.state === uiMaterial.MaterialState.DISABLE) {
return undefined;
}
if (info.state === uiMaterial.MaterialState.ENABLE && !material) {
return defaultMaterial;
}
return material;
}
function enableEffectComponent(
material: uiMaterial.Material | undefined
): boolean {
if (material) {
return material instanceof uiMaterial.ImmersiveMaterial;
}
return false;
}
function createECMaterial(material: uiMaterial.Material | undefined): uiMaterial.Material | undefined {
if (!material) {
return undefined;
}
if (material instanceof uiMaterial.ImmersiveMaterial) {
return uiMaterial.convertToECMaterial(material);
}
return material;
}
function createSubECMaterial(material: uiMaterial.Material | undefined): uiMaterial.Material | undefined {
if (!material) {
return undefined;
}
if (material instanceof uiMaterial.ImmersiveMaterial) {
return uiMaterial.convertToECSubMaterial(material);
}
return material;
}
@Preview
@Component
struct ChipGroupExample {
@LocalBuilder
suffix() {
IconGroupSuffix({
items: [{
icon: { src: $r('sys.media.ohos_ic_public_add') },
action: () => {
this.getUIContext().getPromptAction().showToast({
message: '后缀图标被点击'
})
}
}]
})
}
build() {
ChipGroup({
items: [
{ label: { text: '选项A' } },
{ label: { text: '选项B' } },
{ label: { text: '选项C' } },
{ label: { text: '选项D' } },
{ label: { text: '选项E' } },
],
suffix: () => this.suffix()
})
}
}