自定义按钮样式 (SwiftUI) tvOS

Posted

技术标签:

【中文标题】自定义按钮样式 (SwiftUI) tvOS【英文标题】:Custom Button style (SwiftUI) tvOS 【发布时间】:2020-10-11 06:01:34 【问题描述】:

所以我有一个自定义按钮类(这样我就可以删除所有徽标背后的背景。)

但是现在当用户将鼠标悬停在按钮上时缩放不起作用/激活 - 这意味着他们不知道他们在哪个按钮上。

我想知道当遥控器在按钮上方或按钮上时,如何添加增加按钮大小(宽度和高度)的功能?


struct RedRoundButton: ButtonStyle 

    func makeBody(configuration: Configuration) -> some View 
        configuration.label
            .padding(0)
            .font(.title)
            .background( Circle()
                .fill(Color.red))
    


和按钮代码

 Button(action: 
                                                  //  Analytics.logEvent("Station_Change",parameters: [
                                                    //    "name": station.name
                                                    //])
                                                     AdStichrApi.station = station.name
                                                    MusicPlayer.shared.startBackgroundMusic(url:station.listenlive, type: "radio")
                                                   // self.showingDetail.toggle()
                                                   ) 
                                                    
                                                    KFImage(URL(string: station.imageurl)!)
                                                        .resizable()
                                                        .renderingMode(.original)
                                                        .frame(width:geo.size.width / 10, height:geo.size.width / 10)
                                                        .clipShape(Circle())
                                                    .sheet(isPresented: self.$showingDetail) 
                                                       // MediaPlayerView()
                                                            
                                                    
                                                
                                                   .buttonStyle(RedRoundButton())
                                                   .frame(width: geo.size.width / 10,height: geo.size.width / 10)
                                                   

我发现我可以用这个

.focusable(true)isFocused in
                                                        self.focused = true
                                                   
                                                   .scaleEffect(self.focused ? 1:0)

但它不会缩放按钮

完整代码

//
//  ContentView.swift
//  DRN1
//
//  Created by Russell Harrower on 10/10/20.
//

import SwiftUI
import AVKit
import struct Kingfisher.RoundCornerImageProcessor
import KingfisherSwiftUI


struct ContentView: View 
    @State var showingDetail = false
    @State var stations: [Station] = []
    @State var showDetail = String(false)
    @State var focused = false
    
    
    var body: some View 
        GeometryReader  geo in
            Group 
                
                if self.stations.isEmpty 
                Text("Loading")
                //this must be empty
                //.navigationBarHidden(true)
                      
                
                else
                
                    VStack(alignment: .leading)
                        Text("Our Stations")
                        .lineSpacing(30)
                        .padding(5)
                        .font(.system(size: 30, weight: .heavy, design: .default))
                        ScrollView(.horizontal, showsIndicators: false) 
                                            HStack(alignment: .bottom, spacing: 10) 
                                                ForEach(self.stations)  station in
                                                    //return
                                                   Button(action: 
                                                  //  Analytics.logEvent("Station_Change",parameters: [
                                                    //    "name": station.name
                                                    //])
                                                     AdStichrApi.station = station.name
                                                    MusicPlayer.shared.startBackgroundMusic(url:station.listenlive, type: "radio")
                                                   // self.showingDetail.toggle()
                                                   ) 
                                                    
                                                    KFImage(URL(string: station.imageurl)!)
                                                        .resizable()
                                                        .renderingMode(.original)
                                                        .frame(width:geo.size.width / 10, height:geo.size.width / 10)
                                                        .clipShape(Circle())
                                                    .sheet(isPresented: self.$showingDetail) 
                                                       // MediaPlayerView()
                                                            
                                                    
                                                
                                                   .buttonStyle(RedRoundButton())
                                                   .focusable(true)isFocused in
                                                        self.focused = true
                                                   
                                                   .scaleEffect(self.focused ? 1:0)
                                                   .frame(width: geo.size.width / 10,height: geo.size.width / 10)
                                                   
                                                   
                                                
                                            
                                                
                                            .frame(height: geo.size.width / 4)
                        .frame(height: geo.size.width / 4)
                                                    
                    
                
            
        
                          
                         
                         
            
                            
        .onAppear 
         //   self.navigationViewStyle(StackNavigationViewStyle())
            MusicPlayer.shared.startBackgroundMusic(url: "http://stream.radiomedia.com.au:8006/stream", type: "radio")
            //print(self.showingDetail)
            Api().getStations  (stations) in
                           self.stations = stations
            
        
                            
                       
        .onPlayPauseCommand(perform: 
            
            if(MusicPlayer.shared.player?.rate != 0)
            
                MusicPlayer.shared.player?.pause()
            
            else
                MusicPlayer.shared.player?.play()
            
        )
    
    
    




struct RedRoundButton: ButtonStyle 

   
  
    func makeBody(configuration: Configuration) -> some View 
        configuration.label
            .padding(0)
            .font(.title)
            .background(Circle()
            .fill(Color.red))
           
            
            
    



struct ContentView_Previews: PreviewProvider 
    static var previews: some View 
        ContentView()
    


【问题讨论】:

这是否回答了您的问题***.com/a/63172333/12299030? 【参考方案1】:

Apple 推荐的解决方案是使用新的CardButtonStyle 按钮样式,它移除了通常的填充但保留了 tvOS 悬停效果:

Button(action: , label: 
    Text("B")
        .padding()
        .background(Color.red)
        .clipShape(Circle())
)
.buttonStyle(CardButtonStyle())

但是,这仍然会应用一个圆形矩形按钮背景,这与您的圆形背景看起来不太好。

我建议您更新您的设计,以便您可以使用 CardButtonStyle。 Button 管理自己的焦点状态,因此您不能覆盖或连接任何东西。在 tvOS 上,你不能从头开始制作自己的按钮,因为没有 onTap/onClick 事件。您唯一的其他真正选择是在 UIKit 中构建一个自定义按钮,这样您就可以避免 SwiftUI 在 tvOS 上的限制。

【讨论】:

以上是关于自定义按钮样式 (SwiftUI) tvOS的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - 在视图中包装 Button,以创建自定义按钮

如何在 SwiftUI Toggle 中使用自定义图像

样式视图传递给 SwiftUI 中的自定义视图

SwiftUI 列表中的自定义按钮

如何修复自定义按钮在 SwiftUI(IOS) 中的交互?

如何将我的自定义 ButtonStyle 添加到 swiftui3 中的快捷方式 swiftui .buttonstyle() 属性