animateLayoutChanges=“true” in BottomSheetView showing unexpected behaviour

后端 未结 4 562
没有蜡笔的小新
没有蜡笔的小新 2021-01-31 15:24

I have a BottomSheetView which has animateLayoutChanges=\"true\". Initially it shows up fine. But if change the visibility of a view (insi

4条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-01-31 15:55

    The question was asked more than two years ago, but unfortunately the problem persists.

    I finally got a solution to keep the call to the addView and removeView functions in a BottomSheet, while having animateLayoutChanges="true".

    BottomSheetBehavior cannot calculate the correct height when it changes, so the height must remain the same. To do this, I set the height of the BottomSheet to match_parent and divide it into two children: the content and a Space that changes height according to the height of the content.

    To best mimic the true behavior of a BottomSheet, you also need to add a TouchToDismiss view that darkens the background when the BottomSheet is extended but also to close the BottomSheet when the user presses outside the content.

    Here's the code:

    activity.xml

    
    
        

    activity.java

    BottomSheetBehavior bottomSheetBehavior;
    View touchToDismiss;
    LinearLayout bottomSheet;
    Button showBottomSheet;
    Space space;
    LinearLayout bottomSheetContent;
    Button addOrRemoveAnotherView;
    TextView anotherView;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        touchToDismiss = findViewById(R.id.touch_to_dismiss);
        touchToDismiss.setVisibility(View.GONE);
        touchToDismiss.setOnClickListener(this);
    
        bottomSheet = findViewById(R.id.bottom_sheet);
    
        bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
        bottomSheetBehavior.setPeekHeight(0);
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
        bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                if (newState == BottomSheetBehavior.STATE_HIDDEN || newState == BottomSheetBehavior.STATE_COLLAPSED) {
                    touchToDismiss.setVisibility(View.GONE);
                }else {
                    touchToDismiss.setVisibility(View.VISIBLE);
                }
            }
    
            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
                touchToDismiss.setAlpha(getRealOffset());
            }
        });
    
        showBottomSheet = findViewById(R.id.show_bottom_sheet);
        showBottomSheet.setOnClickListener(this);
    
        space = findViewById(R.id.space);
    
        bottomSheetContent = findViewById(R.id.bottom_sheet_content);
    
        addOrRemoveAnotherView = findViewById(R.id.add_or_remove_another_view);
        addOrRemoveAnotherView.setOnClickListener(this);
    
        anotherView = findViewById(R.id.another_view);
        bottomSheetContent.removeView(anotherView);
    }
    
    @Override
    public void onClick(View v) {
        if (v == showBottomSheet)
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        else if (v == addOrRemoveAnotherView) {
            if (anotherView.getParent() == null)
                bottomSheetContent.addView(anotherView);
            else
                bottomSheetContent.removeView(anotherView);
        }
        else if (v == touchToDismiss)
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
    }
    
    /**
     * Since the height does not change and remains at match_parent, it is required to calculate the true offset.
     * @return Real offset of the BottomSheet content.
     */
    public float getRealOffset() {
        float num = (space.getHeight() + bottomSheetContent.getHeight()) - (bottomSheet.getY() + space.getHeight());
    
        float den = bottomSheetContent.getHeight();
    
        return (num / den);
    }
    

    This is the result obtained with this code:

    Hopefully it will be useful to someone since the problem is still there!

提交回复
热议问题