调整主要布局内容的大小以适合底部工作表?

时间:2017-11-30 18:32:27

标签: android android-layout android-coordinatorlayout bottom-sheet

我尝试创建一个包含持久性底部工作表和提供主要内容的NestedScrollView的布局。不幸的是,当扩展底部工作表时,它会模糊NestedScrollView,并且无法访问它的底部项目。 ?

调整主NestedScroll大小以适应展开的底部工作表的最佳方法是什么?

举个例子:

<android.support.design.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <!-- I want this view resized dependent on bottom sheet expansion -->
    <android.support.v4.widget.NestedScrollView
        android:id="@+id/layout_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

       <!-- content goes here -->

    </android.support.v4.widget.NestedScrollView>

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/layout_bottomsheet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="android.support.design.widget.BottomSheetBehavior">

        <!-- bottom sheet content goes here -->

    </android.support.v4.widget.NestedScrollView>

</android.support.design.widget.CoordinatorLayout>

1 个答案:

答案 0 :(得分:0)

有一种方法可以获得您需要的东西,避免遮挡底部工作表背后的视图并处理它的触摸。

您需要延长BottomSheetDialogFragment

public class MyBottomSheetDialogFragment extends BottomSheetDialogFragment {

    @Override
    public void onStart() {
        super.onStart();
        if(getDialog() != null && getDialog().getWindow() != null) {
        getDialog().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
    }

在onStart()中,你可以删除背景暗淡,这样你就可以清楚地看到你的背后视图。

@Override
public void setupDialog(Dialog dialog, int style) {
    super.setupDialog(dialog, style);
    View rootView = View.inflate(getContext(), R.layout.your_bottom_sheet_layout, null);
    dialog.setContentView(rootView);
    dialog.setCanceledOnTouchOutside(false);
    // set your children views

    dialog.setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialogInterface) {
            // Do stuff when the dialog is visible on screen
            Window window = getDialog().getWindow();
            if(window != null) {
                window.setCallback(windowCallback);
            }
        }
    });
}

在setupDialog()中夸大你的布局并避免通过设置一个窗口回调来解决你可以处理的外部触摸对话框,如下所示:

private Window.Callback windowCallback = new Window.Callback() {

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            onBackPressed();
        }
        return false;
    }

    @Override
    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
        return false;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        return onDispatchTouchEvent(event);
    }

    @Override
    public boolean dispatchTrackballEvent(MotionEvent event) {
        return false;
    }

    @Override
    public boolean dispatchGenericMotionEvent(MotionEvent event) {
        return false;
    }

    @Override
    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
        return false;
    }

    @Nullable
    @Override
    public View onCreatePanelView(int featureId) {
        return null;
    }

    @Override
    public boolean onCreatePanelMenu(int featureId, Menu menu) {
        return false;
    }

    @Override
    public boolean onPreparePanel(int featureId, View view, Menu menu) {
        return false;
    }

    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        return false;
    }

    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
        return false;
    }

    @Override
    public void onWindowAttributesChanged(WindowManager.LayoutParams attrs) {

    }

    @Override
    public void onContentChanged() {

    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {

    }

    @Override
    public void onAttachedToWindow() {

    }

    @Override
    public void onDetachedFromWindow() {

    }

    @Override
    public void onPanelClosed(int featureId, Menu menu) {

    }

    @Override
    public boolean onSearchRequested() {
        return false;
    }

    @Override
    public boolean onSearchRequested(SearchEvent searchEvent) {
        return false;
    }

    @Nullable
    @Override
    public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
        return null;
    }

    @Nullable
    @Override
    public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) {
        return null;
    }

    @Override
    public void onActionModeStarted(ActionMode mode) {

    }

    @Override
    public void onActionModeFinished(ActionMode mode) {

    }
};

通过设置此回调,您需要管理每一次触摸。这有点棘手,但你可以获得目标。 onDispatchTouchEvent(事件)必须是这样的:

@Override
protected boolean onDispatchTouchEvent(MotionEvent event) {

    // check if the dialog is being touched
    float eventX = event.getRawX();
    float eventY = event.getRawY();
    int location[] = new int[2];
    yourDialogRootView.getLocationOnScreen(location);
    boolean isDialogBeingTouched = eventX > (location[0] - leftPaddingX)
            && eventX < (location[0] + view.getWidth())
            && eventY > (location[1])
            && eventY < (location[1] + view.getHeight());

    if (isDialogBeingTouched) {
        checkForAClick(event);
    }

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (isDialogBeingTouched) {
                // the dialog is touched so handle its touch
                return true;
            }
    }

    // dialog not touched so let the activity handle the touch normally
    return getActivity().dispatchTouchEvent(event);
}

checkForAClick(事件)应该是这样的:

protected boolean checkForAClick(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startX = event.getX();
            startY = event.getY();
            break;
        case MotionEvent.ACTION_UP:
            float endX = event.getX();
            float endY = event.getY();
            if (isAClick(startX, endX, startY, endY)) {
                // handle click on your dialog as you prefer
                onBottomSheetClick(event);
            }
            break;
    }
    return false;
}

private static int CLICK_ACTION_THRESHOLD = 50;

public boolean isAClick(float startX, float endX, float startY, float endY) {
    float differenceX = Math.abs(startX - endX);
    float differenceY = Math.abs(startY - endY);
    if (differenceX > CLICK_ACTION_THRESHOLD || differenceY > CLICK_ACTION_THRESHOLD) {
        return false;
    }
    return true;
}

我知道这有点长的解释,但我希望它可以提供帮助。