https://twitter.com/checkyourvector/status/1225847305057820673?s=21
(twitterのリンクです。)
こちらの動画のような、ドラッグで動くスライダーがどのように実装されているか、心当たりがあれば教えてください。
写真アプリの、「編集」機能でも、似た様なスライダーがありますが、これに似ているもので、他のスライダーとも同期させる動きが実装したいです。
とてもかっこいいUIだと思ったので、是非真似したいと思い、質問させていただきました。
よろしくお願いたいします。
以下の様に、UIは作りました。
どれも
SwiftUI
1ScrollView(.horizontal) { 2///幅2 縦10のRectangle()を、ForEachで100個横に並べる。 3}
で作っております。
https://www.youtube.com/watch?v=I5XlYCAb9JM
//DragGesture()と、要素に対する.offsetの説明
こちらを参考にしようと考えています。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
なんだかんだで近いものが自力で作れました!
これ全部コピーして貼り付ければ遊べると思います。
せっかく作ったので遊んでください。
人に見せるために書いてなかったので、コメントとかつけ忘れました。
質問してくれたら答えます。
いろいろ試行錯誤して作ったので、使わない関数とか、もっと綺麗に書ける部分もあるかもしれません。見つかれば教えてください。
SwiftUI
1 2 3import SwiftUI 4 5struct CoffeeSliderView: View { 6 //@EnvironmentObject var value: Values 7 @State var coffee: CGFloat = 10 8 @State var coffeeWaterRatio: Int = 2 9 10 @State var oldStateCoffee: CGSize = CGSize(width: 30.0, height: 0.0) 11 @State var newStateCoffee: CGSize = CGSize(width: 30.0, height: 0.0) 12 // 30分の1: 1/30 13 @State var oldStateCoffeeWaterRatio: CGSize = CGSize(width: 5.0, height: 0.0) 14 @State var newStateCoffeeWaterRatio: CGSize = CGSize(width: 5.0, height: 0.0) 15 // 30分の1: 1/30 16 @State var oldStateWater: CGSize = CGSize(width: -0.0, height: 0.0) 17 @State var newStateWater: CGSize = CGSize(width: -0.0, height: 0.0) 18 19 var dragCoffee: some Gesture { 20 DragGesture() 21 .onChanged { value in 22 self.newStateCoffee.width = self.oldStateCoffee.width - (value.translation.width / 30) 23 self.newStateWater.width = self.newStateCoffee.width * self.newStateCoffeeWaterRatio.width 24 self.oldStateWater.width = self.newStateCoffee.width * self.newStateCoffeeWaterRatio.width 25 } 26 .onEnded { value in 27 self.oldStateCoffee = self.newStateCoffee 28 if self.newStateCoffee.width < 0 { 29 self.newStateCoffee = .zero 30 self.oldStateCoffee = .zero 31 self.newStateWater = .zero 32 } 33 34 } 35 } 36 37 var dragCoffeeWaterRatio: some Gesture { 38 DragGesture() 39 .onChanged { value in 40 self.newStateCoffeeWaterRatio.width = self.oldStateCoffeeWaterRatio.width - (value.translation.width / 30) 41 self.newStateWater.width = self.newStateCoffee.width * self.newStateCoffeeWaterRatio.width 42 self.oldStateWater.width = self.newStateCoffee.width * self.newStateCoffeeWaterRatio.width 43 } 44 .onEnded { value in 45 self.oldStateCoffeeWaterRatio = self.newStateCoffeeWaterRatio 46 if self.newStateCoffeeWaterRatio.width < 0 { 47 self.newStateCoffeeWaterRatio = CGSize(width: 1, height: 0) 48 self.oldStateCoffeeWaterRatio = CGSize(width: 1, height: 0) 49 self.newStateWater.width = self.newStateCoffee.width 50 } 51 } 52 } 53 54 var dragWater: some Gesture { 55 DragGesture() 56 .onChanged { value in 57 self.newStateWater.width = self.oldStateWater.width - (value.translation.width / 3) 58 self.newStateCoffee.width = self.newStateWater.width / self.newStateCoffeeWaterRatio.width 59 } 60 .onEnded { value in 61 self.oldStateWater = self.newStateWater 62 if self.newStateWater.width < 0 { 63 self.newStateCoffee.width = 1 64 self.oldStateCoffee.width = 1 65 self.newStateWater.width = self.newStateCoffeeWaterRatio.width 66 self.oldStateWater.width = self.newStateCoffeeWaterRatio.width 67 } 68 } 69 } 70 71 var body: some View { 72 VStack { 73 /// コーヒーの量: Amount of Coffee 74 HStack { 75 VStack(alignment: .leading) { 76 Text("Coffee") 77 .font(.largeTitle) 78 .bold() 79 Text("(round(self.newStateCoffee.width * 10)/10)g") 80 .bold() 81 } 82 Spacer() 83 }.padding(.horizontal) 84 ScrollView(.horizontal, showsIndicators: false) { 85 VStack { 86 GeometryReader { geometry -> AnyView in 87 //self.coffee = geometry.frame(in: .global).minX 88 return AnyView(EmptyView()) 89 } 90 .frame(height: 1) 91 HStack(spacing: 11) { 92 ForEach(0..<20) { _ in 93 Rectangle() 94 .frame(width: 2, height: 30) 95 Rectangle() 96 .frame(width: 2, height: 20) 97 Rectangle() 98 .frame(width: 2, height: 20) 99 Rectangle() 100 .frame(width: 2, height: 20) 101 Rectangle() 102 .frame(width: 2, height: 20) 103 } 104 } 105 } 106 .offset(x: -self.newStateCoffee.width) 107 .gesture(dragCoffee) 108 .animation(.spring()) 109 } 110 ///コーヒーと、水の割合: Ratio of Coffee and water 111 HStack { 112 VStack(alignment: .leading) { 113 Text("Ratio") 114 .font(.largeTitle) 115 .bold() 116 Text("1:(Int(self.newStateCoffeeWaterRatio.width))") 117 .bold() 118 } 119 Spacer() 120 }.padding(.horizontal) 121 ScrollView(.horizontal, showsIndicators: false) { 122 VStack { 123 GeometryReader { geometry -> AnyView in 124 125 return AnyView(EmptyView()) 126 } 127 .frame(height: 1) 128 HStack(spacing: 17) { 129 ForEach(0..<300) { _ in 130 Rectangle() 131 .frame(width: 2, height: 20) 132 } 133 } 134 } 135 .offset(x: -self.newStateCoffeeWaterRatio.width) 136 .gesture(dragCoffeeWaterRatio) 137 .animation(.spring()) 138 139 } 140 141 ///水の量: Amount of Water 142 HStack { 143 VStack(alignment: .leading) { 144 Text("Water") 145 .font(.largeTitle) 146 .bold() 147 Text("(Int(self.newStateWater.width))g") 148 .bold() 149 } 150 Spacer() 151 }.padding(.horizontal) 152 ScrollView(.horizontal, showsIndicators: false) { 153 VStack { 154 GeometryReader { geometry -> AnyView in 155 156 return AnyView(EmptyView()) 157 } 158 .frame(height: 1) 159 HStack { 160 ForEach(0..<200) { _ in 161 Rectangle() 162 .frame(width: 2, height: 30) 163 Rectangle() 164 .frame(width: 2, height: 20) 165 } 166 } 167 } 168 .offset(x: -self.newStateWater.width) 169 .gesture(dragWater) 170 .animation(.spring()) 171 } 172 } 173 } 174} 175 176struct CoffeeSliderView_Previews: PreviewProvider { 177 static var previews: some View { 178 return CoffeeSliderView() 179 .environmentObject(Values()) 180 } 181} 182
投稿2020/02/19 16:38
総合スコア60
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。