Kısıt Düzeni'nde örtüşme / negatif marj nasıl elde edilir?


118

Örtüşmeyi sağlamak için sınırlama düzeninde negatif kenar boşluğu elde etmek mümkün mü? Düzende ortalanmış bir görüntüye sahip olmaya ve a x dp ile örtüşecek şekilde bir Metin görünümüne sahip olmaya çalışıyorum. Negatif marj değeri ayarlamayı denedim ama şans yok. Bunu başarmanın bir yolu varsa harika olur.


Kılavuz yardımcı olabilir, denemedim.
Eugen Pechanec

Yanıtlar:


214

Açıklama: Aşağıdaki cevap geçerliliğini koruyor, ancak birkaç şeyi açıklığa kavuşturmak istiyorum. Orijinal çözüm, belirtildiği gibi başka bir görünüme göre fiili bir negatif ofseti olan bir görünüm yerleştirecek ve gösterildiği gibi düzende görünecektir.

Başka bir çözüm kullanmaktır ÇeviriY Amir Khorsandi tarafından önerildiği gibi özellik burada . Tek bir uyarı ile bu çözümü daha basit tercih ediyorum: Çeviri, mizanpaj sonrası gerçekleşir , bu nedenle yer değiştiren görünümle sınırlandırılan görünümler çeviriyi takip etmeyecektir.

Örneğin, aşağıdaki XML , görüntünün hemen altında iki TextView görüntüler . Her görünüm, hemen üzerinde görünen görünümle yukarıdan aşağıya sınırlandırılmıştır.

görüntü açıklamasını buraya girin

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:tint="#388E3C"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_action_droid" />

    <TextView
        android:id="@+id/sayName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Say my name."
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintTop_toBottomOf="@+id/imageView"
        app:layout_constraintEnd_toEndOf="@+id/imageView"
        app:layout_constraintStart_toStartOf="@+id/imageView" />

    <TextView
        android:id="@+id/sayIt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Say it."
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintEnd_toEndOf="@+id/sayName"
        app:layout_constraintStart_toStartOf="@+id/sayName"
        app:layout_constraintTop_toBottomOf="@id/sayName" />
</androidx.constraintlayout.widget.ConstraintLayout>

Şimdi, "Adımı söyle" TextView öğesini50dp belirterek yukarı çevirelim

android:translationY="-50dp"

Bu, aşağıdakileri üretir:

görüntü açıklamasını buraya girin

"Adımı söyle" TextView beklendiği gibi yükseldi, ancak "Söyle" TextView beklediğimiz gibi onu takip etmedi. Bunun nedeni, çevirinin düzen sonrası gerçekleşmesidir . Görünüm yerleşim sonrası hareket etse de, yeni konumda yine de tıklanabilir hale getirilebilir.

Öyleyse, yukarıdaki uyarı mizanpajınızı etkilemiyorsa , IMO, ConstraintLayout'ta negatif kenar boşlukları için translationX ve translationY ile gidin ; aksi takdirde, aşağıda belirtildiği gibi boşluk widget'ını kullanın.


Orijinal cevap

Negatif kenar boşluklarının destekleneceği görünmese ConstraintLayoutde, mevcut ve desteklenen araçları kullanarak efekti gerçekleştirmenin bir yolu vardır. İşte görsel başlığının görüntünün 22dpaltından örtüştüğü bir görüntü - etkili bir şekilde bir -22dpkenar boşluğu:

görüntü açıklamasını buraya girin

Bu, Spaceistediğiniz uzaklığa eşit bir alt kenar boşluğuna sahip bir pencere öğesi kullanılarak gerçekleştirildi . SpaceDaha sonra, widget dibine kısıtlı dibini vardır ImageView. Şimdi yapmanız gereken tek şey, TextViewresim başlığıyla birlikte üst kısmını Spacewidget'ın alt kısmıyla sınırlamaktır . , Sayfanın TextViewaltında konumlandırılacaktır.Space ayarlandı marjı göz ardı görünümü.

Aşağıdaki, bu etkiyi gerçekleştiren XML'dir. SpaceHafif olduğu ve bu tür bir kullanım için tasarlandığından kullandığımı not edeceğim , ancak başka bir tür kullanıp Viewgörünmez yapabilirdim. (Muhtemelen olsa ayarlamalar yapmak gerekir.) Ayrıca bir tanımlayabiliriz Viewsıfır marjlarına ve istediğiniz gömme marjının yüksekliği ile ve üst sınırlamak TextViewyerleşsin üstüne View.

Bir diğer yaklaşım bindirmek için olacağını TextViewüstünde ImageViewüstleri / dipleri / kere sola / sağa ve marjlar uygun ayarlamalar yapmak / dolgu hizalayarak. Aşağıda gösterilen yaklaşımın faydası, çok fazla hesaplama yapılmadan negatif bir marjın yaratılabilmesidir. Hepsi bu, buna yaklaşmanın birkaç yolu olduğunu söylemek içindir.

Güncelleme: Bu tekniğin hızlı bir tartışması ve demosu için Google Developers Medium blog gönderisine bakın .

ConstraintLayoutXML için Negatif Marj

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@mipmap/ic_launcher" />

    <android.support.v4.widget.Space
        android:id="@+id/marginSpacer"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="22dp"
        app:layout_constraintBottom_toBottomOf="@+id/imageView"
        app:layout_constraintLeft_toLeftOf="@id/imageView"
        app:layout_constraintRight_toRightOf="@id/imageView" />

    <TextView
        android:id="@+id/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Say my name"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/marginSpacer" />
</android.support.constraint.ConstraintLayout>

Benim durumumda çalışmıyor ImageView, üst TextViewüste odaklanıyor, üst üste biniyor ImageView. Ardından SpaceUygulama arka plandan döndüğünde hata veriyor. Bence 0dp, 0dp biraz sorun çıkarıyor. Ya sadece kullan Guideline.
illusionJJ

Bu yol, görünüm için çalışamaz, ebeveyn ile kısıtlamalara sahiptir.
R4j

Neden bir Alana ihtiyacım var? Boşluksuz denedim ve aynı sonucu aldım.
kuzdu

@kuzdu buradaki nokta, alanın alt kısmının imageView'in altında sınırlandırılması, kenar boşluğunun alanı yukarı hareket ettirmesi ve ardından metin görünümünün üst kısmının, bu "yarı örtüşmeyi oluşturan alanın alt kısmında kısıtlanmasıdır. "elde etmeye çalıştığımız etki. İki görünümünüzde kullandığınız kısıtlamaları görebilmemiz için boşluk olmadan almayı başardıysanız lütfen buraya bir yanıt gönderin.
Lucas P.

Sen Heisenberg'sin ...
Nahro

62

Başka bir yol kullanmak translationXveya bunun translationYgibi:

  <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" 
                android:translationX="25dp"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"/>

gibi çalışacak android:layout_marginRight="-25dp"


29
Bunun farkında olun, görünümün gerçek konumu orijinal konumunda kaldığından (çeviriden önce), yalnızca görsel olarak çevrilecektir. Bu nedenle, onClick olayları yalnızca eski konumun içinden tetiklenecektir.
goemic

@ goemic'in ifadesi yanlış görünüyor, çünkü bu bir ara animasyon değil, bir özellik animasyonu. (yanılıyorsam lütfen beni düzeltin)
Henry

RTL düzenlerini desteklemediği için kötü uygulama
Salam El-Banna

27

Negatif marjlar, RelativeLayout'ta hiçbir zaman resmi olarak desteklenmemiştir. Negatif kenar boşlukları, ConstraintLayout'ta desteklenmeyecektir. [...]

- Romain Guy 8 Haz 2016'da

Şu iki konuyu izleyin:

https://code.google.com/p/android/issues/detail?id=212499 https://code.google.com/p/android/issues/detail?id=234866


onların fikirleri, kısıtlama düzeni ile negatif marjlara ihtiyacınız olmadığı olabilir. Tüm öğelere tek bir düzende sahipseniz bu doğru olabilir. Bazen, yeniden kullanılabilirlik, netlik ve kapsülleme için kendi avantajları olan düğmelerden oluşan bir komut şeridinde olduğu gibi mantıksal olarak öğeleri gruplamak isteseniz de. Bu noktada grup dikdörtgen bir şekle sahip olacaktır ve negatif kenar boşluklarını tekrar faydalı ve gerekli kılan bu şekildeki sınırlamadır.
AndrewBloom

Negatif kenar boşlukları, metindeki temel
çizginin

14

Bir çözüm bulmaya çalıştıktan saatler sonra anladığım şey buydu.

İki resmi ele alalım, image1 ve image2. Image2, sağ alt taraftaki image1'in üstüne yerleştirilecektir.

Çakışan Görünümler Örneği görüntü

Örtüşen görünümler için Space widget'ı kullanabiliriz .

Boşluk widget'ının dört kenarını sırasıyla görüntünün dört kenarıyla sınırlayın1. Bu örnek için, image2'nin sol tarafını Boşluk widget'ının sağ tarafıyla ve image2'nin üst tarafını Boşluk widget'ının alt tarafıyla sınırlayın. Bu, image2'yi Space widget'ına bağlayacaktır ve Space widget'ı her yönden kısıtlandığından, image2'yi gerektiği gibi hareket ettirecek gerekli yatay veya dikey eğilimi tanımlayabiliriz.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Player">
 <ImageView
     android:id="@+id/image1"
     android:layout_width="250dp"
     android:layout_height="167dp"
     android:src="@android:color/holo_green_dark"
     app:layout_constraintEnd_toEndOf="parent"
     app:layout_constraintStart_toStartOf="parent"
     app:layout_constraintTop_toTopOf="parent" />
 <Space
     android:id="@+id/space"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     app:layout_constraintBottom_toBottomOf="@+id/image1"
     app:layout_constraintEnd_toEndOf="@+id/image1"
     app:layout_constraintHorizontal_bias="0.82"
     app:layout_constraintStart_toStartOf="@+id/image1"
     app:layout_constraintTop_toTopOf="@+id/image1"
     app:layout_constraintVertical_bias="0.62" />
 <ImageView
     android:id="@+id/image2"
     android:layout_width="82dp"
     android:layout_height="108dp"
     android:src="@android:color/holo_green_light"
     app:layout_constraintStart_toEndOf="@+id/space"
     app:layout_constraintTop_toBottomOf="@+id/space" />
 </android.support.constraint.ConstraintLayout>

Ek olarak, image2'yi image1'in orta-altında konumlandırmak için, image2'nin sol ve sağ taraflarını sırasıyla Space widget'ın sol ve sağ taraflarıyla sınırlayabiliriz. Benzer şekilde, image2'nin kısıtlamalarını Space widget ile değiştirerek image2'yi herhangi bir yere yerleştirebiliriz.


Cevap için teşekkür ederim!
user3193413

11

Bunu çok daha basit yapmanın bir yolunu buldum.

Temel olarak ImageView'a sahip olun, ardından Metin Görünümü'nde görüntünün en üst sınırlamasına uyması için en üst sınırlamayı ekleyin ve -ve kenar boşluğu türü davranışını elde etmek için eşleşecek şekilde TextView'in üst kenar boşluğunu ekleyin.


9
resim yüksekliği değişken olmadığı sürece
Stas Shusha

Hala işe yarayacaktı. Sadece üst widget'ınızın görüntüyü nereye bindirmesini istediğinize dikkat etmeniz gerekir, kenar boşluğunu sağdan veya alttan ayarlamak daha iyi bir seçenek olabilir veya önyargı kullanabilirsiniz, bunların hepsi soruyu yanıtlar. .
Gabriel Vasconcelos

4

Bu birçok kişiye yardımcı olacak

Benim durumumda tasarımımı şöyle istiyorum:

sonra

Resmimin genişliğinin yarısını göstermesini istediğim anlamına gelir, bu nedenle temelde gerçek görüntü genişliğinin yarısı kadar negatif kenar boşluğuna ihtiyacım var, ancak kısıtlama düzenindeki ve kısıtlama düzenindeki tüm düzenim negatif kenar boşluğuna izin vermiyor, bu yüzden bunu aşağıdaki kodla başardım

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_launcher_background"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/guideline"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="50dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

Böylece ImageView kılavuzun başlangıcında sona erecektir. ve etki 50 dp'nin başlangıcındaki negatif marjla aynıdır.

Ayrıca, görünümünüzün genişliği sabit değilse ve yüzde cinsinden ise kılavuz çizgisini yüzde ile yerleştirebilir ve istediğiniz efekti elde edebilirsiniz.

Mutlu Kodlama :)


0

Düzeninizde yalnızca Uzay widget'ını kullanmanız gerekir

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<Space
    android:id="@+id/negative_margin"
    android:layout_width="16dp"
    android:layout_height="16dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintRight_toLeftOf="parent"/>

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Widget who needs negative margin"
    app:layout_constraintTop_toBottomOf="@+id/negative_margin"
    app:layout_constraintLeft_toLeftOf="@+id/negative_margin" />


0

Bu eski bir sorudur, ancak çok sorulmuştur, bunu başarmanın en hızlı yolu, aşağıdaki gibi, sabitlemek istediğiniz görüntünün üstünü ve altını sınırlamaktır:

        <androidx.appcompat.widget.AppCompatImageView
        android:layout_width="55dp"
        android:layout_height="55dp"
        app:layout_constraintBottom_toBottomOf="@+id/parent_view_id"
        app:layout_constraintTop_toBottomOf="@+id/parent_view_id"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent" />

Bu, onu yatay olarak ortalayarak görünümün alt satırında ortalayacaktır.


-1

Basit Bir Yol.

En iyi yoldan emin değilim.

LinearLayout kullanarak kaydırmanız yeterli

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
 <View
 android:layout_width="wrap_content"
 android:layout_marginLeft="-20dp"
 android:layout_height="wrap_content"/>
</LinearLayout>

Bu, biraz daha fazla iç içe geçme ekler, ANCAK buradaki diğer çözümlerin aksine, Görünümün tamamen gösterileceğini varsayan görünümleri yukarıdan canlandırmak için çalışır. Teşekkürler!
Leo Monica Cellio'yu destekliyor

2
Bu yanıtın çok daha fazla bilgiye ihtiyacı var. Bir LinearLayout'a bir şey koymanın örtüşmeyi başarmak için nasıl kullanılabileceği açık değil.
Robert Liberatore
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.