setOnApplyWindowInsetsListener in android java - android

I have a toolbar which is overlapping with the system bars so I am setting the insets with the toolbar. I have the implementation below which is not doing anything and it is still at the same place. I am trying to set the margins on left, right and top.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
ViewCompat.setOnApplyWindowInsetsListener(myToolbar, (v, windowInsets) -> {
Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
// Apply the insets as a margin to the view. Here the system is setting
// only the bottom, left, and right dimensions, but apply whichever insets are
// appropriate to your layout. You can also update the view padding
// if that's more appropriate.
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
mlp.leftMargin = insets.left;
mlp.topMargin = insets.top;
mlp.rightMargin = insets.right;
v.setLayoutParams(mlp);
return WindowInsetsCompat.CONSUMED;
});

Related

Unable to measure the height of my Bottom Navigation Bar

I'm trying to get the height of my Bottom Navigation Bar, so I can set a bottom margin on the content that is displayed above the bar. My problem is that it always returns 0. Here is the code :
navigation.post(new Runnable() {
#Override
public void run() {
navHeight = navigation.getMeasuredHeight();
}
});
FrameLayout frame = findViewById(R.id.frame_container);
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) frame.getLayoutParams();
params.setMargins(0, 0, 0, navHeight);
frame.setLayoutParams(params);
I also tried using ViewTreeObserver, but it didn't work neither.
I just had to move everything inside the run() method

BottomSheetDialogFragment - How to set expanded height (or min top offset)

I create a BottomSheetDialogFragment and I want to adjust it's maximum expanded height. How can I do that? I can retrieve the BottomSheetBehaviour but all I can find is a setter for the peek height but nothing for the expanded height.
public class DialogMediaDetails extends BottomSheetDialogFragment
{
#Override
public void setupDialog(Dialog dialog, int style)
{
super.setupDialog(dialog, style);
View view = View.inflate(getContext(), R.layout.dialog_media_details, null);
dialog.setContentView(view);
...
View bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setPeekHeight(...);
// how to set maximum expanded height???? Or a minimum top offset?
}
}
EDIT
Why do I need that? Because I show a BottomSheet Dialog in a full screen activity and it looks bad if the BottomSheet leaves a space on top...
The height is being wrapped because the inflated view is added to the FrameLayout which has layout_height=wrap_content. See FrameLayout (R.id.design_bottom_sheet) at https://github.com/dandar3/android-support-design/blob/master/res/layout/design_bottom_sheet_dialog.xml.
The class below makes the bottom sheet full screen, background transparent, and fully expanded to the top.
public class FullScreenBottomSheetDialogFragment extends BottomSheetDialogFragment {
#CallSuper
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
}
#Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
View bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
}
View view = getView();
view.post(() -> {
View parent = (View) view.getParent();
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) (parent).getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) behavior;
bottomSheetBehavior.setPeekHeight(view.getMeasuredHeight());
((View)bottomSheet.getParent()).setBackgroundColor(Color.TRANSPARENT)
});
}
}
--- EDIT Aug 30, 2018 ---
I realized a year later that the background was colored on the wrong view. This dragged the background along with the content while a user was dragging the dialog.
I fixed it so that the parent view of the bottom sheet is colored.
I found a much simpler answer; in your example where you obtain the FrameLayout for the bottom sheet using this code
View bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
you can then set the height on the layout params for that View to whatever height you want to set the expanded height to.
bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
BIG UPDATE
Avoiding duplicated code I'm giving a link to the full answer in where you can find all the explanations about how to get full behavior like Google Maps.
I want to adjust its maximum expanded height. How can I do that?
Both BottomSheet and BottomSheetDialogFragment use a BottomSheetBehavior that you can found in Support Library 23.x
That Java class has 2 different uses for mMinOffset, one of them is used to define the area of the parent it will use to draw his content (maybe a NestedScrollView). And the other use is for defining the expanded anchor point, I mean, if you slide it up to form STATE_COLLAPSEDit will animate your BottomSheetuntil he reached this anchor point BUT if you can still keep sliding up to cover all parent height (CoordiantorLayout Height).
If you took a look at BottomSheetDialog you will see this method:
private View wrapInBottomSheet(int layoutResId, View view, ViewGroup.LayoutParams params) {
final CoordinatorLayout coordinator = (CoordinatorLayout) View.inflate(getContext(),
android.support.design.R.layout.design_bottom_sheet_dialog, null);
if (layoutResId != 0 && view == null) {
view = getLayoutInflater().inflate(layoutResId, coordinator, false);
}
FrameLayout bottomSheet = (FrameLayout) coordinator.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setBottomSheetCallback(mBottomSheetCallback);
if (params == null) {
bottomSheet.addView(view);
} else {
bottomSheet.addView(view, params);
}
// We treat the CoordinatorLayout as outside the dialog though it is technically inside
if (shouldWindowCloseOnTouchOutside()) {
final View finalView = view;
coordinator.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (isShowing() &&
MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_UP &&
!coordinator.isPointInChildBounds(finalView,
(int) event.getX(), (int) event.getY())) {
cancel();
return true;
}
return false;
}
});
}
return coordinator;
}
No idea which one of those 2 behaviors you want but if you need the second one follow those steps:
Create a Java class and extend it from CoordinatorLayout.Behavior<V>
Copy paste code from the default BottomSheetBehavior file to your new one.
Modify the method clampViewPositionVertical with the following code:
#Override
public int clampViewPositionVertical(View child, int top, int dy) {
return constrain(top, mMinOffset, mHideable ? mParentHeight : mMaxOffset);
}
int constrain(int amount, int low, int high) {
return amount < low ? low : (amount > high ? high : amount);
}
Add a new state
public static final int STATE_ANCHOR_POINT = X;
Modify the next methods: onLayoutChild, onStopNestedScroll, BottomSheetBehavior<V> from(V view) and setState (optional)
And here is how it looks like
[]
Its works for me. Add code on BottomSheetDialogFragment's onViewCreated() methode
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
view.viewTreeObserver.removeOnGlobalLayoutListener(this)
val dialog = dialog as BottomSheetDialog
val bottomSheet = dialog.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet) as FrameLayout?
val behavior = BottomSheetBehavior.from(bottomSheet!!)
behavior.state = BottomSheetBehavior.STATE_EXPANDED
val newHeight = activity?.window?.decorView?.measuredHeight
val viewGroupLayoutParams = bottomSheet.layoutParams
viewGroupLayoutParams.height = newHeight ?: 0
bottomSheet.layoutParams = viewGroupLayoutParams
}
})
dialogView = view
}
Don't forget to remove viewTreeObserver.
override fun onDestroyView() {
dialogView?.viewTreeObserver?.addOnGlobalLayoutListener(null)
super.onDestroyView()
}
Get reference to sheet behavior,
private val behavior by lazy { (dialog as BottomSheetDialog).behavior }
turn fitToContents off and set expandedOffset to desired pixels.
behavior.isFitToContents = false
behavior.expandedOffset = 100
Kotlin
In my case I need to define a fixed height and I did the following:
val bottomSheet: View? = dialog.findViewById(R.id.design_bottom_sheet)
BottomSheetBehavior.from(bottomSheet!!).peekHeight = 250
this way you also have access to any property of the BottomSheetBehavior such as halfExpandedRatio
I would advise against using ids to find views. In the BottomSheetDialogFragment the dialog is a BottomSheetDialog which exposes the behavior for the bottom sheet. You can use that to set the peek height.
(dialog as BottomSheetDialog).behavior.peekHeight = ...

Collapsing Toolbar Layout - full height Image and scrolled at start

I have got a layout quite similar to this one: http://antonioleiva.com/collapsing-toolbar-layout/ - a classic approach to the Collapsing Toolbar.
I would like to extend it with following feature:
The ImageView is full screen height and at activity starts it is automatically scrolled half of it height down. When activity starts and user will scroll down, it will behave the old way, but (at activity starts) when he scrolls up, he can scroll all the way up to make the image full screen height size.
What kid of steps I need to take to make it behave the way I imagined?
Here is the the general Idea.
Activity:
public void setupMovingBar(final Boolean full) {
final Display dWidth = getWindowManager().getDefaultDisplay();
appBarLayout.post(new Runnable() {
#Override
public void run() {
int heightPx = dWidth.getHeight();
if (!full) {
heightPx = dWidth.getHeight() - (dWidth.getHeight() * 1 / 3);
}
setAppBarOffset(heightPx);
}
});
}
private void setAppBarOffset(int offsetPx) {
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
behavior.onNestedPreScroll(clContent, appBarLayout, null, 0, offsetPx, new int[]{0, 0});
}

How to overlap system bottom navigation bar.?

I am trying to overlap system bottom navigation bar using window manager but i can`t do it. I am Using bellow code.I have set gravity to bottom, therefore it show view layer in bottom of my activity view not not overlapping bottom navigation bar.
public void onCreate(Bundle savedInstancestate)
{
super.onCreate(savedInstancestate);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);7
manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
localLayoutParams.gravity = Gravity.BOTTOM;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to recieve touch events
//WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN |
//WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
// Draws over navigation bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
//localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = (int) (50 * getResources().getDisplayMetrics().scaledDensity);
localLayoutParams.format = PixelFormat.TRANSPARENT;
view = new customView(this);
manager.addView(view, localLayoutParams);
setContentView(R.layout.Imges);
}
public class customView extends ViewGroup {
public customView(Context context) {
super(context);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("customView", "------Intercepted-------");
return true;
}
}
Using this code i can't overlap navigation,Its shows new custom view in bottom of my activity view but can not overlap navigation bar with custom view.
any one can help me on this, to overlap navigation bar with custom view.?
There are actually some solutions.You cannot overlap in the means of making it totally disappear since there are devices in market without the hardware buttons. However you can elegantly arrange your layout accordingly.
For example,
Add this to your styles.xml (v21 )in a values dir:
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
or if it does not work,
boolean hasMenuKey = ViewConfiguration.get(getContext()).hasPermanentMenuKey();
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
if(!hasMenuKey && !hasBackKey) {
// Do whatever you need to do, this device has a navigation bar
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT
);
params.setMargins(0, 0, 0, 75);
entrancelayout.setLayoutParams(params);
entrancelayout.requestLayout();
}
I had a FrameLayout, you can use it for whatever layout you have. SetMargins adds margin to buttom in example. It assumes System Bar is there if there are no hardware back and menu buttons.

Shadow under ActionBar when using ActionBarSherlock

I'm using ActionBarSherlock. On Android 3.0+, there's a subtle shadow under the ActionBar. But not on older Androids.
The problem is, that the shadow set in android:windowContentOverlay appears at the top of the Activity Window. And on older Androids, ActionBar is part of the Window. So the shadow overlays the top of the ActionBar, instead of overlaying the content under ActionBar.
Is there a way to solve this, without manually inserting the shadow to every Activity's layout?
As #wingman hinted in the comments, I overrided setContentView(...) in my base Activity like this:
#Override
public void setContentView(int layoutResId) {
View view = getLayoutInflater().inflate(layoutResId, null);
setContentView(view);
}
#Override
public void setContentView(View view) {
int wrapContent = ViewGroup.LayoutParams.WRAP_CONTENT;
int matchParent = ViewGroup.LayoutParams.MATCH_PARENT;
view.setLayoutParams(new ViewGroup.LayoutParams(matchParent, matchParent));
View shadow = new View(this);
shadow.setBackgroundResource(R.drawable.action_bar_shadow);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(matchParent,
wrapContent);
shadow.setLayoutParams(params);
RelativeLayout container = new RelativeLayout(this);
container.addView(view);
container.addView(shadow);
super.setContentView(container);
}

Categories

Resources