16

カスタムUISlider(UISliderのサブクラス)を実装しようとしています。これは、強調表示されたときに親指の周りが光るネイティブスライダーと同じように動作します。しかし、私はこれに問題があります。

ハイライトされた親指の(有効な)幅は、通常の親指よりも明らかに大きくなっています(グローのため)。通常の状態の画像に透明なピクセルパディングを追加して、両方の画像の幅が同じになるようにすると、問題は、通常の状態のサムがトラックの最後に到達したようには見えないことです(ただし、パディングによりそれ以外の場合は表示されます)。

thumbRectForBounds:を使用して、親指をオフセットしてトラックの先頭に正しく合わせると、もう一方の端で問題が悪化するだけです。

両方の画像を必要な幅だけに保つと(つまり、通常の状態ではパディングがなく、2つは同じ幅ではありません)、近づきました。オフセットはthumbRectForBoundsで個別に設定できます:UIControl.stateに基づいていますが、舞台裏で数学の魔法が行われているようです。UISliderが両方の状態の画像が完全に並んでいると考える唯一の場所は、正確な中心です。

トラックに沿った相対位置に基づいてハイライト状態のオフセットを決定する数学を実装する必要があるようです。中央にゼロのyオフセットが必要になります(UISliderは両方の画像を中央に配置します。つまり、画像は整列します)。極端な場合は、グローを完全に補うyオフセットが必要になります。そしてその間に、yオフセットを補間する必要があります。

これは、ネイティブスライダーが行うことを再現するための多くの作業のように思われるので、おそらく私は明らかな何かを見逃しています。

現在のソリューションを更新する:

追加されるグローのサイズについていくつかの仮定を行うため、完全に移植可能ではありません。CALayerに直接描画するのではなく、画像を使用してグローを追加しています。これがどれほどパフォーマンスが良いかはまだテストしていません。

基本的に、デフォルトの状態の親指の画像の高さを寸法とする正方形のレイヤーを作成し、それを親指の中央に配置してから、グローを描画します(グローのみで、グローのある親指の個別のイメージではありません。ハイライト状態の画像を使用して)をレイヤーに追加します。

- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value {
  CGRect r = [super thumbRectForBounds:bounds trackRect:rect value:value];

  [thumbHighlightOverlayLayer removeFromSuperlayer];
  thumbHighlightOverlayLayer = [CALayer layer]; 

  int x = r.origin.x + (r.size.width / 2) - (r.size.height / 2);
  thumbHighlightOverlayLayer.frame = CGRectMake(x, r.origin.y, r.size.height, r.size.height);

  UIImage* thumbHighlightOverlayImage = [UIImage imageNamed:@"thumb-highlight"];
  thumbHighlightOverlayLayer.contents = (id)thumbHighlightOverlayImage.CGImage;

  switch (self.state) {
    case UIControlStateHighlighted:
      [[self layer] addSublayer:thumbHighlightOverlayLayer];
      break;
    default:
      break;
  }

  return r;
}
4

3 に答える 3

1

画像にグロー効果を追加するのではなく、動的に追加した方がよい場合があります。CALayer を使用してグロー効果を追加できます。

CALayer

于 2012-05-09T07:01:00.967 に答える
0

あるアプリのカスタムスライダーで同様の問題が発生しました。通常のスライダーとは異なり、トラックは静的な数直線であるため、最小トラック画像と最大トラック画像を別々に表示する必要はありません。それでも、親指用に特大のホットスポットが必要でした。そこで、透明なピクセルを追加して親指の画像を作成し、トラックに透明な画像を割り当てました。表示されるトラックは、スライダーの背後にあるUIImageViewです(実際には、スライダーのグループの背後にある1つのUIImageView)。スライダーの端は、トラック画像の端をはるかに超えて伸びています。

私の提案は、UISliderのカスタマイズの制限に逆らうのではなく、複数のビューを組み合わせて、目的のスライダーの視覚的な構成を作成することです。トラックを変更せずにできるのであれば、私のテクニックを複製することができます。または、UIViewのフレームを1つか2つ操作して、スライダーの値が変わるたびにカスタムトラックを調整することもできます。この同じスライダーをアプリで複数回使用する必要がある場合は、ビューのグループをUIViewサブクラスにパッケージ化できます。スライダーアクションがどれほど複雑になるかによっては、カスタムコントロールを作成する方が賢明な選択になる場合があります。

于 2012-05-10T14:39:40.103 に答える
0

独自のスライダーを回転させることもできます。これは、思ったほど複雑ではありませんが、数時間のコーディングが必要です。

ただし、最も簡単な解決策は、カスタム トラック イメージも設定することです。

  1. 左側/右側にパディング (透明ピクセル) を使用して、カスタムの「最小」/「最大」トラック イメージを作成します。パディングは、グローの半径から親指の半径 (11pt) を差し引いた大きさにする必要があります。
  2. setMinimumTrackImage:forState:と を使用して UISlider に画像を適用しますsetMaximumTrackImage:forState:
  3. 追加したパディングのサイズだけスライダーの幅を広げます
于 2012-05-10T12:50:40.170 に答える