Hoe kan ik de achtergrond dimmen wanneer Bottomsheet wordt weergegeven, zonder Dialog te gebruiken?

Ik weet dat BottomSheetDialogdit al doet, maar ik moet de normale BottomSheeten het gedrag dat is gegenereerd uit BottomSheetBehavior.from()gebruiken. Deze BottomSheetverduistert de achtergrond niet en ook aanraken buiten zou hem niet sluiten. Is er een manier om de achtergrond te dimmen wanneer BottomSheetwordt weergegeven? en misschien afwijzen wanneer u buiten aanraakt. In principe is het gedrag hetzelfde als BottomSheetDialog, maar ik moet BottomSheetBottomSheetBehaviorrechtstreeks gebruiken.


Antwoord 1, autoriteit 100%

U kunt deze code gebruiken
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);
    }
    }
    

Antwoord 2, autoriteit 4%

U kunt een aangepast fragment maken met een lay-out (soort bottomSheet) aan de onderkant en de achtergrond transparent_black& wanneer u die BG aanraakt, verwijder dat fragment. Vb:

activity_main.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: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>

MainActivity.java

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) {
        }
    }
}

BottomSheetFragment.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;
    }
}

bottom_sheet_layout.xml

<?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>

Om dat fragment toe te voegen met bottom_top/animation.. kun je deze link volgen: Android-fragmenten en animatie


Antwoord 3, autoriteit 2%

Met behulp van de interface – onSlide die als parameter slideOffSet van het type float , kan worden gebruikt om de achtergrond te dimmen. De nieuwe offset van dit onderblad binnen [-1,1] bereik. De offset neemt toe naarmate dit ondervel naar boven beweegt. Van 0 tot 1 bevindt het blad zich tussen samengevouwen en uitgevouwen toestanden en van -1 tot 0 bevindt het zich tussen verborgen en samengevouwen toestanden.

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

waarbij mainActivityLayoutView de id is voor NestedScrollView , die de hoofdinhoud van de activiteit bevat.


Antwoord 4

Je kunt mijn concept gebruiken als je wilt dat ik heb gebruikt in AlertDialog with Blur background in possition center

Mijn aanpak

  1. Een screenshot maken
  2. Programma’s animaties maken van gedimde/vervaagde schermafbeeldingen
  3. Krijg een besvenster met behulp van een dialoogvenster dat geen inhoud heeft
  4. Screenshot met effect bijvoegen
  5. Geef de echte weergave weer die ik wilde weergeven

Hier heb ik een les om een ​​afbeelding van de achtergrond als bitmap te maken

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;
    }
}

Gefeliciteerd, je hebt nu een donkerder/gedimde afbeelding die hetzelfde is als je achtergrond

U moet dan dimmen en niet vervagen zoals de mijne, zodat u deze bitmap kunt doorgeven aan de onderstaande methode,

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;
    }

Gebruik nu een nep-dialoog/dialoogvenster zonder achtergrond/inhoud alleen om het venster te krijgen (controleer de implementatie van mijn vragen, u kunt dat begrijpen)

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

hierna kunt u uw echte weergave laten zien. In mijn geval geef ik een waarschuwing weer, u kunt alles weergeven wat uw weergave is en vergeet niet om die waarschuwing te verwijderen/verdwijnen wanneer uw echte weergave van het scherm verdwijnt!

Snelle uitvoer: (achtergrond kan naar wens worden aangepast, niet alleen donker)

voer hier de afbeeldingsbeschrijving in


Antwoord 5

Gebruik deze stijl en pas deze toe op uw dialoog.

PS: deze stijl werkt ook perfect in Android 6.0, 6.1 en 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>

En gebruik als:

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

Bedankt.


Antwoord 6

In het geval dat de weergave die het BottomSheetBehaviorimplementeert zich binnen een afzonderlijke activiteit bevindt, kunt u de volgende oplossing gebruiken

Om de achtergrond van je activiteit transparant + gedimd te maken, voeg je de volgende stijl toe aan je activiteit

<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>

Stel in uw AndroidManifest.xml het activiteitsthema in

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

De kleur van de statusbalk instellen op volledig transparant (werkt alleen voor 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
    }
}

En tot slot voor het verbergen van het onderste blad wanneer u buiten de bladinhoud klikt, verlengt u het 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)
    }
}

En stel het in op het gedrag van uw weergave

<?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>

Other episodes