4

このレイアウトを検討してください(ここから引っ張ってきました):

ここに画像の説明を入力

このレイアウトを画面サイズに合わせて拡大縮小する原理を理解したいと思います。正方形の場合、カスタム onMeasure 関数がうまく機能します。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}

以下のカスタム Togglebuttons と Imagebuttons の幅と高さは、画面の残りの部分 (layout_margins を除く) を満たすようにスケーリングする必要があり、内部のテキストと画像は、ボタンを埋めるためにスケーリングする必要があります (パディングを除く)。外側のマージンもスケーリングする必要があります。

私が最初に考えたのは、相対レイアウトを使用してボタンを配置し、layout_margin/padding 属性を使用してマージンを作成することでした。ただし、相対レイアウトと layout_margin/padding には固定ピクセル値が必要なため、スケーラブルではありません。

次に、layout_weights を使用してネストされたリニア レイアウトを使用してボタンを配置し、プレースホルダー ビューを使用して余白を作成することを考えました。これらの手法はスケーラブルですが、ボタンには固定ピクセル値を必要とする多くの属性 (テキスト サイズ、画像サイズ、角の半径など) があるため、ボタンでは機能しません。この制限は、たとえば、次の xml を意味します。

<ToggleButton 
    android:layout_weight="1"
    style="@style/myButton"
    [...] />
<View 
    android:layout_weight="1"/>
<ImageButton 
    android:layout_weight="1"
    style="@style/myButton"
    [...] />

必ずしも 2 つのボタンとそれらの間のスペースがすべて同じ幅になるとは限りません。それはすべて、ボタンのテキストサイズ、画像サイズなどに依存します。

私はこの質問を見てきましたが、非XMLに頼る必要のない、このような単純な問題に対するより単純な解決策があるはずだと感じています。

4

3 に答える 3

4

View作成するカスタムとクラスの数に大きく依存ViewGroupします。私が考えることができるカスタムクラスの数が最も少ない実装は、次のようになります(あなたが説明したものと非常に似ています):

  • FrameLayout最大の正方形に合わせてカスタマイズされ、高さを使用可能な幅に一致させるカスタム実装onMeasure()があります (これについては既に述べました)。
  • LinearLayoutウェイトを使用してすべてのグリッド ボタンを同じサイズにするネストされたインスタンス。

このアプローチの大きな欠点は効率です。LinearLayout大きな 9x9 グリッド内に小さな 9x9 グリッドを作成するには、およそ 36 個のインスタンスが必要です。これは、純粋なレイアウト オーバーヘッドの 36 ビューです。


テキストのサイズ変更に関しては、これを処理する方法がいくつか考えられます。1 つは(測定を行うために any のオブジェクトをPaint.measureTextBounds()取得できます) を使用して、測定後に各ボタンのテキストを作成するために必要なサイズを決定することです。残念ながら、 は現在の設定に基づいて特定のテキストを測定するため、これは幾分反復的なプロセスになります。そのため、次のことを行う必要があります。PaintTextViewPaint

  1. 文字サイズを設定する
  2. 測定範囲
  3. 高さをチェック
  4. サイズがちょうど合うまで繰り返します

幸いなことに、これを 1 回だけ実行してすべてのグリッド ボタンに適用するだけで済みますが、グリッド ボタンが測定されるまで待つ必要があります。

ここでの別のオプションは、テキストの代わりに画像を のようなものに表示することですImageView。これにより、コンテンツをそのサイズに合わせて拡大縮小できます。私が書いたTextDrawableのようなものを使用して、テキスト コンテンツを、品質を損なうことなくスケーラブルな画像として設定できます。


レイアウトに戻ります。ViewGroupグリッドを測定してレイアウトするカスタムを作成することで、大幅な効率を取り戻すことができます(名前GridLayoutは既に使用されています...そして、この目的にはまったく役立たないので、 と呼びましょうBlockLayout)。カスタムを作成すると、各ブロックのサイズを測定し、4 つのインスタンスBlockLayoutではなく単一の親を持つグリッドに 9 つのサブビューをレイアウトできます。LinearLayoutこれは基本的に、正方形全体を均等に分割する方法と同じです。

その後、レイアウト オーバーヘッドのインスタンスを 10 回だけ使用してレイアウト全体を構築できます。全体を単一のViewGroup.

基本的に、ビュー階層を平坦化するために記述できるコードが多いほど、アプリケーションは全体的により適切に実行されます。

HTH

于 2012-12-29T04:54:58.857 に答える
0

Devnuwired の回答を補完するために、これに似たメソッドを記述して、彼のTextDrawableテキストをに追加できImageButtonます。

private void addText(String text, ImageButton button, int colour) {
    TextDrawable d = new TextDrawable(this);
    d.setText(text);
    d.setTextColor(colour);
    d.setTextAlign(Layout.Alignment.ALIGN_CENTER);
    button.setImageDrawable(d);
}

または交互に

private void addText(String text, int buttonID, int colour) {
    TextDrawable d = new TextDrawable(this);
    d.setText(text);
    d.setTextColor(colour);
    d.setTextAlign(Layout.Alignment.ALIGN_CENTER);
    ((ImageButton) findViewById(buttonID)).setImageDrawable(d);
}
于 2013-01-01T17:06:48.010 に答える