แสดงและซ่อนมุมมองพร้อมภาพเคลื่อนไหวสไลด์ขึ้น / ลง


318

ฉันมีสิ่งLinearLayoutที่ฉันต้องการแสดงหรือซ่อนด้วยสิ่งAnimationที่ผลักเลย์เอาต์ขึ้นหรือลงทุกครั้งที่ฉันเปลี่ยนการมองเห็น

ฉันเห็นตัวอย่างเล็ก ๆ น้อย ๆ ที่นั่น แต่ไม่มีตัวอย่างใดที่ตรงกับความต้องการของฉัน

ผมได้สร้างสองไฟล์ XML สำหรับภาพเคลื่อนไหว LinearLayoutแต่ผมไม่ทราบว่าจะเริ่มต้นพวกเขาเมื่อฉันเปลี่ยนการแสดงผลที่

คำตอบ:


639

ด้วย API ภาพเคลื่อนไหวใหม่ที่นำมาใช้ใน Android 3.0 (Honeycomb) มันง่ายมากที่จะสร้างภาพเคลื่อนไหวดังกล่าว

เลื่อนViewลงโดยระยะทาง:

view.animate().translationY(distance);

คุณสามารถเลื่อนViewด้านหลังไปยังตำแหน่งเดิมในลักษณะนี้:

view.animate().translationY(0);

คุณยังสามารถรวมภาพเคลื่อนไหวหลายรายการได้อย่างง่ายดาย ภาพเคลื่อนไหวต่อไปนี้จะเลื่อนViewลงตามความสูงและจางหายไปในเวลาเดียวกัน:

// Prepare the View for the animation
view.setVisibility(View.VISIBLE);
view.setAlpha(0.0f);

// Start the animation
view.animate()
    .translationY(view.getHeight())
    .alpha(1.0f)
    .setListener(null);

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

view.animate()
    .translationY(0)
    .alpha(0.0f)
    .setListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            view.setVisibility(View.GONE);
        }
    });

1
ทำไมมองไม่เห็นเมื่อผ่านไป
Ram

1
ฉันต้องการดูภาพเคลื่อนไหวเมื่อมองเห็นได้และเมื่อไป แต่ถ้าฉันไปดูครั้งแรก. มันไม่สามารถมองเห็นได้และสถานที่ดูว่างเปล่า
Ram

3
@Ram สิ่งที่คุณพยายามที่จะบรรลุโดยการเคลื่อนไหวViewเมื่อตั้งค่าการมองเห็นได้View.GONEหรือไม่ ถ้าคุณตั้งค่าการเปิดเผยเป็นสิ่งที่นอกเหนือจากView.VISIBLEนั้นViewจะมองไม่เห็น ฉันไม่เข้าใจสิ่งที่คุณถาม หากคุณต้องการการเคลื่อนไหวของคุณจะมองเห็นแล้วไม่ได้ตั้งค่าการแสดงผลของการView View.GONE
Xaver Kapeller

2
หันหน้าไปทางปัญหาเดียวกันสิ่งที่หันหน้าไปทางรามในครั้งแรกมันทำงานได้ดี แต่จากครั้งต่อไปเมื่อฉันทำให้มุมมองนั้นในสถานะที่หายไปและพยายามที่จะทำให้มุมมองที่มองเห็นได้อีกครั้งก็ไม่ปรากฏ
Pankaj kumar

12
@ XaverKapeller ฉันคิดว่าปัญหาที่หลายคนมีคือผู้ฟังonAnimationEndเรียกว่าทุกครั้งที่มีภาพเคลื่อนไหวที่เกิดขึ้นหลายครั้งซึ่งหมายความว่าonAnimationEndจะถูกเรียกเช่นกันเมื่อมีการแสดงภาพซึ่งทำให้มองเห็น Gone ได้ ฯลฯ
oldergod

129

ฉันมีปัญหาในการเข้าใจคำตอบที่ยอมรับได้ ฉันต้องการบริบทเพิ่มอีกนิด ตอนนี้ฉันได้คิดออกแล้วนี่เป็นตัวอย่างเต็มรูปแบบ:

ป้อนคำอธิบายรูปภาพที่นี่

MainActivity.java

public class MainActivity extends AppCompatActivity {

    Button myButton;
    View myView;
    boolean isUp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myView = findViewById(R.id.my_view);
        myButton = findViewById(R.id.my_button);

        // initialize as invisible (could also do in xml)
        myView.setVisibility(View.INVISIBLE);
        myButton.setText("Slide up");
        isUp = false;
    }

    // slide the view from below itself to the current position
    public void slideUp(View view){
        view.setVisibility(View.VISIBLE);
        TranslateAnimation animate = new TranslateAnimation(
                0,                 // fromXDelta
                0,                 // toXDelta
                view.getHeight(),  // fromYDelta
                0);                // toYDelta
        animate.setDuration(500);
        animate.setFillAfter(true);
        view.startAnimation(animate);
    }

    // slide the view from its current position to below itself
    public void slideDown(View view){
        TranslateAnimation animate = new TranslateAnimation(
                0,                 // fromXDelta
                0,                 // toXDelta
                0,                 // fromYDelta
                view.getHeight()); // toYDelta
        animate.setDuration(500);
        animate.setFillAfter(true);
        view.startAnimation(animate);
    }

    public void onSlideViewButtonClick(View view) {
        if (isUp) {
            slideDown(myView);
            myButton.setText("Slide up");
        } else {
            slideUp(myView);
            myButton.setText("Slide down");
        }
        isUp = !isUp;
    }
}

activity_mail.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.slideview.MainActivity">

    <Button
        android:id="@+id/my_button"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="100dp"
        android:onClick="onSlideViewButtonClick"
        android:layout_width="150dp"
        android:layout_height="wrap_content"/>

    <LinearLayout
        android:id="@+id/my_view"
        android:background="#a6e1aa"
        android:orientation="vertical"
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="200dp">

    </LinearLayout>

</RelativeLayout>

หมายเหตุ

  • ขอบคุณบทความนี้ที่ชี้ให้ฉันไปในทิศทางที่ถูกต้อง มันมีประโยชน์มากกว่าคำตอบอื่น ๆ ในหน้านี้
  • INVISIBLEถ้าคุณต้องการที่จะเริ่มต้นด้วยมุมมองบนหน้าจอแล้วไม่ได้เริ่มต้นมันเป็น
  • INVISIBLEเนื่องจากเรามีการเคลื่อนไหวได้อย่างสมบูรณ์ปิดหน้าจอมีไม่จำเป็นต้องตั้งมันกลับไป ถ้าคุณไม่ได้เคลื่อนไหวอย่างสมบูรณ์ปิดหน้าจอ AnimatorListenerAdapterแต่แล้วคุณสามารถเพิ่มภาพเคลื่อนไหวอัลฟาและการตั้งค่าการแสดงผลด้วย
  • เอกสารภาพเคลื่อนไหวอสังหาริมทรัพย์

Android: ทัศนวิสัย = "ล่องหน" เพื่อเริ่มต้นนิเมชั่นดูเป็นซ่อน
Goodlife

2
ฉันไม่แนะนำให้ใช้ animate.setFillAfter (จริง); หากคุณมีมุมมองที่คลิกได้ภายใต้มุมมองแบบเลื่อนมันจะไม่เกิดเหตุการณ์อีกเลย
HOCiNE BEKKOUCHE

2
โปรดสังเกตว่าหากไม่มี.setVisibility(View.INVISIBLE);ฟังก์ชั่นเลื่อนขึ้นจะไม่ทำงานตามที่คาดหวัง
Advait S

Translate Animationย้ายมุมมอง หากคุณต้องการเคลื่อนไหวมุมมองแบบปรับขนาดเองให้ใช้ScaleAnimation anim = new ScaleAnimation(1, 1, 0, 1)
Zohab Ali

33

ตอนนี้ภาพเคลื่อนไหวการเปลี่ยนแปลงการมองเห็นควรจะทำผ่านทางTransition APIที่มีอยู่ในแพคเกจสนับสนุน (androidx) เพียงแค่เรียกวิธีการTransitionManager.beginDelayedTransitionด้วยการเปลี่ยนสไลด์แล้วเปลี่ยนการมองเห็นของมุมมอง

ป้อนคำอธิบายรูปภาพที่นี่

import androidx.transition.Slide;
import androidx.transition.Transition;
import androidx.transition.TransitionManager;

private void toggle(boolean show) {
    View redLayout = findViewById(R.id.redLayout);
    ViewGroup parent = findViewById(R.id.parent);

    Transition transition = new Slide(Gravity.BOTTOM);
    transition.setDuration(600);
    transition.addTarget(R.id.redLayout);

    TransitionManager.beginDelayedTransition(parent, transition);
    redLayout.setVisibility(show ? View.VISIBLE : View.GONE);
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="play" />

    <LinearLayout
        android:id="@+id/redLayout"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:background="#5f00"
        android:layout_alignParentBottom="true" />
</RelativeLayout>

ตรวจสอบคำตอบนี้พร้อมกับตัวอย่างการเปลี่ยนค่าเริ่มต้นและแบบกำหนดเองอื่น


@akubi ใช่มันควรจะเป็น
Aba

1
หนึ่งในคำตอบที่ดีที่สุดและง่าย! ขอบคุณ!
krisDrOid

เพียงแค่ต้องทราบนี้ต้องminSdkVersion 21
lasec0203

@ lasec0203 ไม่คลาสมาจากandroidxแพ็คเกจ มันทำงานได้ดีเมื่อวันที่ 21 เมษายนก่อน
ashakirov

: thumbs_up: นี่เป็นการกำจัดข้อผิดพลาดความคลุมเครือของวิธีที่ฉันได้รับ
lasec0203

30

วิธีแก้ปัญหาที่ง่ายที่สุด: ตั้งค่าandroid:animateLayoutChanges="true"บนคอนเทนเนอร์ที่เก็บมุมมองของคุณ

หากต้องการวางไว้ในบริบท: หากคุณมีเลย์เอาต์ด้านล่างการเปลี่ยนแปลงการมองเห็นทั้งหมดในมุมมองในคอนเทนเนอร์นี้จะเป็นภาพเคลื่อนไหวโดยอัตโนมัติ

<LinearLayout android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:animateLayoutChanges="true"
    >

    <Views_which_change_visibility>

</LinearLayout>

คุณสามารถหารายละเอียดเพิ่มเติมเกี่ยวกับสิ่งนี้ได้ในการเปลี่ยนแปลงการเคลื่อนไหวของเค้าโครง - นักพัฒนา Android


มันเป็นวิธีที่ง่ายที่สุด แต่พฤติกรรมของมันแตกต่างกันเนื่องจากผู้ผลิตโทรศัพท์และเขาเปลี่ยนรหัส
b2mob

สิ่งนี้ทำให้แอลฟ่าไม่ใช่ตำแหน่ง
Suragch

ใช่ แต่นั่นคือคำถามเดิมเกี่ยวกับถ้าฉันเข้าใจอย่างถูกต้อง หากคุณต้องการเคลื่อนไหวตำแหน่งคุณสามารถใช้ RecyclerView ที่ใช้ ViewHolders ที่มีรหัสคงที่
Stefan Medack

12

คุณสามารถเริ่มต้นที่ถูกต้องAnimationเมื่อการแสดงผลของLinearLayoutการเปลี่ยนแปลงโดยการสร้างคลาสใหม่LinearLayoutและเอาชนะในการเริ่มต้นsetVisibility() Animationsลองพิจารณาสิ่งนี้:

public class SimpleViewAnimator extends LinearLayout
{
    private Animation inAnimation;
    private Animation outAnimation;

    public SimpleViewAnimator(Context context)
    {
        super(context);
    }

    public void setInAnimation(Animation inAnimation)
    {
        this.inAnimation = inAnimation;
    }

    public void setOutAnimation(Animation outAnimation)
    {
        this.outAnimation = outAnimation;
    }

    @Override
    public void setVisibility(int visibility)
    {
        if (getVisibility() != visibility)
        {
            if (visibility == VISIBLE)
            {
                if (inAnimation != null) startAnimation(inAnimation);
            }
            else if ((visibility == INVISIBLE) || (visibility == GONE))
            {
                if (outAnimation != null) startAnimation(outAnimation);
            }
        }

        super.setVisibility(visibility);
    }
}

1
ฉันชอบวิธี subclass ดีกว่า ขอบคุณมาก.
MichelReap

1
นี่เป็นทางออกที่ยอดเยี่ยมที่ฉันจะนำไปใช้ใน BaseView ของฉัน ขอบคุณสำหรับสิ่งนี้!
Bram Vandenbussche

1
วิธีนี้จะทำงานเมื่อแสดงเมื่อซ่อนมุมมองจะหายไปก่อนที่จะเห็นภาพเคลื่อนไหว วิธีแก้ปัญหาใด ๆ
เบอร์นาร์โด

12
@BramVandenbussche นี่คือทางออกที่น่ากลัว มันทำให้Viewความรับผิดชอบสำหรับภาพเคลื่อนไหวของตัวเองซึ่งเป็นไม่เคยสิ่งที่คุณต้องการ ลองนึกภาพคุณต้องการทำให้ภาพเคลื่อนไหวViewแตกต่างในส่วนอื่นของแอพของคุณ ตอนนี้คุณทำอะไร เพิ่มการตั้งค่าสถานะเพื่อไม่ให้เคลื่อนไหวการมองเห็นโดยอัตโนมัติหรือไม่ ซับคลาสViewและแทนที่setVisibility()เพื่อลบภาพเคลื่อนไหวหรือไม่ หรือแย่กว่านั้นใช้setVisibility()กับอนิเมชั่นอื่น? มันเพิ่งได้รับอัปลักษณ์และอัปลักษณ์จากที่นั่น อย่าใช้ "วิธีแก้ปัญหา" นี้
Xaver Kapeller

3
เรียกมันว่า AnimatedLinearLayout ดีกว่า
Roel

12

Kotlin

จากคำตอบของSuragchต่อไปนี้เป็นวิธีที่สวยงามในการใช้ส่วนขยายการดู:

fun View.slideUp(duration: Int = 500) {
    visibility = View.VISIBLE
    val animate = TranslateAnimation(0f, 0f, this.height.toFloat(), 0f)
    animate.duration = duration.toLong()
    animate.fillAfter = true
    this.startAnimation(animate)
}

fun View.slideDown(duration: Int = 500) {
    visibility = View.VISIBLE
    val animate = TranslateAnimation(0f, 0f, 0f, this.height.toFloat())
    animate.duration = duration.toLong()
    animate.fillAfter = true
    this.startAnimation(animate)
}

และทุกที่ที่คุณต้องการใช้คุณเพียงแค่ต้องการmyView.slideUp()หรือmyView.slideDown()


ข้อผิดพลาดเพียงอย่างเดียวคือมันไม่จำเป็นต้อง "fillAfter = true" เพราะมันบล็อกการเข้าถึงการคลิกเด็กดู
Ranjan

นอกจากนี้คุณอาจจะต้องเพิ่มผู้ฟังไปยังสไลด์แอนิเมชันที่เลื่อนลงและทำให้มุมมองหายไปเมื่อแอนิเมชั่นสิ้นสุด
Manohar Reddy

9
if (filter_section.getVisibility() == View.GONE) {
    filter_section.animate()
            .translationY(filter_section.getHeight()).alpha(1.0f)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    super.onAnimationStart(animation);
                    filter_section.setVisibility(View.VISIBLE);
                    filter_section.setAlpha(0.0f);
                }
            });
} else {
    filter_section.animate()
            .translationY(0).alpha(0.0f)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    filter_section.setVisibility(View.GONE);
                }
            });
}

10
ปัญหาเกี่ยวกับคำตอบนี้: 1) การจัดรูปแบบโค้ดแย่มาก 2) คุณใช้ข้อมูลโค้ดเพื่อโพสต์โค้ดซึ่งไม่สามารถเรียกใช้ในเบราว์เซอร์ได้ สิ่งนี้ไม่เพียงเพิ่มปุ่มที่ไร้ประโยชน์สองปุ่มเท่านั้น แต่ยังทำลายการเน้นไวยากรณ์ 3) มันเป็นเพียงการสุ่มโค้ดแบบสุ่มโดยไม่มีคำอธิบายหรือวัตถุประสงค์ 4) คุณกำลังเปลี่ยนการมองเห็นในขณะที่แสดงภาพเคลื่อนไหว นอกเหนือจากความจริงที่ว่านี่คือกลิ่นรหัสที่ชัดเจนนี้จะไม่ทำงานอย่างถูกต้อง การเปลี่ยนการมองเห็นจะเริ่มต้นกระบวนการเลย์เอาต์ใหม่หลังจากนั้นภาพเคลื่อนไหวจะมีค่าที่ใช้ได้จริง รายการดำเนินไป
เรื่อย ๆ

ฉันได้แก้ไขคำตอบของคุณเพื่อแก้ไขการจัดรูปแบบและเปลี่ยนข้อมูลโค้ดเป็นบล็อกรหัสจริง แต่คุณต้องกรอกข้อมูลส่วนที่เหลือ ...
Xaver Kapeller

ขอโทษที่ทำให้มันเป็นเพื่อนฉันสร้างรหัสจากคุณเพราะมันใช้งานไม่ได้สำหรับฉันรหัสของฉันทำงานได้ แต่การเปลี่ยนแปลงที่จำเป็นในวิธีการโพสต์ฉันเห็นด้วย
Ameen Maheen

@AmeenMaheen มีsetAlphaไว้เพื่ออะไร?
IgorGanapolsky

@ Igor Ganapolsky ใช้เพื่อความโปร่งใสเช่นเพื่อให้เอฟเฟกต์สีซีดจาง
Ameen Maheen

4

คุณสามารถเลื่อนขึ้นหรือลงมุมมองหรือรูปแบบใด ๆ โดยใช้รหัสร้องในแอพ Android

boolean isClicked=false;
LinearLayout mLayoutTab = (LinearLayout)findViewById(R.id.linearlayout);

        if(isClicked){
                    isClicked = false;
                    mLayoutTab.animate()
                    .translationYBy(120)
                    .translationY(0)     
                    .setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));

        }else{
                isClicked = true;
                mLayoutTab.animate()
                .translationYBy(0)
                .translationY(120)
                .setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));
                }

120 คืออะไร และ 0 คืออะไร หน่วยสำหรับ setDuration คืออะไรหากฉันต้องการฮาร์ดโค้ดนี้
santoso สแตนลี่ย์

1
ที่นี่ 120 และ 0 คือระยะทางที่เกี่ยวข้องกับแกน Y หากคุณใส่รหัสยากกว่าการพบปัญหาในหน้าจอหรือแท็บเล็ตขนาดใหญ่ดังนั้นคุณต้องใส่ค่าจากค่า string.xml ของคุณสำหรับอุปกรณ์ที่แตกต่างกันทั้งหมด และระยะเวลาคือเวลาที่คุณต้องการแสดงภาพเคลื่อนไหวของเลย์เอาต์ .... !!! ขอโทษด้วยสำหรับภาษาอังกฤษที่ไม่ดีของฉัน ... !
varotariya vajsi

@varotariyavajsi นี่ไม่ได้แสดง / ซ่อนการเปิดเผยของมุมมอง
IgorGanapolsky

สวัสดี igor ganapolsky ฉันรู้ว่าสิ่งเหล่านี้ ... มันเป็นเพียงการแปลมุมมองในทิศทาง y หากผู้ใช้ต้องการแสดงขึ้นและลงเช่นแถบเลื่อนด้านล่างมันจะทำงานได้ดี
varotariya vajsi

4

ใช้คลาสนี้:

public class ExpandCollapseExtention {

 public static void expand(View view) {
    view.setVisibility(View.VISIBLE);

    final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    view.measure(widthSpec, heightSpec);

    ValueAnimator mAnimator = slideAnimator(view, 0, view.getMeasuredHeight());
    mAnimator.start();
}


public static void collapse(final View view) {
    int finalHeight = view.getHeight();

    ValueAnimator mAnimator = slideAnimator(view, finalHeight, 0);

    mAnimator.addListener(new Animator.AnimatorListener() {

        @Override
        public void onAnimationEnd(Animator animator) {               
            view.setVisibility(View.GONE);
        }


        @Override
        public void onAnimationStart(Animator animation) {

        }


        @Override
        public void onAnimationCancel(Animator animation) {

        }


        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    });
    mAnimator.start();
}


private static ValueAnimator slideAnimator(final View v, int start, int end) {

    ValueAnimator animator = ValueAnimator.ofInt(start, end);

    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {

            int value = (Integer) valueAnimator.getAnimatedValue();
            ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
            layoutParams.height = value;
            v.setLayoutParams(layoutParams);
        }
    });
    return animator;
}
}

3

ใช้ ObjectAnimator

private fun slideDown(view: View) {
    val height = view.height
    ObjectAnimator.ofFloat(view, "translationY", 0.toFloat(), height.toFloat()).apply {
        duration = 1000
        start()
    }
}

private fun slideUp(view: View) {
    val height = view.height
    ObjectAnimator.ofFloat(view, "translationY", height.toFloat(),0.toFloat()).apply {
        duration = 1000
        start()
    }
}

2
การปรับปรุงเล็กน้อย: เราสามารถใช้ View.TRANSLATION_Y คงที่แทน "translationY" และในสไลด์อัพ ObjectAnimation ที่เราสามารถทำได้. ใช้ {doOnEnd {view.visibility = View.GONE} ....... }. start ()
tashi

0.toFloat()ยังสามารถเป็น0f
styler1972

2

ฉันมีกรณีมุมที่ความสูงของมุมมองของฉันยังคงเป็นzeroเช่นนั้น ...

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.view.View;

public final class AnimationUtils {

  public static void slideDown(final View view) {
        view.animate()
                .translationY(view.getHeight())
                .alpha(0.f)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        // superfluous restoration
                        view.setVisibility(View.GONE);
                        view.setAlpha(1.f);
                        view.setTranslationY(0.f);
                    }
                });
    }

    public static void slideUp(final View view) {
        view.setVisibility(View.VISIBLE);
        view.setAlpha(0.f);

        if (view.getHeight() > 0) {
            slideUpNow(view);
        } else {
            // wait till height is measured
            view.post(new Runnable() {
                @Override
                public void run() {
                    slideUpNow(view);
                }
            });
        }
    }

    private static void slideUpNow(final View view) {
        view.setTranslationY(view.getHeight());
        view.animate()
                .translationY(0)
                .alpha(1.f)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        view.setVisibility(View.VISIBLE);
                        view.setAlpha(1.f);
                    }
                });
    }

}

1

นี่คือทางออกของฉัน เพียงรับการอ้างอิงถึงมุมมองของคุณและเรียกวิธีนี้:

public static void animateViewFromBottomToTop(final View view){

    view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {

            view.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            final int TRANSLATION_Y = view.getHeight();
            view.setTranslationY(TRANSLATION_Y);
            view.setVisibility(View.GONE);
            view.animate()
                .translationYBy(-TRANSLATION_Y)
                .setDuration(500)
                .setStartDelay(200)
                .setListener(new AnimatorListenerAdapter() {

                    @Override
                    public void onAnimationStart(final Animator animation) {

                        view.setVisibility(View.VISIBLE);
                    }
                })
                .start();
        }
    });
}

ไม่จำเป็นต้องทำอะไรอีก =)


1
ทำไมคุณต้องใช้ GlobalLayoutListener ในการทำเช่นนี้? ทำไมคุณถึงตั้งค่าการมองเห็นด้วยวิธีแปลก ๆ ? ทำไมคุณรวมถึงสิ่งต่าง ๆ เช่นความล่าช้าในการเริ่มต้นซึ่งไม่เกี่ยวข้องกับคำถามในคำตอบของคุณ
Xaver Kapeller

1

คำตอบของ Suragch ใน Kotlin สิ่งนี้ใช้ได้สำหรับฉัน

class MainActivity : AppCompatActivity() {

var isUp: Boolean = false

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    var myView: View = findViewById(R.id.my_view)
    var myButton: Button = findViewById(R.id.my_button)

    //Initialize as invisible
    myView.visibility = View.INVISIBLE
    myButton.setText("Slide up")

    isUp = false

}


fun View.slideUp(duration: Int = 500){
    visibility = View.VISIBLE
    val animate = TranslateAnimation(0f, 0f, this.height.toFloat(), 0f)
    animate.duration = duration.toLong()
    animate.fillAfter = true
    this.startAnimation(animate)
}

fun View.slideDown(duration: Int = 500) {
    visibility = View.VISIBLE
    val animate = TranslateAnimation(0f, 0f, 0f, this.height.toFloat())
    animate.duration = duration.toLong()
    animate.fillAfter = true
    this.startAnimation(animate)
}

fun onSlideViewButtonClick(view: View){
    if(isUp){
        my_view.slideDown()
        my_button.setText("Slide Up")

    }
    else{
        my_view.slideUp()
        my_button.setText("Slide Down")
    }
    isUp = !isUp
}

}


0

คุณสามารถใช้โค้ดสามบรรทัดอย่างง่ายเพื่อแสดงภาพเคลื่อนไหว ...

//getting the hiding view by animation

 mbinding.butn.setOnClickListener {

                val SlideOutLeft = AnimationUtils.loadAnimation(this, R.anim.slide_out_left)
                simplelayout.visibility = View.INVISIBLE
                simplelayout.startAnimation(SlideOutLeft)


                val SlideInRight = AnimationUtils.loadAnimation(applicationContext, R.anim.slide_in_right)
                animation1.visibility = View.VISIBLE
                animation1.startAnimation(SlideInRight)

            }
            //again unhide the view animation
            mbinding.buttn.setOnClickListener {


               val SlideInLeft=AnimationUtils.loadAnimation(this,R.anim.slide_in_left)
                //set the layout
               simplelayout.visibility=View.VISIBLE
               simplelayout.startAnimation(SlideInLeft)

               val SlideOutRight=AnimationUtils.loadAnimation(this,R.anim.slide_out_right)
               animation1.visibility=View.INVISIBLE
               animation1.startAnimation(SlideOutRight)

            }

0

ด้วยส่วนขยาย Kotlin คุณสามารถใช้สิ่งนี้:

enum class SlideDirection{
    UP,
    DOWN,
    LEFT,
    RIGHT
}

enum class SlideType{
    SHOW,
    HIDE
}

fun View.slideAnimation(direction: SlideDirection, type: SlideType, duration: Long = 250){
    val fromX: Float
    val toX: Float
    val fromY: Float
    val toY: Float
    val array = IntArray(2)
    getLocationInWindow(array)
    if((type == SlideType.HIDE && (direction == SlideDirection.RIGHT || direction == SlideDirection.DOWN)) ||
        (type == SlideType.SHOW && (direction == SlideDirection.LEFT || direction == SlideDirection.UP))   ){
        val displayMetrics = DisplayMetrics()
        val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        windowManager.defaultDisplay.getMetrics(displayMetrics)
        val deviceWidth = displayMetrics.widthPixels
        val deviceHeight = displayMetrics.heightPixels
        array[0] = deviceWidth
        array[1] = deviceHeight
    }
    when (direction) {
        SlideDirection.UP -> {
            fromX = 0f
            toX = 0f
            fromY = if(type == SlideType.HIDE) 0f else (array[1] + height).toFloat()
            toY = if(type == SlideType.HIDE) -1f * (array[1] + height)  else 0f
        }
        SlideDirection.DOWN -> {
            fromX = 0f
            toX = 0f
            fromY = if(type == SlideType.HIDE) 0f else -1f * (array[1] + height)
            toY = if(type == SlideType.HIDE) 1f * (array[1] + height)  else 0f
        }
        SlideDirection.LEFT -> {
            fromX = if(type == SlideType.HIDE) 0f else 1f * (array[0] + width)
            toX = if(type == SlideType.HIDE) -1f * (array[0] + width) else 0f
            fromY = 0f
            toY = 0f
        }
        SlideDirection.RIGHT -> {
            fromX = if(type == SlideType.HIDE) 0f else -1f * (array[0] + width)
            toX = if(type == SlideType.HIDE) 1f * (array[0] + width) else 0f
            fromY = 0f
            toY = 0f
        }
    }
    val animate = TranslateAnimation(
        fromX,
        toX,
        fromY,
        toY
    )
    animate.duration = duration
    animate.setAnimationListener(object: Animation.AnimationListener{
        override fun onAnimationRepeat(animation: Animation?) {

        }

        override fun onAnimationEnd(animation: Animation?) {
            if(type == SlideType.HIDE){
                visibility = View.INVISIBLE
            }
        }

        override fun onAnimationStart(animation: Animation?) {
            visibility = View.VISIBLE
        }

    })
    startAnimation(animate)
}

ตัวอย่างสำหรับการขยาย:

view.slideAnimation(SlideDirection.UP, SlideType.HIDE)//to make it disappear through top of the screen
view.slideAnimation(SlideDirection.DOWN, SlideType.SHOW)//to make it reappear from top of the screen

view.slideAnimation(SlideDirection.DOWN, SlideType.HIDE)//to make it disappear through bottom of the screen
view.slideAnimation(SlideDirection.UP, SlideType.SHOW)//to make it reappear from bottom of the screen

0

หนึ่งในวิธีง่ายๆ:

containerView.setLayoutTransition(LayoutTransition())
containerView.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.