rotation issues (#13)

* animate indicator bar
fix rotation issue

* requested changes
This commit is contained in:
cecipirotto 2021-07-23 16:23:36 -03:00 committed by GitHub
parent 16ee70ccc9
commit 80a2937f8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 26 additions and 12 deletions

View File

@ -38,7 +38,6 @@ private struct PagerSetAppearItem: ViewModifier {
func body(content: Content) -> some View { func body(content: Content) -> some View {
content content
.frame(width: pagerSettings.width, height: pagerSettings.height)
.overlay( .overlay(
GeometryReader { reader in GeometryReader { reader in
Color.clear Color.clear
@ -68,7 +67,6 @@ private struct PagerTabItem<NavTabView: View> : ViewModifier {
func body(content: Content) -> some View { func body(content: Content) -> some View {
PagerTabView(navTabView: navTabView) { PagerTabView(navTabView: navTabView) {
content content
.frame(width: pagerSettings.width, height: pagerSettings.height)
.overlay( .overlay(
GeometryReader { reader in GeometryReader { reader in
Color.clear Color.clear
@ -108,25 +106,26 @@ private struct NavBarModifier: ViewModifier {
func body(content: Content) -> some View { func body(content: Content) -> some View {
VStack(alignment: .leading, spacing: 0) { VStack(alignment: .leading, spacing: 0) {
LazyHStack(spacing: pagerSettings.tabItemSpacing) { HStack(spacing: pagerSettings.tabItemSpacing) {
if itemCount > 0 && pagerSettings.width > 0 { if itemCount > 0 && pagerSettings.width > 0 {
ForEach(0...itemCount-1, id: \.self) { idx in ForEach(0...itemCount-1, id: \.self) { idx in
NavBarItem(id: idx, selection: $indexSelected) NavBarItem(id: idx, selection: $indexSelected)
.frame(width: navBarItemWidth, height: pagerSettings.tabItemHeight, alignment: .center) .frame(height: pagerSettings.tabItemHeight, alignment: .center)
} }
} }
} }
.frame(width: pagerSettings.width, height: pagerSettings.tabItemHeight, alignment: .center) .frame(height: pagerSettings.tabItemHeight, alignment: .center)
HStack { HStack {
if let width = navBarItemWidth, width > 0, width <= pagerSettings.width { if let width = navBarItemWidth, width > 0, width <= pagerSettings.width {
let x = -self.pagerSettings.contentOffset / CGFloat(itemCount) + width / 2 let x = -self.pagerSettings.contentOffset / CGFloat(itemCount) + width / 2
Rectangle() Rectangle()
.fill(pagerSettings.indicatorBarColor) .fill(pagerSettings.indicatorBarColor)
.animation(.default)
.frame(width: width) .frame(width: width)
.position(x: x, y: 0) .position(x: x, y: 0)
} }
} }
.frame(width: pagerSettings.width, height: pagerSettings.indicatorBarHeight) .frame(height: pagerSettings.indicatorBarHeight)
content content
} }
} }
@ -195,7 +194,7 @@ public class PagerSettings: ObservableObject {
} }
/// ///
/// Public Source Cide /// Public Source Code
/// ///
@available(iOS 14.0, *) @available(iOS 14.0, *)
@ -212,7 +211,7 @@ public struct XLPagerView<Content> : View where Content : View {
self.pagerSettings.contentOffset = currentOffset self.pagerSettings.contentOffset = currentOffset
} }
} }
@State private var itemCount : Int = 0 @State private var itemCount : Int = 0
@GestureState private var translation: CGFloat = 0 @GestureState private var translation: CGFloat = 0
@ -229,17 +228,29 @@ public struct XLPagerView<Content> : View where Content : View {
GeometryReader { gproxy in GeometryReader { gproxy in
HStack(spacing: 0) { HStack(spacing: 0) {
content() content()
.frame(width: gproxy.size.width)
} }
.frame(width: pagerSettings.width, height: pagerSettings.height, alignment: .leading)
.offset(x: -CGFloat(self.currentIndex) * pagerSettings.width) .offset(x: -CGFloat(self.currentIndex) * pagerSettings.width)
.offset(x: self.translation) .offset(x: self.translation)
.animation(.interactiveSpring(response: 0.5, dampingFraction: 1.00, blendDuration: 0.25), value: currentIndex) .animation(.interactiveSpring(response: 0.5, dampingFraction: 1.00, blendDuration: 0.25), value: currentIndex)
.animation(.interactiveSpring(response: 0.5, dampingFraction: 1.00, blendDuration: 0.25), value: translation) .animation(.interactiveSpring(response: 0.5, dampingFraction: 1.00, blendDuration: 0.25), value: translation)
.gesture( .gesture(
DragGesture().updating(self.$translation) { value, state, _ in DragGesture().updating(self.$translation) { value, state, _ in
state = value.translation.width if (currentIndex == 0 && value.translation.width > 0) {
let valueWidth = value.translation.width
let normTrans = valueWidth / (gproxy.size.width + 50)
let logValue = log(1 + normTrans)
state = gproxy.size.width/1.5 * logValue
} else if (currentIndex == itemCount - 1 && value.translation.width < 0) {
let valueWidth = -value.translation.width
let normTrans = valueWidth / (gproxy.size.width + 50)
let logValue = log(1 + normTrans)
state = -gproxy.size.width / 1.5 * logValue
} else {
state = value.translation.width
}
}.onEnded { value in }.onEnded { value in
let offset = value.predictedEndTranslation.width / pagerSettings.width let offset = value.predictedEndTranslation.width / gproxy.size.width
let newPredictedIndex = (CGFloat(self.currentIndex) - offset).rounded() let newPredictedIndex = (CGFloat(self.currentIndex) - offset).rounded()
let newIndex = min(max(Int(newPredictedIndex), 0), self.itemCount - 1) let newIndex = min(max(Int(newPredictedIndex), 0), self.itemCount - 1)
if abs(self.currentIndex - newIndex) > 1 { if abs(self.currentIndex - newIndex) > 1 {
@ -252,7 +263,9 @@ public struct XLPagerView<Content> : View where Content : View {
} }
} }
) )
.clipped() .onChange(of: gproxy.frame(in: .local), perform: { geo in
pagerSettings.width = geo.width
})
.onChange(of: self.currentIndex) { [currentIndex] newIndex in .onChange(of: self.currentIndex) { [currentIndex] newIndex in
self.currentOffset = self.offsetForPageIndex(newIndex) self.currentOffset = self.offsetForPageIndex(newIndex)
if let callback = navContentViews.items.value[currentIndex]?.appearCallback { if let callback = navContentViews.items.value[currentIndex]?.appearCallback {
@ -289,6 +302,7 @@ public struct XLPagerView<Content> : View where Content : View {
tabViewDelegate.setSelectedState(state: .selected) tabViewDelegate.setSelectedState(state: .selected)
} }
} }
.clipped()
} }
private func offsetForPageIndex(_ index: Int) -> CGFloat { private func offsetForPageIndex(_ index: Int) -> CGFloat {