2017-08-07 8 views
1

UIViewの角の半径を、それが属するビューに適度にする方法はありますか?ビューの幅や高さが変わると(たとえば、異なる画面の向きで)すぐにコーナーが完全に異なって見えるため、コーナーの半径値をハードコーディングするというのは難しいです。たとえば、WhatsAppのチャットウィンドウを見てみましょう。動的コーナー半径(Swift)の一貫性曲線?

chat window of WhatsApp

あなたが見ることができるように、すべてのメッセージコンテナビューは、異なる幅と異なる高さを持っていますが、コーナーのカーブはすべてまったく同じです。これが私が達成しようとしていることです。ビューのサイズやビューの表示内容に関係なく、すべてのビューでコーナーの曲線が同じになるようにします。私はビューの高さ(view.layer.cornerRadius = view.frame.size.height * 0.25)に相対的なコーナー半径を設定しようとしましたが、ビューの幅にも設定しようとしましたが、これは機能しません。コーナーは、異なる画面サイズで表示されるとすぐに奇妙に見えます。曲線がすべてのビュー/画面サイズで同じに見えるようにする特定の数式やトリックがある場合は、教えてください。

+0

、あなたは彼らが本当に何ではありません – nathan

+0

@nathanそれをやった方法を学ぶために[JSQMessagesViewController](https://github.com/jessesquires/JSQMessagesViewController)を見てみる必要がありますを探しています。私の問題は、メッセージビューに固有の問題ではありません。一貫性のある曲線のランダムな例としてWhatsAppを使用していました。すべての 'UIView'サブクラス(画像ビュー、テキストビュー、ボタンなど)の解決策が必要です。私はチャットアプリケーションを作っていないし、たとえあったとしても、そのGithubプロジェクトを含めずに私自身のメッセージビューを作成することができます。私はちょうど異なる方向に同じままにするためにコーナーが必要です。 –

+0

あなたが気づいていない、または言及しなかった場合(あなたが気付いた場合)は、あなたの例では、各コーナーの間に相当な*ストレート*ボーダーもあるということです。これは重要なことです。cornerRadiusはコーナーにしか影響しません。つまり、あなたのビュー/サブビューが非常に小さい場合、コーナー半径の値を小さくする必要があるサークル(直線ボーダーのためのスペースなし)になります。角の半径の* max *値は、円で表され、フレームの高さまたは幅を2で割ったものです。たぶんあなたは、あなたが望む価値を決めるためにその経験則を使うことができます。 – dfd

答えて

2

ここで私ができることは最高です。これが助けになるかどうかは分かりませんが、うまくいけばあなたにいくつかのアイデアが与えられます。

まずコード:

class ViewController: UIViewController { 

    let cornerRadius:CGFloat = 10 
    let insetValue:CGFloat = 10 
    var numberOfViews:Int = 0 
    var myViews = [UIView]() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     view.translatesAutoresizingMaskIntoConstraints = false 
    } 

    override func viewWillLayoutSubviews() { 
     setNumberOfViews() 
     createViews() 
     createViewHierarchy() 
     addConstraints() 
    } 

    func setNumberOfViews() { 
     var smallerDimension:CGFloat = 0 
     if view.frame.height < view.frame.width { 
      smallerDimension = view.frame.height 
     } else { 
      smallerDimension = view.frame.width 
     } 
     let viewCount = smallerDimension/(insetValue * 2) 
     numberOfViews = Int(viewCount) 
    } 

    func createViews() { 
     for i in 1...numberOfViews { 
      switch i % 5 { 
      case 0: 
       myViews.append(MyView(UIColor.black, cornerRadius)) 
      case 1: 
       myViews.append(MyView(UIColor.blue, cornerRadius)) 
      case 2: 
       myViews.append(MyView(UIColor.red, cornerRadius)) 
      case 3: 
       myViews.append(MyView(UIColor.yellow, cornerRadius)) 
      case 4: 
       myViews.append(MyView(UIColor.green, cornerRadius)) 
      default: 
       break 
      } 
     } 
    } 

    func createViewHierarchy() { 
     view.addSubview(myViews[0]) 
     for i in 1...myViews.count-1 { 
      myViews[i-1].addSubview(myViews[i]) 
     } 
    } 

    func addConstraints() { 
     for view in myViews { 
      view.topAnchor.constraint(equalTo: (view.superview?.topAnchor)!, constant: insetValue).isActive = true 
      view.leadingAnchor.constraint(equalTo: (view.superview?.leadingAnchor)!, constant: insetValue).isActive = true 
      view.trailingAnchor.constraint(equalTo: (view.superview?.trailingAnchor)!, constant: -insetValue).isActive = true 
      view.bottomAnchor.constraint(equalTo: (view.superview?.bottomAnchor)!, constant: -insetValue).isActive = true 
     } 
    } 
} 

class MyView: UIView { 
    convenience init(_ backgroundColor:UIColor, _ cornerRadius:CGFloat) { 
     self.init(frame: CGRect.zero) 
     self.translatesAutoresizingMaskIntoConstraints = false 
     self.backgroundColor = backgroundColor 
     self.layer.cornerRadius = cornerRadius 
    } 
} 

説明:

これはかなり単純なコードです。できるだけ階層を深くネストして作成し、自動レイアウトを使用して、cornerRadius(ビューの角の半径)とinsetValue(「フレームの」インセット)の2つの主な変数を作成します。これらの2つの変数は、実験のために調整することができます。

ロジックの大部分はviewWillLayoutSubviewsにあり、ルートビューのフレームサイズは分かります。私は5種類の背景色を使用しているので、階層に収まるビューの数を計算しています。次に、それらを作成してからビュー階層を作成し、最後に制約を追加します。試す

と結論:

  • 私はあなたの心配が何であるかを見ることができました - はい、ビューのサイズの部品はコーナー半径よりも小さい場合、あなたは矛盾探しコーナーで終わります。しかし、これらの値はかなり小さく、10以下です。ほとんどのビューはそのサイズでは使用できません。 (私がリコールした場合でも、HIGは、ボタンのサイズには以下の40点あってはならないことを示唆している。確かに、でもAppleはそのルールを破る。まだ。)

  • あなたの「insetValue is sufficiently larger than the corner radius, you should never have an issue. Likewise, using the iMessage scenario, a single UILabel containing text and/or emoticons should have enough height that a noticeable cornerRadius`があったことができます。

  • cornerRadiusinsetValueのようなものを設定するためのキーポイントはあなたが決めることができたときに、viewWillLayoutSubviewsである(1)小さな寸法、高さまたは幅である、(2)どのように深くあなたが巣を望むことができ、そして(3)あなたが設定できるコーナー半径の大きさ。

  • 自動レイアウトを使用してください!フレームの絶対的な欠如に注意してください。適切な時点でルートビューの寸法を決定する以外に、デバイスのサイズや向きを気にせずに非常にコンパクトなコードを書くことができます。プロジェクトは最近廃止されている場合でも

+0

詳細な説明をありがとう。 'viewWillLayoutSubviews()'でコーナーの半径を設定することは、最も有用なヒントでした。それは知らなかった。私は間違いなく上記のコードを試してみます。結果はこれまでに試したことよりも良いはずです。 –

関連する問題