Android CollapsingToolbarLayout ยุบ Listener


106

ฉันใช้CollapsingToolBarLayoutควบคู่ไปกับAppBarLayoutและCoordinatorLayoutและพวกเขากำลังทำงานได้ดีทั้งหมด ฉันตั้งค่าToolbarเป็นค่าคงที่เมื่อเลื่อนขึ้นฉันต้องการทราบว่ามีวิธีเปลี่ยนข้อความชื่อเรื่องของ Toolbar หรือไม่เมื่อCollapsingToolBarLayoutมีการยุบ

ห่อผมต้องการที่แตกต่างกันสองชื่อเมื่อเลื่อนและเมื่อขยาย

ขอขอบคุณทุกท่านล่วงหน้า

คำตอบ:


150

ฉันแบ่งปันการใช้งานแบบเต็มตามรหัส @Frodio Beggins และ @Nifhel:

public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {

    public enum State {
        EXPANDED,
        COLLAPSED,
        IDLE
    }

    private State mCurrentState = State.IDLE;

    @Override
    public final void onOffsetChanged(AppBarLayout appBarLayout, int i) {
        if (i == 0) {
            if (mCurrentState != State.EXPANDED) {
                onStateChanged(appBarLayout, State.EXPANDED);
            }
            mCurrentState = State.EXPANDED;
        } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
            if (mCurrentState != State.COLLAPSED) {
                onStateChanged(appBarLayout, State.COLLAPSED);
            }
            mCurrentState = State.COLLAPSED;
        } else {
            if (mCurrentState != State.IDLE) {
                onStateChanged(appBarLayout, State.IDLE);
            }
            mCurrentState = State.IDLE;
        }
    }

    public abstract void onStateChanged(AppBarLayout appBarLayout, State state);
}

จากนั้นคุณสามารถใช้งานได้:

appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() {
    @Override
    public void onStateChanged(AppBarLayout appBarLayout, State state) {
        Log.d("STATE", state.name());
    }
});

21
ถูกต้อง. แต่โปรดอย่าว่าการใช้ Proguard ที่ enum จะถูกแปลเป็นค่าจำนวนเต็ม
rciovati

1
ฉันไม่รู้เรื่องนั้น เยี่ยมมาก!
tim687

2
นอกจากนี้ enums ยังเป็นวิธีที่ดีมากในการรับประกันความปลอดภัย คุณไม่สามารถมี State.IMPLODED ได้เนื่องจากไม่มีอยู่ (คอมไพเลอร์จะบ่น) แต่ด้วยค่าคงที่จำนวนเต็มคุณสามารถใช้ค่าที่คอมไพลเลอร์ไม่มีความคิดว่าผิด พวกเขาทำได้ดีในฐานะเสื้อกล้าม แต่นั่นก็เป็นอีกเรื่องหนึ่ง
droppin_science

@droppin_science สำหรับ android enums ตรวจสอบIntDef
David Darias

1
@DavidDarias โดยส่วนตัวแล้วฉันพบว่าวิธีการที่สะอาดกว่ามากแม้จะมีค่าใช้จ่าย (เริ่มการโต้แย้งที่นี่ ... :-)
droppin_science

95

วิธีนี้ใช้ได้ผลอย่างสมบูรณ์สำหรับฉันในการตรวจจับการAppBarLayoutยุบหรือขยาย

appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {

            if (Math.abs(verticalOffset)-appBarLayout.getTotalScrollRange() == 0)
            {
                //  Collapsed


            }
            else
            {
                //Expanded


            }
        }
    });

ใช้addOnOffsetChangedListenerกับAppBarLayout.


36

เชื่อมOnOffsetChangedListenerต่อกับAppBarLayoutไฟล์. เมื่อverticalOffsetถึง 0 หรือน้อยกว่าToolbarความสูงหมายความว่า CollapsingToolbarLayout ยุบไม่เช่นนั้นจะขยายหรือขยาย

mAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if(verticalOffset == 0 || verticalOffset <= mToolbar.getHeight() && !mToolbar.getTitle().equals(mCollapsedTitle)){
                    mCollapsingToolbar.setTitle(mCollapsedTitle);
                }else if(!mToolbar.getTitle().equals(mExpandedTitle)){
                    mCollapsingToolbar.setTitle(mExpandedTitle);
                }

            }
        });

1
มันไม่ได้ผลสำหรับฉัน OnCollapse ฉันต้องการเปิดใช้งานปุ่มโฮมและขยายซ่อนปุ่มโฮม
Maheshwar Ligade

9
ค่า verticalOffset ดูเหมือนจะเป็นศูนย์เมื่อแถบเครื่องมือถูกขยายจนสุดจากนั้นจะเป็นค่าลบในขณะที่ยุบ เมื่อแถบเครื่องมือถูกยุบ verticalOffset จะเท่ากับลบความสูงของแถบเครื่องมือ (-mToolbar.getHeight ()) ดังนั้น ... แถบเครื่องมือจึงถูกขยายบางส่วน "if (verticalOffset> -mToolbar.getHeight ())"
Mike

ในกรณีที่ใครสงสัยว่าappBarLayout.getVerticalOffset()เมธอดอยู่ที่ไหนคุณสามารถเรียกappBarLayout.getY()เพื่อดึงค่าเดียวกับที่ใช้ในการโทรกลับได้
Jarett Millard

น่าเสียดายที่ Jarett Millard ไม่ถูกต้อง ขึ้นอยู่กับการกำหนดค่า fitSystemWindow และการกำหนดค่า StatusBar ของคุณ (โปร่งใส) appBarLayout.getY()อาจเป็นไปได้ว่าverticalOffset = appBarLayout.getY() + statusBarHeight
ราศีมังกร

1
มีใครสังเกตเห็นว่า mAppBarLayout.addOnOffsetChangedListener (ผู้ฟัง) ถูกเรียกซ้ำ ๆ แม้ว่าเราจะไม่ได้โต้ตอบกับ appbar จริงๆ หรือเป็นจุดบกพร่องในเค้าโครง / แอปของฉันซึ่งฉันสังเกตพฤติกรรมนี้ ช่วยด้วย!
Rahul Shukla

16

รหัสนี้ใช้ได้ผลสำหรับฉัน

mAppBarLayout.addOnOffsetChangedListener(new   AppBarLayout.OnOffsetChangedListener() {
        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
            if (verticalOffset == -mCollapsingToolbarLayout.getHeight() + mToolbar.getHeight()) {
                //toolbar is collapsed here
                //write your code here
            }
        }
    });

คำตอบที่ดีกว่า Nikola Despotoski
Vignesh Bala

ดูเหมือนจะไม่ใช่วิธีแก้ปัญหาที่เชื่อถือได้ ฉันทดสอบแล้วและค่าบนอุปกรณ์ของฉันมีดังต่อไปนี้: mCollapsingToolbarLayout.getHeight () = 1013, mToolbar.getHeight () = 224 ดังนั้นตามวิธีการแก้ปัญหาของคุณ verticalOffset ในสถานะยุบต้องเป็น -789 อย่างไรก็ตามมันเท่ากับ -693
Leo Droidcoder

16
private enum State {
    EXPANDED,
    COLLAPSED,
    IDLE
}

private void initViews() {
    final String TAG = "AppBarTest";
    final AppBarLayout mAppBarLayout = findViewById(R.id.appbar);
    mAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
        private State state;

        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
            if (verticalOffset == 0) {
                if (state != State.EXPANDED) {
                    Log.d(TAG,"Expanded");
                }
                state = State.EXPANDED;
            } else if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()) {
                if (state != State.COLLAPSED) {
                    Log.d(TAG,"Collapsed");
                }
                state = State.COLLAPSED;
            } else {
                if (state != State.IDLE) {
                    Log.d(TAG,"Idle");
                }
                state = State.IDLE;
            }
        }
    });
}

10

คุณสามารถรับเปอร์เซ็นต์อัลฟายุบเครื่องมือบาร์โดยใช้ด้านล่าง:

appbarLayout.addOnOffsetChangedListener( new AppBarLayout.OnOffsetChangedListener() {
        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
            float percentage = ((float)Math.abs(verticalOffset)/appBarLayout.getTotalScrollRange());
            fadedView.setAlpha(percentage);
    });

สำหรับการอ้างอิง: ลิงค์


2
นี่เป็นคำตอบที่ดีเนื่องจากให้ค่าชดเชยปกติ ในความคิดของฉัน API ควรให้สิ่งนี้โดยตรงแทนverticalOffsetระยะพิกเซล
dbm

5

นี่คือโซลูชันของKotlin เพิ่มOnOffsetChangedListenerไฟล์AppBarLayout.

วิธี A:

เพิ่มAppBarStateChangeListener.ktในโครงการของคุณ:

import com.google.android.material.appbar.AppBarLayout
import kotlin.math.abs

abstract class AppBarStateChangeListener : AppBarLayout.OnOffsetChangedListener {

    enum class State {
        EXPANDED, COLLAPSED, IDLE
    }

    private var mCurrentState = State.IDLE

    override fun onOffsetChanged(appBarLayout: AppBarLayout, i: Int) {
        if (i == 0 && mCurrentState != State.EXPANDED) {
            onStateChanged(appBarLayout, State.EXPANDED)
            mCurrentState = State.EXPANDED
        }
        else if (abs(i) >= appBarLayout.totalScrollRange && mCurrentState != State.COLLAPSED) {
            onStateChanged(appBarLayout, State.COLLAPSED)
            mCurrentState = State.COLLAPSED
        }
        else if (mCurrentState != State.IDLE) {
            onStateChanged(appBarLayout, State.IDLE)
            mCurrentState = State.IDLE
        }
    }

    abstract fun onStateChanged(
        appBarLayout: AppBarLayout?,
        state: State?
    )

}

เพิ่มผู้ฟังลงในappBarLayout:

appBarLayout.addOnOffsetChangedListener(object: AppBarStateChangeListener() {
        override fun onStateChanged(appBarLayout: AppBarLayout?, state: State?) {
            Log.d("State", state.name)
            when(state) {
                State.COLLAPSED -> { /* Do something */ }
                State.EXPANDED -> { /* Do something */ }
                State.IDLE -> { /* Do something */ }
            }
        }
    }
)

วิธี B:

appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset ->
        if (abs(verticalOffset) - appBarLayout.totalScrollRange == 0) { 
            // Collapsed
        } else if (verticalOffset == 0) {
            // Expanded
        } else {
            // Idle
        }
    }
)

3

วิธีนี้ใช้ได้ผลสำหรับฉัน:

@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
  if (i == 0) {
    if (onStateChangeListener != null && state != State.EXPANDED) {
      onStateChangeListener.onStateChange(State.EXPANDED);
    }
    state = State.EXPANDED;
  } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
    if (onStateChangeListener != null && state != State.COLLAPSED) {
      onStateChangeListener.onStateChange(State.COLLAPSED);
    }
    state = State.COLLAPSED;
  } else {
    if (onStateChangeListener != null && state != State.IDLE) {
      onStateChangeListener.onStateChange(State.IDLE);
    }
    state = State.IDLE;
  }
}

ใช้ addOnOffsetChangedListener บน AppBarLayout


คุณสามารถแบ่งปันรหัสทั้งหมดของคุณได้หรือไม่? State.EXPANDED ฯลฯ คืออะไร?
Chetna

1

หากคุณใช้ CollapsingToolBarLayout คุณสามารถวางสิ่งนี้ได้

collapsingToolbar.setExpandedTitleColor(ContextCompat.getColor(activity, android.R.color.transparent));
collapsingToolbar.setTitle(title);

1

รหัสนี้ใช้งานได้ดีสำหรับฉัน คุณสามารถใช้มาตราส่วนเปอร์เซ็นต์ได้ตามต้องการ

@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
    double percentage = (double) Math.abs(verticalOffset) / collapsingToolbar.getHeight();
    if (percentage > 0.8) {
        collapsingToolbar.setTitle("Collapsed");
    } else {
        collapsingToolbar.setTitle("Expanded");
    }
}

0

ค่าออฟเซ็ตของแถบเครื่องมือของฉันได้รับ -582 เมื่อยุบเมื่อขยาย = 0 ดังนั้นฉันจึงหาค่าโดยการตั้งค่าชดเชยใน Toast และเปลี่ยนรหัสตามนั้น

 mAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
            if(verticalOffset == -582) {
            Toast.makeText(MainActivity.this, "collaped" + verticalOffset, Toast.LENGTH_SHORT).show();
            mCollapsingToolbarLayout.setTitle("Collapsed");
            }else if(verticalOffset == 0){
                Toast.makeText(MainActivity.this, "expanded" + verticalOffset, Toast.LENGTH_SHORT).show();
            mCollapsingToolbarLayout.setTitle("expanded");
            }
        }
    });
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.