วิธีการบรรลุขอบทับซ้อน / ลบในเค้าโครงข้อ จำกัด ?


119

เป็นไปได้หรือไม่ที่จะบรรลุขอบเชิงลบในรูปแบบข้อ จำกัด เพื่อให้เกิดการทับซ้อนกัน? ฉันพยายามให้รูปภาพอยู่ตรงกลางเค้าโครงและมีมุมมองข้อความเพื่อให้ภาพซ้อนทับกัน a x dp ฉันลองตั้งค่ามาร์จิ้นติดลบ แต่โชคไม่ดี จะดีมากถ้ามีวิธีที่จะทำให้สำเร็จได้


แนวทางอาจช่วยได้ฉันยังไม่ได้ลอง
Eugen Pechanec

คำตอบ:


215

คำชี้แจง:คำตอบด้านล่างยังคงใช้ได้ แต่ฉันต้องการชี้แจงสองสามสิ่ง โซลูชันดั้งเดิมจะวางมุมมองที่มีค่าชดเชยเชิงลบโดยพฤตินัยเทียบกับมุมมองอื่นตามที่ระบุไว้และจะปรากฏในเค้าโครงดังที่แสดง

ทางออกก็คือการใช้translationYคุณสมบัติตามที่แนะนำโดยอาเมียร์ Khorsandi ที่นี่ ฉันชอบวิธีการแก้ปัญหาที่ง่ายกว่าโดยมีข้อแม้เดียว: การแปลเกิดขึ้นหลังการจัดวางดังนั้นมุมมองที่ จำกัด อยู่ที่มุมมองที่ถูกแทนที่จะไม่เป็นไปตามคำแปล

ตัวอย่างเช่น XML ต่อไปนี้จะแสดงTextViewสองรายการที่ด้านล่างของรูปภาพ แต่ละมุมมองจะถูก จำกัด จากบนลงล่างโดยมุมมองที่ปรากฏอยู่ด้านบนทันที

ใส่คำอธิบายภาพที่นี่

<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>

ตอนนี้ขอแปลว่า "ฉันพูดชื่อ" TextViewขึ้น50dpโดยการระบุ

android:translationY="-50dp"

สิ่งนี้ก่อให้เกิดสิ่งต่อไปนี้:

ใส่คำอธิบายภาพที่นี่

TextView "พูดชื่อฉัน" ได้เลื่อนขึ้นตามที่คาดไว้ แต่TextView "พูดเลย" ไม่ได้เป็นไปตามที่เราคาดไว้ เพราะนี่คือการแปลเกิดขึ้นโพสต์รูปแบบ แม้ว่ามุมมองจะย้ายหลังการจัดวาง แต่ก็ยังสามารถคลิกได้ในตำแหน่งใหม่

ดังนั้น IMO ไปกับtranslationXและtranslationYสำหรับระยะขอบติดลบในConstraintLayoutหากข้อแม้ข้างต้นไม่ส่งผลต่อเลย์เอาต์ของคุณ มิฉะนั้นให้ใช้วิดเจ็ตพื้นที่ดังที่ระบุไว้ด้านล่าง


คำตอบเดิม

แม้ว่าจะไม่ได้รับการสนับสนุนขอบลบConstraintLayoutแต่ก็มีวิธีที่จะทำให้เอฟเฟกต์สำเร็จได้โดยใช้เครื่องมือที่พร้อมใช้งานและรองรับ นี่คือภาพที่ชื่อภาพซ้อนทับ22dpจากด้านล่างของภาพ - -22dpระยะขอบอย่างมีประสิทธิภาพ:

ใส่คำอธิบายภาพที่นี่

สิ่งนี้ทำได้โดยใช้Spaceวิดเจ็ตที่มีระยะขอบล่างเท่ากับออฟเซ็ตที่คุณต้องการ วิดเจ็ตนั้นมาได้ด้านล่างของมันบีบบังคับให้ด้านล่างของSpace ImageViewตอนนี้สิ่งที่คุณต้องทำคือ จำกัด ด้านบนของTextViewชื่อภาพที่ด้านล่างของSpaceวิดเจ็ต TextViewจะถูกวางตำแหน่งที่ด้านล่างของSpaceมุมมองละเลยอัตรากำไรขั้นต้นที่ตั้งไว้

ต่อไปนี้คือ XML ที่บรรลุผลนี้ ฉันจะสังเกตว่าฉันใช้Spaceเพราะมันมีน้ำหนักเบาและมีไว้สำหรับการใช้งานประเภทนี้ แต่ฉันสามารถใช้ประเภทอื่นViewและทำให้มองไม่เห็น (คุณอาจจะต้องทำการปรับเปลี่ยนแม้ว่า.) นอกจากนี้คุณยังสามารถกำหนดViewมีอัตรากำไรที่ศูนย์และความสูงของขอบภาพประกอบที่คุณต้องการและข้อ จำกัด ด้านบนของด้านบนของสิ่งที่ใส่เข้าไปที่TextViewView

อีกวิธีหนึ่งคือการวางซ้อนทับTextViewด้านบนImageViewโดยจัดแนวท็อปส์ / ก้น / ซ้าย / ขวาและทำการปรับเปลี่ยนระยะขอบ / ช่องว่างภายในให้เหมาะสม ประโยชน์ของแนวทางที่แสดงด้านล่างนี้คือสามารถสร้างขอบลบได้โดยไม่ต้องคำนวณมากนัก กล่าวคือมีหลายวิธีในการเข้าถึงสิ่งนี้

ปรับปรุง:สำหรับการอภิปรายอย่างรวดเร็วและการสาธิตของเทคนิคนี้ให้ดูที่ Google Developers กลางบล็อกโพสต์

ขอบลบสำหรับConstraintLayoutXML

<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>

ไม่ได้ทำงานในกรณีของฉันImageViewเป็นศูนย์กลางในการปกครองการทับซ้อนดังกล่าวข้างต้นTextView ImageViewจากนั้นSpaceทำให้เกิดข้อผิดพลาดเมื่อแอปกลับจากพื้นหลัง ฉันคิดว่า 0dp, 0dp ทำให้เกิดปัญหา Guidelineสิ่งที่เกี่ยวกับการใช้งานเพียงแค่
illusionJJ

วิธีนี้ใช้ไม่ได้กับมุมมองที่มีข้อ จำกัด กับผู้ปกครอง
R4j

ทำไมฉันต้องมี Space? ฉันลองโดยไม่มีช่องว่างและก็ได้ผลลัพธ์แบบเดียวกัน
kuzdu

@kuzdu ประเด็นตรงนี้คือด้านล่างของช่องว่างถูก จำกัด ที่ด้านล่างของ imageView ระยะขอบจะเลื่อนช่องว่างขึ้นจากนั้นด้านบนของมุมมองข้อความจะถูก จำกัด ที่ด้านล่างของช่องว่างซึ่งจะสร้าง "การซ้อนทับครึ่งหนึ่งนี้ "ผลที่เราพยายามทำให้สำเร็จ โปรดโพสต์คำตอบที่นี่หากคุณได้รับมันโดยไม่มีช่องว่างเพื่อให้เราเห็นข้อ จำกัด ที่คุณใช้กับสองมุมมองของคุณ
Lucas P.

62

อีกวิธีหนึ่งคือการใช้translationXหรือtranslationYเช่นนี้:

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

มันจะทำงานเหมือน android:layout_marginRight="-25dp"


29
โปรดทราบเรื่องนี้เนื่องจากตำแหน่งจริงของมุมมองยังคงอยู่ที่ตำแหน่งเดิม (ก่อนการแปล) จึงจะแปลด้วยภาพเท่านั้น ดังนั้นเหตุการณ์ onClick จะถูกทริกเกอร์จากในตำแหน่งเดิมเท่านั้น
goemic

คำกล่าวของ @ goemic ดูเหมือนจะผิดเนื่องจากนี่ไม่ใช่แอนิเมชั่นทวีต แต่เป็นแอนิเมชั่นคุณสมบัติ (โปรดแก้ไขฉันถ้าฉันผิด)
Henry

การปฏิบัติที่ไม่ดีเนื่องจากไม่รองรับรูปแบบ RTL
Salam El-Banna

27

อัตรากำไรเชิงลบไม่เคยได้รับการสนับสนุนอย่างเป็นทางการใน RelativeLayout ไม่รองรับระยะขอบเชิงลบใน ConstraintLayout [... ]

- Romain Guy เมื่อวันที่ 8 มิ.ย. 2559

ปฏิบัติตามสองประเด็นนี้:

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


แนวคิดของพวกเขาอาจเป็นไปได้ว่าด้วยรูปแบบที่ จำกัด คุณไม่จำเป็นต้องมีขอบลบ ซึ่งอาจเป็นจริงหากคุณมีองค์ประกอบทั้งหมดในเค้าโครงเดียว บางครั้งแม้ว่าคุณต้องการจัดกลุ่มองค์ประกอบเชิงตรรกะเช่นในแถบคำสั่งที่ทำจากปุ่มซึ่งมีข้อดีในตัวเองสำหรับการใช้ซ้ำและความชัดเจนและการห่อหุ้ม เมื่อถึงจุดนั้นกลุ่มจะมีรูปร่างเป็นสี่เหลี่ยมผืนผ้าและข้อ จำกัด ของรูปร่างนั้นทำให้ระยะขอบเชิงลบมีประโยชน์และจำเป็นอีกครั้ง
AndrewBloom

ระยะขอบเชิงลบเลียนแบบแนวคิดเดียวกันกับพื้นฐานของข้อความโดยเป็นข้อความที่มีรูปร่างซับซ้อนภายในภาชนะสี่เหลี่ยม
AndrewBloom

15

นี่คือสิ่งที่ฉันคิดได้หลังจากพยายามหาวิธีแก้ปัญหามาหลายชั่วโมง

ให้เราพิจารณาสองภาพ image1 และ image2 Image2 จะถูกวางไว้ที่ด้านบนของ image1 ในตำแหน่งทางด้านขวาล่าง

ตัวอย่างมุมมองที่ทับซ้อนกัน ภาพ

เราสามารถใช้วิดเจ็ตSpaceสำหรับมุมมองที่ทับซ้อนกัน

จำกัด ทั้งสี่ด้านของวิดเจ็ต Space กับด้านทั้งสี่ของรูปภาพ 1 ตามลำดับ สำหรับตัวอย่างนี้ จำกัด ด้านซ้ายของ image2 ด้วยด้านขวาของวิดเจ็ต Space และด้านบนของ image2 กับด้านล่างของวิดเจ็ต Space สิ่งนี้จะผูก image2 กับวิดเจ็ต Space และเนื่องจากวิดเจ็ต Space ถูก จำกัด จากทุกด้านเราจึงสามารถกำหนดอคติแนวนอนหรือแนวตั้งที่ต้องการซึ่งจะย้าย image2 ตามต้องการ

<?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>

นอกจากนี้ในการวางตำแหน่ง image2 ที่กึ่งกลางด้านล่างของ image1 เราสามารถ จำกัด ด้านซ้ายและขวาของ image2 ด้วย Space widget ด้านซ้ายและขวาตามลำดับ ในทำนองเดียวกันเราสามารถวาง image2 ได้ทุกที่โดยเปลี่ยนข้อ จำกัด ของ image2 ด้วยวิดเจ็ต Space


ขอบคุณสำหรับคำตอบ!
user3193413

11

ฉันพบวิธีที่ง่ายกว่านี้มาก

โดยทั่วไปจะมี ImageView จากนั้นในมุมมองข้อความให้เพิ่มข้อ จำกัด ด้านบนเพื่อให้ตรงกับข้อ จำกัด ด้านบนของรูปภาพและเพิ่มระยะขอบด้านบนของ TextView เพื่อจับคู่เพื่อให้ได้ลักษณะการทำงานของประเภทระยะขอบ -ve


9
เว้นแต่ความสูงของภาพจะแปรผัน
Stas Shusha

มันจะยังคงทำงาน คุณเพียงแค่ต้องระวังว่าคุณต้องการให้วิดเจ็ตส่วนบนของคุณวางซ้อนภาพที่ใดการตั้งค่าระยะขอบจากด้านขวาหรือด้านล่างอาจเป็นตัวเลือกที่ดีกว่าหรือคุณอาจใช้อคติซึ่งทั้งหมดนี้ตอบคำถามได้ .
Gabriel Vasconcelos

4

ซึ่งจะช่วยหลาย ๆ

ในกรณีของฉันฉันต้องการการออกแบบของฉันเช่นนี้:

หลังจาก

หมายความว่าฉันต้องการให้รูปภาพของฉันแสดงผลครึ่งหนึ่งของความกว้างดังนั้นโดยพื้นฐานแล้วฉันต้องการระยะขอบเชิงลบของครึ่งหนึ่งของความกว้างของภาพจริง แต่เลย์เอาต์ทั้งหมดของฉันในเลย์เอาต์ที่ จำกัด และเลย์เอาต์ข้อ จำกัด ไม่อนุญาตให้มีขอบติดลบดังนั้นฉันจึงทำได้ด้วยโค้ดด้านล่าง

<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>

ดังนั้น ImageView จะสิ้นสุดที่จุดเริ่มต้นของแนวทาง และผลกระทบจะเหมือนกับระยะขอบติดลบที่จุดเริ่มต้น 50dp

และหากความกว้างของมุมมองของคุณไม่ได้รับการแก้ไขและเป็นเปอร์เซ็นต์เพื่อให้คุณสามารถวางแนวทางด้วยเปอร์เซ็นต์และบรรลุผลตามที่คุณต้องการ

Happy Coding :)


0

คุณต้องใช้วิดเจ็ต Space ในเลย์เอาต์ของคุณเท่านั้น

<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

นี่เป็นคำถามเก่าที่ยังถูกถามกันมากวิธีที่เร็วที่สุดในการบรรลุเป้าหมายนี้คือการ จำกัด ด้านบนและด้านล่างไว้ที่ด้านข้างของมุมมองที่คุณต้องการยึดไว้ดังนี้:

        <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" />

ซึ่งจะจัดกึ่งกลางไว้ที่บรรทัดล่างสุดของมุมมองโดยจัดกึ่งกลางในแนวนอน


-1

วิธีง่ายๆ

ฉันไม่แน่ใจว่าวิธีที่ดีที่สุด

เพียงห่อโดยใช้ LinearLayout

<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>

สิ่งนี้เพิ่มการซ้อนกันเล็กน้อย แต่ใช้ได้กับการสร้างภาพเคลื่อนไหวจากมุมมองด้านบนซึ่งแตกต่างจากโซลูชันอื่น ๆ ที่นี่ซึ่งสมมติว่ามุมมองจะแสดงอย่างสมบูรณ์ ขอบคุณ!
Leo สนับสนุน Monica Cellio

2
คำตอบนี้ต้องการข้อมูลเพิ่มเติมจำนวนมาก ไม่ชัดเจนว่าการวางบางสิ่งใน LinearLayout สามารถใช้เพื่อทำให้เกิดการทับซ้อนกันได้อย่างไร
Robert Liberatore
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.