如何在显示Bottomsheet时调暗背景,而不使用Dialog?

时间:2016-12-01 00:33:25

标签: android bottom-sheet

我知道BottomSheetDialog已经这样做了,但我需要使用BottomSheet生成的常规BottomSheetBehavior.from()和行为。此BottomSheet不会使背景变暗,而且外部触摸也不会将其关闭。有没有办法在显示BottomSheet时调暗背景?当外面碰到时可能会解雇。基本上行为就像BottomSheetDialog一样,但我必须直接使用BottomSheet BottomSheetBehavior

谢谢!

6 个答案:

答案 0 :(得分:22)

您可以使用此代码 1. MainActivity.xml

<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingTop="24dp">

        <Button
            android:id="@+id/button_1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button 1"
            android:padding="16dp"
            android:layout_margin="8dp"
            android:textColor="@android:color/white"
            android:background="@android:color/holo_green_dark"/>

    </LinearLayout>

</ScrollView>

<View
    android:visibility="gone"
    android:id="@+id/bg"
    android:background="#99000000"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

<android.support.v4.widget.NestedScrollView
    android:id="@+id/bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="350dp"
    android:clipToPadding="true"
    android:background="@android:color/holo_orange_light"
    app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
    >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="aefwea"
        android:padding="16dp"
        android:textSize="16sp"/>

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

 </android.support.design.widget.CoordinatorLayout>
  1. MAinActivity.java

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
    private static final String TAG = "MainActivity";
    private BottomSheetBehavior mBottomSheetBehavior;
    View bottomSheet;
    View mViewBg;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bottomSheet = findViewById(R.id.bottom_sheet);
        mViewBg = findViewById(R.id.mViewBg);
        Button button1 = (Button) findViewById(R.id.button_1);
        button1.setOnClickListener(this);
        mViewBg.setOnClickListener(this);
        mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
        mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                if (newState == BottomSheetBehavior.STATE_COLLAPSED)
                    mViewBg.setVisibility(View.GONE);
            }
    
            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
                Log.d(TAG, "onSlide: slideOffset" + slideOffset + "");
               mViewBg.setVisibility(View.VISIBLE);
                mViewBg.setAlpha(slideOffset);
            }
        });
    
    }
    
    
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button_1: {
                mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                break;
            }
            case R.id.bg: {
                mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                break;
            }
        }
    }
    
    
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
                Rect outRect = new Rect();
                bottomSheet.getGlobalVisibleRect(outRect);
                if (!outRect.contains((int) event.getRawX(), (int) event.getRawY())) {
                    mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                    return true;
                }
    
            }
        }
        return super.dispatchTouchEvent(event);
    }
    
    }
    

答案 1 :(得分:2)

如果你想要我在AlertDialog with Blur background in possition center

中使用我的概念,你可以使用我的概念

我的方法

  1. 拍摄屏幕截图
  2. 以虚拟方式为dim / blur屏幕快照设置动画
  3. 使用没有任何内容的对话框获取currant窗口
  4. 附加有效的屏幕截图
  5. 显示我想要显示的真实视图
  6. 这里我有一个类,用于将背景图像作为位图

    public class AppUtils {
    
        public static Bitmap takeScreenShot(Activity activity) {
            View view = activity.getWindow().getDecorView();
            view.setDrawingCacheEnabled(true);
            view.buildDrawingCache();
    
    
            Bitmap b1 = view.getDrawingCache();
            Rect frame = new Rect();
            activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
            int statusBarHeight = frame.top;
    
            Display display = activity.getWindowManager().getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
            int width = size.x;
            int height = size.y;
    
    
            Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height - statusBarHeight);
            view.destroyDrawingCache();
            return b;
        }
    }
    

    恭喜你现在有一个与你的背景相同的变暗/暗淡的图像

    然后你的要求是暗淡不要像我一样模糊,所以你可以将这个位图传递给下面的方法,

    public static Bitmap changeBitmapContrastBrightness(Bitmap bmp, float contrast, float brightness) {
            ColorMatrix cm = new ColorMatrix(new float[]
                    {
                            contrast, 0, 0, 0, brightness,
                            0, contrast, 0, 0, brightness,
                            0, 0, contrast, 0, brightness,
                            0, 0, 0, 1, 0
                    });
    
            Bitmap ret = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig());
    
            Canvas canvas = new Canvas(ret);
    
            Paint paint = new Paint();
            paint.setColorFilter(new ColorMatrixColorFilter(cm));
            canvas.drawBitmap(bmp, 0, 0, paint);
    
            return ret;
        }
    

    现在使用假的对话框/对话框,仅显示背景/内容以获取窗口(检查我的问题实现,你可以理解)

    Window window = fakeDialogUseToGetWindowForBlurEffect.getWindow();
    window.setBackgroundDrawable(draw);  // draw is bitmap that you created 
    

    在此之后你可以显示你的真实视图。在我的情况下,我会显示一个警告,你可以显示你的任何视图,并记住当你的真实视图从屏幕上消失时删除/消除警告!

    快速输出 :(可根据需要自定义背景,不仅暗淡)

    enter image description here

答案 2 :(得分:2)

您可以创建一个自定义片段,该片段具有附加到底部的布局(底部种类),并使背景为<?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:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ff2020" android:orientation="vertical" tools:context="com.example.jiffysoftwaresolutions.copypastesampleapp.MainActivity"> <Button android:id="@+id/show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Show" /> <FrameLayout android:id="@+id/bottom_sheet_fragment_container" android:layout_width="match_parent" android:layout_height="match_parent"></FrameLayout> </RelativeLayout> &amp;当触摸那个BG时删除那个片段。例如:

<强> activity_main.xml中

public class MainActivity extends AppCompatActivity {

    private BottomSheetFragment bottomSheetFragment;

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

        findViewById(R.id.show).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (bottomSheetFragment == null) {
                    bottomSheetFragment = new BottomSheetFragment();
                }
                getSupportFragmentManager().beginTransaction().add(R.id.bottom_sheet_fragment_container, bottomSheetFragment).addToBackStack(null).commit();

            }
        });

    }


    public void removeBottomSheet() {
        try {
            getSupportFragmentManager().beginTransaction().remove(bottomSheetFragment).addToBackStack(null).commit();
        } catch (Exception e) {
        }
    }

}

<强> MainActivity.java

public class BottomSheetFragment extends Fragment {


    private View rootView;
    private LayoutInflater layoutInflater;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }


    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.bottom_sheet_layout, container, false);
        rootView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // remove sheet on BG touch
                ((MainActivity) getActivity()).removeBottomSheet();
            }
        });
        return rootView;
    }

}

<强> BottomSheetFragment.java

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#6d000000"
    android:gravity="bottom">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#fff"
        android:orientation="vertical"
        android:padding="5dp">

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button1"
            android:textColor="#000" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button2"
            android:textColor="#000" />

    </LinearLayout>

</RelativeLayout>

<强> bottom_sheet_layout.xml

a = 'Good day to you sir and lady.
Hello and good day.'

a.gsub!('Good day', 'Hellor').gsub!('good day', 'hellor')

要使用bottom_top / animation添加该片段..您可以点击此链接:Android Fragments and animation

答案 3 :(得分:1)

使用接口-onSlide,它可以将float类型的参数slideOffSet用作背景变暗。此底页的新偏移量在[-1,1]范围内。随着此底纸向上移动,偏移量增加。从0到1,工作表介于折叠状态和展开状态之间;从-1到0,工作表介于隐藏状态和折叠状态之间。

if ( slideOffSet>=0 && slideOffSet<=1 ) {
    mainActivityLayoutView.setAlpha( 1f - slideOffSet ); 
}

其中mainActivityLayoutView是NestedScrollView的ID,用于保存活动的主要内容。

答案 4 :(得分:0)

如果实现 BottomSheetBehavior 的视图位于不同的 Activity 中,您可以使用以下解决方案

为了使您的活动背景透明+变暗,请为您的活动添加以下样式

<style name="Your.Transparent.Style">
    <!-- Found no solution for setting the status bar color to fully transparent 
         from within the style. Had to resort to programmatically setting -->
    <item name="android:windowBackground">@color/transparent</item>
    <item name="android:backgroundDimEnabled">true</item>
</style>

在你的 AndroidManifest.xml 中设置活动主题

<activity
   android:name="your.activity"
   android:theme="@style/Your.Transparent.Style" />

将状态栏颜色设置为完全透明(仅适用于 API >= 21)

// Inside your activity's onCreate 
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setStatusBarTransparent(window)

fun setStatusBarTransparent(window: Window) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        window.statusBarColor = Color.TRANSPARENT
    }
}

最后,为了在单击工作表内容外部时隐藏底部工作表,请扩展 BottomSheetBehavior

class AutoCloseBottomSheetBehavior<V : View>(
    context: Context,
    attrs: AttributeSet
) : BottomSheetBehavior<V>(context, attrs) {
    
    @SuppressLint("ClickableViewAccessibility")
    override fun onLayoutChild(parent: CoordinatorLayout, child: V, layoutDirection: Int): Boolean {
        parent.setOnTouchListener { _, event ->
            if (event.action == MotionEvent.ACTION_DOWN) {
                val outRect = Rect()
                child.getGlobalVisibleRect(outRect)
                if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
                    state = STATE_HIDDEN
                    return@setOnTouchListener true
                }
            }

            return@setOnTouchListener false

        }
        return super.onLayoutChild(parent, child, layoutDirection)
    }
}

并为您的视图行为设置它

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
    >

    <Your.View.Acting.As.BottomSheet
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior=".your.path.AutoCloseBottomSheetBehavior" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

答案 5 :(得分:-1)

使用此样式并应用于对话框。

  

PS:这种风格在Android 6.0,6.1和7.0中也很完美。

<style name="MaterialDialogSheet" parent="@android:style/Theme.Dialog">
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:backgroundDimEnabled">true</item>
        <item name="android:windowIsFloating">false</item>
        <item name="android:windowAnimationStyle">@style/MaterialDialogSheetAnimation</item>
    </style>
<style name="MaterialDialogSheetAnimation">
        <item name="android:windowEnterAnimation">@anim/popup_show</item>
        <item name="android:windowExitAnimation">@anim/popup_hide</item>
    </style>

并用作:

final Dialog mBottomSheetDialog = new Dialog(mActivity, R.style.MaterialDialogSheet);

感谢。