当上面没有任何东西时,UISegmentedControl难以处理

问题描述

我的问题是如此具体,我必须为此提供代码,如果代码过于复杂或太复杂,抱歉,因为我一直在学习SwiftUI而不是UIKit,所以我对UIKit有点陌生。

我有一个非常复杂的UITableView标头,上面有一些漂亮的动画等,我在上面放了一个UISegmentedControl。但是,一旦UITableViewCell落后于UISegmentedControl,它就会停止工作,并且UISegmentedControl用户交互功能会丢失。

如果没有可视上下文和代码,这太难解释了,就在这里

如您所见,在顶部,用户可以自由地与UISegmentedControl进行交互,但是当我开始滚动并且表格视图单元格位于UISegmentedControl之后(如预期的那样)时,分段控件将停止响应用户完全触摸输入。

1

再说一次,请原谅我冗长的(可能是不好的)代码,我还在学习。

这是我编写的UITableView的代码

class TertiaryProfileScroll: UITableViewController {
    var segmentedControl: UISegmentedControl!
    
    var testBlurView: UIVisualEffectView!
    var headerTitle: UIStackView!
    var blurView: UIVisualEffectView!
    var scoreRect: UIView!
    var scoreLabel: UILabel!
    
    var originalBlurRect: CGRect!
    var originalTitleRect: CGRect!
    var originalTestRect: CGRect!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let headerView = SecondaryStretchyTableHeaderView(frame: CGRect(x: 0,y: 0,width: view.bounds.width,height: 488))
        
        let image = UIImage(named: "background_image")
        
        UIGraphicsBeginImageContextWithOptions(CGSize(width: 350,height: 350),false,4)
        image!.draw(in: CGRect(origin: CGPoint(x: 0,y: 0),size: CGSize(width: 350,height: 350)))
        let newImage = UIGraphicsGetimageFromCurrentimageContext()
        UIGraphicsEndImageContext()
        
        tableView.allowsSelection = false
        tableView.separatorStyle = .none
        
        headerView.imageView.image = newImage
        
        tableView.tableHeaderView = headerView
        addTitle()
        
        blurView.contentView.isUserInteractionEnabled = true
        
        tableView.register(UITableViewCell.self,forCellReuseIdentifier: "Cell")
    }
    
    override func scrollViewDidScroll(_ scrollView: UIScrollView) {
        
        guard tableView.tableHeaderView != nil else { return }
        
        let headerView = self.tableView.tableHeaderView as! SecondaryStretchyTableHeaderView
        let headerGeometry = self.geometry(view: headerView,scrollView: scrollView)
        
        let titleGeometry = self.geometry(view: headerTitle,scrollView: scrollView)
        
        (tableView.tableHeaderView as! SecondaryStretchyTableHeaderView).containerView
            .alpha = CGFloat(sqrt(headerGeometry.largeTitleWeight))
        (tableView.tableHeaderView as! SecondaryStretchyTableHeaderView).imageContainer.alpha = CGFloat(sqrt(headerGeometry.largeTitleWeight))
        
        let largeTitleOpacity = (max(titleGeometry.largeTitleWeight,0.5) - 0.5) * 2
        let tinyTitleOpacity = 1 - min(titleGeometry.largeTitleWeight,0.5) * 2
        
        headerTitle.alpha = CGFloat(sqrt(largeTitleOpacity))
        
        blurView.contentView.subviews[1].alpha = CGFloat(sqrt(tinyTitleOpacity))
        
        if let vfxSubview = blurView.subviews.first(where: {
            String(describing: type(of: $0)) == "_UIVisualEffectSubview"
        }) {
            vfxSubview.backgroundColor = UIColor.systemBackground.withAlphaComponent(0)
        }
        
        if let vfxBackdrop = blurView.subviews.first(where: {
            String(describing: type(of: $0)) == "_UIVisualEffectBackdropView"
        }) {
            vfxBackdrop.alpha = CGFloat(1 - sqrt(titleGeometry.largeTitleWeight))
        }
        
        var blurFrame = blurView.frame
        var titleFrame = headerTitle.frame
        
        blurFrame.origin.y = max(originalBlurRect.minY,originalBlurRect.minY + titleGeometry.blurOffset)
        titleFrame.origin.y = originalTitleRect.minY + 364
        
        blurView.frame = blurFrame
        headerTitle.frame = titleFrame
        
        headerView.scrollViewDidScroll(scrollView: scrollView)
    }
    
    override func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
        1000
    }
    
    override func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
        
        cell?.textLabel?.text = String(indexPath.row)
        
        cell?.layer.zPosition = -1000
        
        view.sendSubviewToBack(cell!)
        view.bringSubviewToFront(tableView.tableHeaderView!)
        
        return cell!
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        self.navigationController?.setNavigationBarHidden(true,animated: false)
    }
    
    func addTitle() {
        let blurEffect = UIBlurEffect(style: uitraitcollection.current.userInterfaceStyle == .dark ? .dark : .light)
        blurView = UIVisualEffectView(effect: blurEffect)
        blurView.frame = CGRect(x: 0,width: UIScreen.main.bounds.size.width,height: 44 + 38 + tableView.safeAreaInsets.top)
        
        segmentedControl = UISegmentedControl(items: secondaryProfilePages)
        segmentedControl.selectedSegmentIndex = 0
        
        segmentedControl.frame = CGRect(x: 0,width: UIScreen.main.bounds.size.width - 32,height: 30)
        
        let scoreSize = ("+\(String(9999))" as Nsstring).boundingRect(with: CGSize(width: UIScreen.main.bounds.size.width,height: CGFloat.greatestFiniteMagnitude),options: [.truncatesLastVisibleLine,.usesLineFragmentOrigin],attributes: [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .caption1)],context: nil).size
        scoreLabel = PaddingLabel(withInsets: 2.5,2.5,5,5)
        scoreLabel.text = "+\(String(9999))"
        scoreLabel.font = UIFont.preferredFont(forTextStyle: .caption1)
        scoreLabel.textColor = .black
        scoreLabel.backgroundColor = .white
        scoreLabel.layer.masksToBounds = true
        scoreLabel.layer.cornerRadius = 5
        
        let smallscoreLabel = PaddingLabel(withInsets: 2.5,5)
        smallscoreLabel.text = "+\(String(9999))"
        smallscoreLabel.font = UIFont.preferredFont(forTextStyle: .caption1)
        smallscoreLabel.textColor = .label
        smallscoreLabel.backgroundColor = uitraitcollection.current.userInterfaceStyle == .dark ? .white : .black
        smallscoreLabel.layer.masksToBounds = true
        smallscoreLabel.layer.cornerRadius = 5
        
        let nsText = "OmerFlame" as Nsstring?
        
        let bigLabelSize = nsText?.boundingRect(with: CGSize(width: UIScreen.main.bounds.size.width - 32 - scoreLabel.intrinsicContentSize.width,attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 34,weight: .black)],context: nil).size
        
        let smallLabelSize = nsText?.boundingRect(with: CGSize(width: UIScreen.main.bounds.size.width - 32 - scoreLabel.intrinsicContentSize.width,attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18,weight: .bold)],context: nil).size
        
        let largeLabel = UILabel(frame: CGRect(x: 0,width: bigLabelSize!.width,height: bigLabelSize!.height))
        let smallLabel = UILabel(frame: CGRect(x: 0,width: smallLabelSize!.width,height: smallLabelSize!.height))
        
        largeLabel.text = "OmerFlame"
        largeLabel.font = .systemFont(ofSize: 34,weight: .black)
        largeLabel.textColor = .white
        largeLabel.adjustsFontSizetoFitWidth = true
        largeLabel.minimumScaleFactor = 0.2
        largeLabel.allowsDefaultTighteningForTruncation = true
        largeLabel.numberOfLines = 1
        
        smallLabel.text = "OmerFlame"
        smallLabel.font = .systemFont(ofSize: 18,weight: .bold)
        smallLabel.textColor = .label
        smallLabel.adjustsFontSizetoFitWidth = true
        smallLabel.minimumScaleFactor = 0.1
        smallLabel.allowsDefaultTighteningForTruncation = true
        smallLabel.numberOfLines = 1
        
        largeLabel.translatesAutoresizingMaskIntoConstraints = false
        smallLabel.translatesAutoresizingMaskIntoConstraints = false
        
        headerTitle = UIStackView(frame: CGRect(x: 0,width: largeLabel.frame.size.width + 5 + scoreLabel.intrinsicContentSize.width,height: max(largeLabel.frame.size.height,scoreLabel.intrinsicContentSize.height)))
        
        headerTitle.axis = .horizontal
        headerTitle.alignment = .center
        headerTitle.distribution = .equalCentering
        
        headerTitle.addArrangedSubview(largeLabel)
        headerTitle.addArrangedSubview(scoreLabel)
        
        let smallHeaderTitle = UIStackView(frame: CGRect(x: 0,width: smallLabel.frame.size.width + 5 + smallscoreLabel.intrinsicContentSize.width,height: max(smallLabel.frame.size.height,smallscoreLabel.intrinsicContentSize.height)))
        
        smallHeaderTitle.axis = .horizontal
        smallHeaderTitle.alignment = .center
        smallHeaderTitle.distribution = .equalCentering
        
        smallHeaderTitle.addArrangedSubview(smallLabel)
        smallHeaderTitle.addArrangedSubview(smallscoreLabel)
        
        blurView.contentView.addSubview(headerTitle)
        blurView.contentView.addSubview(smallHeaderTitle)
        blurView.contentView.addSubview(segmentedControl)
        tableView.tableHeaderView!.addSubview(blurView)
        
        blurView.translatesAutoresizingMaskIntoConstraints = false
        blurView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        blurView.heightAnchor.constraint(equalTo: tableView.tableHeaderView!.heightAnchor).isActive = true
        blurView.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.size.width).isActive = true
        
        largeLabel.translatesAutoresizingMaskIntoConstraints = false
        smallLabel.translatesAutoresizingMaskIntoConstraints = false
        
        scoreLabel.translatesAutoresizingMaskIntoConstraints = false
        scoreLabel.leadingAnchor.constraint(equalTo: largeLabel.trailingAnchor,constant: 5).isActive = true
        
        smallHeaderTitle.translatesAutoresizingMaskIntoConstraints = false
        
        smallscoreLabel.translatesAutoresizingMaskIntoConstraints = false
        smallscoreLabel.leadingAnchor.constraint(equalTo: smallLabel.trailingAnchor,constant: 5).isActive = true
        smallscoreLabel.bottomAnchor.constraint(equalTo: smallLabel.bottomAnchor).isActive = true
        
        smallHeaderTitle.centerXAnchor.constraint(equalTo: blurView.contentView.centerXAnchor).isActive = true
        smallHeaderTitle.heightAnchor.constraint(equalToConstant: max(smallLabel.frame.size.height,smallscoreLabel.intrinsicContentSize.height)).isActive = true
        smallHeaderTitle.widthAnchor.constraint(equalToConstant: smallLabel.frame.size.width + 5 + smallscoreLabel.intrinsicContentSize.width).isActive = true
        smallHeaderTitle.bottomAnchor.constraint(equalTo: segmentedControl.topAnchor,constant: -4).isActive = true
        
        headerTitle.translatesAutoresizingMaskIntoConstraints = false
        
        headerTitle.bottomAnchor.constraint(equalTo: segmentedControl.topAnchor,constant: -8).isActive = true
        headerTitle.widthAnchor.constraint(equalToConstant: largeLabel.frame.size.width + 5 + scoreLabel.intrinsicContentSize.width).isActive = true
        headerTitle.heightAnchor.constraint(equalToConstant: max(largeLabel.frame.size.height,scoreLabel.intrinsicContentSize.height)).isActive = true
        
        largeLabel.leadingAnchor.constraint(equalTo: blurView.contentView.leadingAnchor,constant: 16).isActive = true
        
        originalBlurRect = blurView.frame
        originalTitleRect = headerTitle.frame
        
        segmentedControl.translatesAutoresizingMaskIntoConstraints = false
        segmentedControl.bottomAnchor.constraint(equalTo: blurView.contentView.bottomAnchor,constant: -8).isActive = true
        segmentedControl.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.size.width - 32).isActive = true
        segmentedControl.heightAnchor.constraint(equalToConstant: 30).isActive = true
        segmentedControl.leadingAnchor.constraint(equalTo: blurView.contentView.leadingAnchor,constant: 16).isActive = true

        view.bringSubviewToFront(smallHeaderTitle)
        view.bringSubviewToFront(segmentedControl)
        
        segmentedControl.layer.zPosition = 1000
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        view.bringSubviewToFront(blurView)
    }
    
    override func traitCollectionDidChange(_ prevIoUsTraitCollection: uitraitcollection?) {
        super.traitCollectionDidChange(prevIoUsTraitCollection)
        
        if traitCollection.userInterfaceStyle == .dark {
            (blurView.contentView.subviews[1] as! UIStackView).arrangedSubviews[1].backgroundColor = .white
            ((blurView.contentView.subviews[1] as! UIStackView).arrangedSubviews[1] as! UILabel).textColor = .black
        } else {
            (blurView.contentView.subviews[1] as! UIStackView).arrangedSubviews[1].backgroundColor = .black
            ((blurView.contentView.subviews[1] as! UIStackView).arrangedSubviews[1] as! UILabel).textColor = .white
        }
    }
}

extension TertiaryProfileScroll {
    struct HeaderGeometry {
        let width: CGFloat
        let headerHeight: CGFloat
        let elementsHeight: CGFloat
        let headerOffset: CGFloat
        let blurOffset: CGFloat
        let elementsOffset: CGFloat
        let largeTitleWeight: Double
    }
    
    func geometry(view: UIView,scrollView: UIScrollView) -> HeaderGeometry {
        let safeArea = scrollView.safeAreaInsets
        
        let minY = -(scrollView.contentOffset.y + scrollView.safeAreaInsets.top)
        
        let hasScrolledUp = minY > 0
        
        let hasScrolledToMinHeight = -minY >= 450 - 44 - safeArea.top

        let headerHeight = hasScrolledUp ?
            (tableView.tableHeaderView as! SecondaryStretchyTableHeaderView).containerView.frame.size.height + minY + 38 : (tableView.tableHeaderView as! SecondaryStretchyTableHeaderView).containerView.frame.size.height + 38

        let elementsHeight = (tableView.tableHeaderView as! SecondaryStretchyTableHeaderView).frame.size.height + minY

        let headerOffset: CGFloat
        let blurOffset: CGFloat
        let elementsOffset: CGFloat
        let largeTitleWeight: Double

        if hasScrolledUp {
            headerOffset = -minY
            blurOffset = -minY
            elementsOffset = -minY
            largeTitleWeight = 1
        } else if hasScrolledToMinHeight {
            headerOffset = -minY - 450 + 44 + safeArea.top
            blurOffset = -minY - 450 + 44 + safeArea.top
            elementsOffset = headerOffset / 2 - minY / 2
            largeTitleWeight = 0
        } else {
            headerOffset = 0
            blurOffset = 0
            elementsOffset = -minY / 2
            let difference = 450 - 44 - safeArea.top + minY
            largeTitleWeight = difference <= 44 + 1 ? Double(difference / (44 + 1)) : 1
        }
        
        return HeaderGeometry(width: (tableView.tableHeaderView as! SecondaryStretchyTableHeaderView).frame.size.width,headerHeight: headerHeight,elementsHeight: elementsHeight,headerOffset: headerOffset,blurOffset: blurOffset,elementsOffset: elementsOffset,largeTitleWeight: largeTitleWeight)
    }
}

class SecondaryStretchyTableHeaderView: UIView {
    var imageContainerHeight = NSLayoutConstraint()
    var imageContainerBottom = NSLayoutConstraint()
    
    var imageViewHeight = NSLayoutConstraint()
    var imageViewBottom = NSLayoutConstraint()
    var imageViewTop = NSLayoutConstraint()
    
    
    var containerView: UIView!
    var imageContainer: UIView!
    var imageView: UIImageView!
    
    var largeTitleOpacity = Double()
    var tinyTitleOpacity = Double()
    
    var largeLabel: UILabel!
    var tinyLabel: UILabel!
    
    var containerViewHeight = NSLayoutConstraint()
    
    var stack: UIStackView!
    
    var title: StretchyHeaderTitle!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        createViews()
        
        setViewConstraints()
        
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    func createViews() {
        
        // Container View
        containerView = UIView()
        self.addSubview(containerView)
        
        imageContainer = UIView()
        imageContainer.backgroundColor = UIColor(hex: "d55161")
        imageContainer.contentMode = .scaleAspectFill
        imageContainer.clipsToBounds = true
        containerView.addSubview(imageContainer)
        
        // ImageView for background
        imageView = UIImageView()
        imageView.backgroundColor = UIColor(hex: "d55161")
        imageView.contentMode = .scaleAspectFill
        imageContainer.addSubview(imageView)
    }
    
    func setViewConstraints() {
        // UIView Constraints
        NSLayoutConstraint.activate([
            self.widthAnchor.constraint(equalTo: containerView.widthAnchor),self.centerXAnchor.constraint(equalTo: containerView.centerXAnchor),self.heightAnchor.constraint(equalTo: containerView.heightAnchor)
        ])
        
        // Container View Constraints
        containerView.translatesAutoresizingMaskIntoConstraints = false
        
        containerView.widthAnchor.constraint(equalTo: imageContainer.widthAnchor).isActive = true
        containerViewHeight = containerView.heightAnchor.constraint(equalTo: self.heightAnchor)
        containerViewHeight.isActive = true
        
        // ImageView Constraints
        imageContainer.translatesAutoresizingMaskIntoConstraints = false
        imageContainerBottom = imageContainer.bottomAnchor.constraint(equalTo: containerView.bottomAnchor)
        imageContainerBottom.isActive = true
        imageContainerHeight = imageContainer.heightAnchor.constraint(equalTo: containerView.heightAnchor)
        imageContainerHeight.isActive = true
        
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageViewBottom = imageView.bottomAnchor.constraint(equalTo: imageContainer.bottomAnchor,constant: -50)
        imageViewBottom.isActive = true
        
        imageViewTop = imageView.topAnchor.constraint(equalTo: imageContainer.topAnchor,constant: 50)
        imageViewTop.isActive = true
        
        imageView.centerXAnchor.constraint(equalTo: imageContainer.centerXAnchor).isActive = true
    }
    
    func scrollViewDidScroll(scrollView: UIScrollView) {
        
        containerViewHeight.constant = scrollView.contentInset.top
        let offsetY = -(scrollView.contentOffset.y + scrollView.contentInset.top)
        
        containerView.clipsToBounds = offsetY <= 0
        imageContainerBottom.constant = offsetY >= 0 ? 0 : -offsetY / 2
        imageContainerHeight.constant = max(offsetY + scrollView.contentInset.top,scrollView.contentInset.top)
        imageContainer.clipsToBounds = offsetY <= 0
        imageViewBottom.constant = (offsetY >= 0 ? 0 : -offsetY / 2) - 50
        imageViewTop.constant = (offsetY >= 0 ? 0 : -offsetY / 2) + 50
    }
}

extension UIColor {

    // MARK: - Initialization

    convenience init?(hex: String) {
        var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines)
        hexSanitized = hexSanitized.replacingOccurrences(of: "#",with: "")

        var rgb: UInt32 = 0

        var r: CGFloat = 0.0
        var g: CGFloat = 0.0
        var b: CGFloat = 0.0
        var a: CGFloat = 1.0

        let length = String(hexSanitized).count

        guard Scanner(string: hexSanitized).scanHexInt32(&rgb) else { return nil }

        if length == 6 {
            r = CGFloat((rgb & 0xFF0000) >> 16) / 255.0
            g = CGFloat((rgb & 0x00FF00) >> 8) / 255.0
            b = CGFloat(rgb & 0x0000FF) / 255.0

        } else if length == 8 {
            r = CGFloat((rgb & 0xFF000000) >> 24) / 255.0
            g = CGFloat((rgb & 0x00FF0000) >> 16) / 255.0
            b = CGFloat((rgb & 0x0000FF00) >> 8) / 255.0
            a = CGFloat(rgb & 0x000000FF) / 255.0

        } else {
            return nil
        }

        self.init(red: r,green: g,blue: b,alpha: a)
    }

    // MARK: - Computed Properties

    var toHex: String? {
        return toHex()
    }

    // MARK: - From UIColor to String

    func toHex(alpha: Bool = false) -> String? {
        guard let components = cgColor.components,components.count >= 3 else {
            return nil
        }

        let r = Float(components[0])
        let g = Float(components[1])
        let b = Float(components[2])
        var a = Float(1.0)

        if components.count >= 4 {
            a = Float(components[3])
        }

        if alpha {
            return String(format: "%02lX%02lX%02lX%02lX",lroundf(r * 255),lroundf(g * 255),lroundf(b * 255),lroundf(a * 255))
        } else {
            return String(format: "%02lX%02lX%02lX",lroundf(b * 255))
        }
    }

}

我想我已经给出了与问题相关的所有代码。如果我错过了什么,请告诉我。我知道代码真的很长,但是对于应该做什么我一无所知。欢迎任何回复!对于可能重复的代码,我也表示歉意,我急于发布此代码

谢谢!

解决方法

好-我要运行您的代码。

问题是您的分段控件正在扩展到表标题视图的边界

我认为将所有属于“可伸缩标头” 一部分的UI元素保留在标头类中会更有意义,所以我不建议这样做,但这应该应该带给您分段的控件交互:

在您的SecondaryStretchyTableHeaderView类中,添加以下var /属性:

weak var segControl: UISegmentedControl?

在您的addTitle()类的TertiaryProfileScroll中,添加以下内容:

    // your existing code
    blurView.contentView.addSubview(headerTitle)
    blurView.contentView.addSubview(smallHeaderTitle)
    blurView.contentView.addSubview(segmentedControl)
    tableView.tableHeaderView!.addSubview(blurView)

    // add this
    if let v = tableView.tableHeaderView as? SecondaryStretchyTableHeaderView {
        // give our custom header view a reference to the segemented control
        v.segControl = segmentedControl
    }

返回您的SecondaryStretchyTableHeaderView类,添加此功能:

override func hitTest(_ point: CGPoint,with event: UIEvent?) -> UIView? {
    
    guard isUserInteractionEnabled,!isHidden,alpha >= 0.01,let sc = segControl
    else { return nil }

    // if we tap outside the bounds,//  but on the segmented control
    //  return the segmented control
    let convertedPoint = sc.convert(point,from: self)
    if let v = sc.hitTest(convertedPoint,with: event) {
        return v
    }
    
    guard self.point(inside: point,with: event) else { return nil }
    
    return self
    
}

这将允许您与分段控件进行交互,即使该控件不在表标题视图的范围之内。

作为旁注,您似乎将.layer.zPosition设置为不需要的位置。在cellForRowAt中,我注释了以下几行:

override func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
    
    cell?.textLabel?.text = String(indexPath.row)
    
    //cell?.layer.zPosition = -1000
    //view.sendSubviewToBack(cell!)
    //view.bringSubviewToFront(tableView.tableHeaderView!)
    
    return cell!
}

并注释掉了这一行(在addTitle()的末尾):

//segmentedControl.layer.zPosition = 1000

我没什么区别。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...