Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(iOS): scroll edge appearance #54

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/docs/docs/guides/usage-with-react-navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ Whether to show labels in tabs. Defaults to true.

Whether to disable page animations between tabs. (iOS only)

#### `scrollEdgeAppearance`

Describes the appearance attributes for the tabBar to use when an observable scroll view is scrolled to the bottom. (iOS only)
dylancom marked this conversation as resolved.
Show resolved Hide resolved

Available options:
- `default` - uses default background and shadow values.
- `transparent` - uses transparent background and no shadow.
- `opaque` - uses set of opaque colors that are appropriate for the current theme

okwasniewski marked this conversation as resolved.
Show resolved Hide resolved
Note: It's recommended to use `transparent` or `opaque` without lazy loading as the tab bar background flashes when a view is rendered lazily.
#### `sidebarAdaptable`

A tab bar style that adapts to each platform. (Apple platforms only)
Expand Down
8 changes: 8 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
return <FourTabs disablePageAnimations />;
};

const FourTabsTransparentScrollEdgeAppearance = () => {
return <FourTabs scrollEdgeAppearance="transparent" />;
};

const examples = [
{ component: ThreeTabs, name: 'Three Tabs' },
{ component: FourTabs, name: 'Four Tabs' },
Expand All @@ -42,6 +46,10 @@
screenOptions: { headerShown: false },
},
{ component: FourTabsNoAnimations, name: 'Four Tabs - no animations' },
{
component: FourTabsTransparentScrollEdgeAppearance,
name: 'Four Tabs - Transparent scroll edge appearance',
},
{ component: NativeBottomTabs, name: 'Native Bottom Tabs' },
{ component: JSBottomTabs, name: 'JS Bottom Tabs' },
{
Expand Down Expand Up @@ -88,7 +96,7 @@
name="BottomTabs Example"
component={App}
options={{
headerRight: () => (

Check warning on line 99 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Do not define components during render. React will see a new component type on every render and destroy the entire subtree’s DOM nodes and state (https://reactjs.org/docs/reconciliation.html#elements-of-different-types). Instead, move this component definition out of the parent component “Navigation” and pass data as props. If you want to allow component creation in props, set allowAsProps option to true
<Button
onPress={() =>
Alert.alert(
Expand Down
3 changes: 3 additions & 0 deletions example/src/Examples/FourTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import { Chat } from '../Screens/Chat';
interface Props {
ignoresTopSafeArea?: boolean;
disablePageAnimations?: boolean;
scrollEdgeAppearance?: 'default' | 'opaque' | 'transparent';
}

export default function FourTabs({
ignoresTopSafeArea = false,
disablePageAnimations = false,
scrollEdgeAppearance = 'default',
}: Props) {
const [index, setIndex] = useState(0);
const [routes] = useState([
Expand Down Expand Up @@ -53,6 +55,7 @@ export default function FourTabs({
ignoresTopSafeArea={ignoresTopSafeArea}
sidebarAdaptable
disablePageAnimations={disablePageAnimations}
scrollEdgeAppearance={scrollEdgeAppearance}
navigationState={{ index, routes }}
onIndexChange={setIndex}
renderScene={renderScene}
Expand Down
1 change: 1 addition & 0 deletions ios/RCTTabViewViewManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ - (UIView *)view
RCT_EXPORT_VIEW_PROPERTY(labeled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(ignoresTopSafeArea, BOOL)
RCT_EXPORT_VIEW_PROPERTY(disablePageAnimations, BOOL)
RCT_EXPORT_VIEW_PROPERTY(scrollEdgeAppearance, NSString)

@end
22 changes: 18 additions & 4 deletions ios/TabViewImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class TabViewProps: ObservableObject {
@Published var labeled: Bool?
@Published var ignoresTopSafeArea: Bool?
@Published var disablePageAnimations: Bool = false
@Published var scrollEdgeAppearance: String?
}

/**
Expand Down Expand Up @@ -70,16 +71,29 @@ struct TabViewImpl: View {
}
onSelect(newValue)
}
.onAppear {
.onChange(of: props.scrollEdgeAppearance) { newValue in
if #available(iOS 15.0, *) {
// This causes issues with lazy loading making the TabView background blink.
let appearance = UITabBarAppearance()
UITabBar.appearance().scrollEdgeAppearance = appearance
UITabBar.appearance().scrollEdgeAppearance = configureAppearance(for: newValue ?? "")
}
}
}
}

private func configureAppearance(for appearanceType: String) -> UITabBarAppearance {
let appearance = UITabBarAppearance()

switch appearanceType {
case "opaque":
appearance.configureWithOpaqueBackground()
case "transparent":
appearance.configureWithTransparentBackground()
default:
appearance.configureWithDefaultBackground()
}

return appearance
}

struct TabItem: View {
var title: String?
var icon: UIImage?
Expand Down
6 changes: 6 additions & 0 deletions ios/TabViewProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ struct TabData: Codable {
}
}

@objc var scrollEdgeAppearance: NSString? {
didSet {
props.scrollEdgeAppearance = scrollEdgeAppearance as? String
}
}

@objc var items: NSArray? {
didSet {
props.items = parseTabData(from: items)
Expand Down
4 changes: 4 additions & 0 deletions src/TabView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ interface Props<Route extends BaseRoute> {
* Whether to disable page animations between tabs. (iOS only)
*/
disablePageAnimations?: boolean;
/**
* Describes the appearance attributes for the tabBar to use when an observable scroll view is scrolled to the bottom. (iOS only)
*/
scrollEdgeAppearance?: 'default' | 'opaque' | 'transparent';
/**
* State for the tab view.
*
Expand Down
1 change: 1 addition & 0 deletions src/TabViewNativeComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface TabViewProps extends ViewProps {
icons?: ReadonlyArray<ImageSource>;
labeled?: boolean;
sidebarAdaptable?: boolean;
scrollEdgeAppearance?: string;
}

export default codegenNativeComponent<TabViewProps>('RCTTabView');
Loading