web-dev-qa-db-ja.com

Androidでマイナスのマージンを使用するのは悪い習慣ですか?

負のマージンのデモ:

enter image description here

シナリオ

別のビューの境界ボックスに侵入するように、ビューの1つに負のマージンを設定して、ビューをオーバーラップします。

考え

レイアウトが重複している場合、期待どおりに機能するようです。しかし、無意識のうちに物事を正しく行わないために、より大きな問題に遭遇したくありません。エミュレーター、物理デバイス、名前を付けます。負のマージンを使用すると、すべてが正常に動作するように見えます。あるビューは別のビューの境界ボックスに侵入し、レイアウトで宣言されている方法に応じて、他のビューの上または下になります。

また、API 21以降、 translationZ および elevation 属性を設定して、ビューを他のビューの上または下に表示できるが、私の懸念基本的に、 ドキュメント内layout_margin属性に対してマージン値は正でなければなりませんであることが明確に指定されているという事実から来ています。

抜粋:
このビューの左、上、右、下側の余分なスペースを指定します。このスペースは、このビューの境界の外側にあります。 マージン値は正でなければなりません。ディメンション値である必要があります。これは、「14.5sp」などの単位が追加された浮動小数点数です。使用可能な単位は、px(ピクセル)、dp(密度に依存しないピクセル)、sp(優先フォントサイズに基づいてスケーリングされたピクセル)、in(インチ)、mm(ミリメートル)...

もともとこの質問をしてから何年もの間、私は負のマージンに問題がなかったので、可能な限り使用しないようにしましたが、not問題が発生しました。それ、私はそれについてあまり心配していません。

104
Juan Cortés

2010年、@ RomainGuy(コアAndroidエンジニア)は、 負のマージンには不特定の動作があった と述べました。

2011年、@ RomainGuyは LinearLayoutおよびRelativeLayoutに負のマージンを使用できます と述べました。

2016年、@ RomainGuyは、 正式にサポートされたことはなく、ConstraintLayoutによってサポートされない と述べました。

ただし、この制限を回避するのは簡単です。

ベースビューの下部にヘルパービュー(高さ0dp、幅を親に制限)を追加し、下部に必要なマージンを追加します。
次に、ビューをこのビューの下に配置し、サポートされていない負の値を使用せずに、事実上「負の」マージンを持つようにします。

174
CommonsWare

負のマージンを使用する場合は、コンテナとそのclipToPaddingに十分なパディングをfalseに設定し、子ビューにクリップしないようにその子に負のマージンを設定します!

15
Ali

これが誰かを助けることを願っています。 @CommonsWareの回答に基づいて ConstraintLayout を使用したサンプルコードを次に示します。

ベースビューの下部にヘルパービュー(高さ0dp、幅を親に制限)を追加し、下部に必要なマージンを追加します。次に、ビューをこのビューの下に配置し、サポートされていない負の値を使用せずに、事実上「負の」マージンを持つようにします。

サンプルコード:

<TextView
    Android:id="@+id/below"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:background="#F1B36D"
    Android:padding="30dp"
    Android:text="I'm below"
    Android:textColor="#ffffff"
    Android:textSize="48sp"
    Android:textAlignment="center"
    tools:layout_editor_absoluteX="129dp"
    tools:layout_editor_absoluteY="0dp" />

<Android.support.v4.widget.Space
    Android:id="@+id/space"
    Android:layout_width="0dp"
    Android:layout_height="0dp"
    Android:layout_marginBottom="32dp"
    app:layout_constraintBottom_toBottomOf="@+id/below"
    app:layout_constraintLeft_toLeftOf="@id/below"
    app:layout_constraintRight_toRightOf="@id/below" />

<TextView
    Android:id="@+id/top"
    Android:layout_width="100dp"
    Android:layout_height="60dp"
    Android:textAlignment="center"
    Android:textColor="#ffffff"
    Android:text="I'M ON TOP!"
    Android:background="#676563"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/space" />

出力:

enter image description here

11
VicJordan

過去には悪い習慣だったかもしれませんが、マテリアルデザインとそのフローティングアクションボタンを使用すると、多くの場合、避けられず必要になるようです。基本的に、明確に別々の処理が必要なために単一のRelativeLayoutに入れることができない2つの個別のレイアウトがある場合(たとえば、ヘッダーとコンテンツを考える)、FABをオーバーラップさせる唯一の方法は、それらの1つから突き出すことです負のマージンを使用するレイアウト。そして、これはクリック可能な領域で追加の問題を作成します。

4
Gábor

私にとって、そしてTextViewで負のマージンを設定することについて(私はOPがViewGroupを参照していることを理解していますが、負のマージンを設定する問題を探していて、ここに着陸しました)... 4.0.3で問題を見つけました( API 15)のみおよびAndroid:layout_marginTopまたはAndroid:layout_marginBottomを-2dpなどの負の値に設定します。

何らかの理由で、TextViewがまったく表示されません。ビューから「消えた」ように見えます(目に見えないだけではありません)。

Layout_marginの他の3つのバージョンでこれを試しても、問題は見られませんでした。

実際のデバイスではこれを試していませんが、これは4.0.3エミュレータを使用していることに注意してください。これは、4.0.3にのみ影響することがわかった2番目の奇妙なことなので、私の新しいルールは 常に 4.0.3エミュレータでテストします:)

私はたまたまAndroid:lineSpacingExtra="-2dp"を持っていても動作するAndroid:singleLine="true"を使用してTextViewの下マージンを減らすことに成功しています(したがって、行間が要因になるとは思わなかったでしょう)。

3
GaryAmundson

いいえ、negative marginを使用しないでください。代わりにtranslateを使用する必要があります。負のマージンがいつか機能する場合でも、レイアウトをプログラムで変更すると、翻訳が役立ちます。また、マージンを使用すると、ビューが画面からあふれることはありません。

2
Cheung Sean

私はそれがかなり短期間しか可能でなかったことを知っていました。しかし、私はそれで問題が見られません。画面サイズなどに注意するだけで、画面上で重なって表示されるべきではないアイテムを誤って作成しないようにできます。 (つまり、テキストの上にあるテキストは、おそらく悪い考えです。)

0
FoamyGuy