【问题标题】:How to make Horizontal scrollView and some buttons in it (programming)如何制作水平滚动视图和其中的一些按钮(编程)
【发布时间】:2025-11-30 02:35:01
【问题描述】:

抱歉,我有一个问题。我不使用storyBoard。

我想做一个这样的视图。
photo by terenceLuffy/AppStoreStyleHorizontalScrollView

但我尝试这样做。 最后,scrollView 只显示这样的最后一个按钮。

这是代码:

var scView:UIScrollView = UIScrollView()
var buttonPadding:CGFloat = 10
var xOffset:CGFloat = 10


scView.backgroundColor = UIColor.blue
scView.translatesAutoresizingMaskIntoConstraints = false


func viewDidLoad() {

for i in 0 ... 10 {

    let button = UIButton()

    button.tag = i
    button.backgroundColor = UIColor.darkGray
    button.setTitle("\(i)", for: .normal)
    button.addTarget(self, action: #selector(btnTouch), for: UIControlEvents.touchUpInside)

    button.frame = CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 70, height: 30)

    xOffset = xOffset + CGFloat(buttonPadding) + button.frame.size.width
    scView.addSubview(button)


}

scView.contentSize = CGSize(width: xOffset, height: scView.frame.height)

}

请帮助我。 谢谢大家!

【问题讨论】:

  • 为什么不使用水平滚动的 UICollectionView ???
  • 您能展示一下如何将 UIScrollView 添加到您的视图中吗?
  • view.addSubview(scView)
  • 您的代码似乎没有任何问题。除了你在视图中调用它确实加载。请尝试我的回答,如果有任何问题,请告诉我
  • 我已经尝试过你的代码,它运行良好,也许你有其他方法可以改变 uiscrollview 的偏移位置或其他什么?

标签: ios iphone swift uiscrollview horizontal-scrolling


【解决方案1】:

我已经尝试了您的代码并对其进行了一些更改。它按预期工作,除非您有其他事情要做:

var scView:UIScrollView!
let buttonPadding:CGFloat = 10
var xOffset:CGFloat = 10

override func viewDidLoad() {
    super.viewDidLoad()
    scView = UIScrollView(frame: CGRect(x: 0, y: 120, width: view.bounds.width, height: 50))
    view.addSubview(scView)

    scView.backgroundColor = UIColor.blue
    scView.translatesAutoresizingMaskIntoConstraints = false

    for i in 0 ... 10 {
        let button = UIButton()
        button.tag = i
        button.backgroundColor = UIColor.darkGray
        button.setTitle("\(i)", for: .normal)
        //button.addTarget(self, action: #selector(btnTouch), for: UIControlEvents.touchUpInside)

        button.frame = CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 70, height: 30)

        xOffset = xOffset + CGFloat(buttonPadding) + button.frame.size.width
        scView.addSubview(button)


    }

    scView.contentSize = CGSize(width: xOffset, height: scView.frame.height)
}

【讨论】:

    【解决方案2】:

    有两种方法可以实现它:) 一种是使用 scrollView 并以编程方式在 ScrollView 上计算偏移量和设置视图作为子视图的艰难方法,否则使用 CollectionView

    第 1 步:

    将 UICollectionView 添加到情节提要,设置 collectionView 的高度以符合您的要求:)

    第 2 步

    创建一个单元格,其大小取决于您的要求。我创建了一个背景颜色为橙色/粉红色的单元格。在其上添加了一个标签以显示您的号码。

    第 3 步:

    将可重复使用的单元格标识符设置为单元格并设置其类:)

    第 4 步:

    将collectionView滚动方向设置为水平:)

    第 5 步:

    现在实现 collectionView 委托和数据源方法:)

    extension ViewController : UICollectionViewDataSource,UICollectionViewDelegate {
        func numberOfSections(in collectionView: UICollectionView) -> Int {
            return 1
        }
    
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 10
        }
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "myCell", for: indexPath) as! MyCollectionViewCell
            cell.myLabel.text = "ABCD"
            return cell;
        }
    }
    

    就是这样:)

    最终的 O/P

    查看带有单元格 ABCD 的 collectionView :D

    其他信息

    如果您在 UIViewController 上拖动 collectionView,您可能会看到 collectionView 在顶部留下了一个间隙,您可以通过取消选中 Adjust ScrollView Insets of ViewController 来解决这个问题:)

    【讨论】:

    • 谢谢,但我只想使用 scrollView 来显示我的视图。
    【解决方案3】:
    import UIKit
    
    class ViewController: UIViewController {
    
        var imageStrings:[String] = []
         var myScrollView:UIScrollView!
    
    
        @IBOutlet weak var previewView: UIImageView!
    
    
    
        var scrollWidth : CGFloat = 320
        let scrollHeight : CGFloat = 100
        let thumbNailWidth : CGFloat = 80
        let thumbNailHeight : CGFloat = 80
        let padding: CGFloat = 10
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            imageStrings = ["image01","image02","image03","image04","image05","image06","image07","image08"]
    
            scrollWidth = self.view.frame.width
    
            //setup scrollView
            myScrollView = UIScrollView(frame: CGRectMake(0, self.view.frame.height - scrollHeight, scrollWidth, scrollHeight))
    
            //setup content size for scroll view
            let contentSizeWidth:CGFloat = (thumbNailWidth + padding) * (CGFloat(imageStrings.count))
            let contentSize = CGSize(width: contentSizeWidth ,height: thumbNailHeight)
    
            myScrollView.contentSize = contentSize
            myScrollView.autoresizingMask = UIViewAutoresizing.FlexibleWidth
    
    
            for(index,value) in enumerate(imageStrings) {
                var button:UIButton = UIButton.buttonWithType(.Custom) as! UIButton
                //calculate x for uibutton
                var xButton = CGFloat(padding * (CGFloat(index) + 1) + (CGFloat(index) * thumbNailWidth))
                button.frame = CGRectMake(xButton,padding, thumbNailWidth, thumbNailHeight)
                button.tag = index
    
                let image = UIImage(named:value)
                button.setBackgroundImage(image, forState: .Normal)
                button.addTarget(self, action: Selector("changeImage:"), forControlEvents: .TouchUpInside)
    
                myScrollView.addSubview(button)
            }
            previewView.image = UIImage(named: imageStrings[0])
            self.view.addSubview(myScrollView)
        }
            // Do any additional setup after loading the view, typically from a nib.
    
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
        func changeImage(sender:UIButton){
            let name = imageStrings[sender.tag]
            previewView.image = UIImage(named: name)
        }
    
    
    }
    

    【讨论】:

      【解决方案4】:
          //make that variable gloabl
         let button = UIButton.init(type: .custom)
          var arrMmenu :  NSMutableArray = []
          var  selectedIndex : Int = 0
           @IBOutlet weak var btnScrollView: UIScrollView!
          var lineArray : NSMutableArray = []
          var buttonArray : NSMutableArray = []
      

      //调用buttonCreated()

        //MARK:- Create an Horizontral LayOut
      func buttonCreated()
      {
      
          btnScrollView.contentSize.width = 0
       namesOfMenu = ["GMC","GPA","GTL"]
          var scrollwidth: CGFloat = 10.0
      
          for j in 0..<namesOfMenu.count
          {
              let name = namesOfMenu[j] as! String
              let size : CGSize? = name.size(withAttributes : [NSAttributedStringKey.font : UIFont.systemFont(ofSize: 10.0)])
      
      
              let textsize = CGSize(width : CGFloat(ceilf(Float(size!.width))), height : CGFloat(ceilf(Float(size!.height))))
      
              var strikwidth : CGFloat = textsize.width
              strikwidth = textsize.width + 30
              let frame = CGRect(x: scrollwidth , y : CGFloat(7),width :CGFloat(strikwidth + 20) , height :CGFloat(20))
              let frameLine = CGRect(x: scrollwidth , y : CGFloat(30),width :CGFloat(strikwidth + 20) , height :CGFloat(2))
              let button = UIButton(type: .custom)
              let line = UIView()
              line.frame = frameLine
              button.tag = j
              view.tag = j
              button.frame = frame
              line .backgroundColor = UIColor.red
              button.backgroundColor = UIColor.red
              button.setTitleColor(UIColor.white, for: UIControlState.normal)
              button.layer.borderColor = UIColor.white.cgColor
              button.titleLabel?.textAlignment = .center
              button.addTarget(self, action: #selector(self.buttonEvent(_:)), for: .touchUpInside)
              button.setTitle(name, for : .normal)
              scrollwidth = scrollwidth + strikwidth + 30
              let strofMenu = namesOfMenu[selectedIndex] as! String
      
              if (j == selectedIndex)
              {
      
                  if(strofMenu == "GMC")
                  {
                      // apicall()
                  }
      
                  line.backgroundColor = hexStringToUIColor(hex: "#3174C7")
                  button.backgroundColor = UIColor.clear
      
                  button.setTitleColor(hexStringToUIColor(hex: "#3174C7"), for: UIControlState.normal)
      
      
              }else
              {
                  line.backgroundColor = UIColor.clear
                  button.backgroundColor = UIColor.clear
      
                  button.setTitleColor(MyConstant.Color.dark_gray_shade, for: UIControlState.normal)
      
              }
              button.titleLabel?.font =  MyConstant.fontApp.Regular
      
              buttonArray.add(button)
      
              lineArray.add(line)
      
              btnScrollView.addSubview(button)
      
              btnScrollView.addSubview(line)
      
          }
      
          btnScrollView.contentSize = CGSize(width : CGFloat(scrollwidth), height :  CGFloat(40.0))
      
          btnScrollView.isPagingEnabled = false
      
          btnScrollView.showsHorizontalScrollIndicator = false
      
          btnScrollView.showsVerticalScrollIndicator = false
      }
      
      //MARK:- Button Event
      
      @objc func buttonEvent(_ sender : UIButton)
      
      {
      
          let index = sender.tag
      
          selectedIndex = index
      
          let getRepoName = namesOfMenu[index] as! String
      
          print(getRepoName)
      
      
          for i in 0..<buttonArray.count
      
          {
      
              let buttonone : UIButton = (buttonArray[i] as! UIButton)
      
              let line : UIView  = (lineArray[i]) as! UIView
      
              if i == selectedIndex
              {
                  buttonone.backgroundColor = UIColor.clear
      
                  line.backgroundColor = hexStringToUIColor(hex: "#3174C7")
      
                  buttonone.setTitleColor(hexStringToUIColor(hex: "#3174C7"), for: .normal)
                  //
                  //                if(getRepoName == "GMC")
                  //                {
                  //                    clickedCellIndexes.add(0)
                  //
                  //                    arrmutablefordata.removeAllObjects()
                  //                    tblhome.reloadData()
                  //                    apicall()
                  //                }
      
      
                  //buttonone.titleLabel
              }else
              {
                  buttonone.backgroundColor = UIColor.clear
      
                  line.backgroundColor = UIColor.clear
      
                  buttonone.setTitleColor(MyConstant.Color.dark_gray_shade, for: .normal)
      
              }
      
      
      
      
      
          }
      
      }
      

      【讨论】:

      【解决方案5】:

      使用最少的情节提要很容易。你可以很容易地避免这种情况。您只需要:

      1. 滚动视图
      2. 水平堆栈视图
      3. 如项目所示设置上述的约束
      4. 按钮数量 - 需要显示的视图控制器数量。
      5. 容器视图 - 这将是保存活动视图控制器的视图。

      请参考这个项目的一些示例代码: https://github.com/equitronix/horizontalScrollMenu

      【讨论】:

        【解决方案6】:

        使用滚动视图和堆栈视图从情节提要中执行此操作,这是一个非常简单的解决方案。连同一堆子视图控制器和转换。我已经在 GitHub 上发布了示例代码。请看这里:

        https://github.com/equitronix/horizontalScrollMenu

        让我知道这是否有效。

        【讨论】: