Regardless of whether or not it is a good idea to create a custom Snackbar, I have a custom Snackbar and I can't seem to get rid of the margins. I've tried several things such as adjusting in code and in layout as shown below. Nothing seems to work.
I am using the approach laid out by Yakiv here:
final CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) snackBarView.getLayoutParams();
params.setMargins(0,0,0,0);
and other approaches such as
android:layout_marginLeft="0dp"
android:layout_marginStart="0dp"
android:paddingLeft="0dp"
android:paddingStart="0dp" ...
The Snackbar:
My layout file:
<view
xmlns:android="http://schemas.android.com/apk/res/android"
class="android.support.design.internal.SnackbarContentLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#color/realBlack"
android:layout_marginLeft="0dp"
android:layout_marginStart="0dp"
android:paddingLeft="0dp"
android:paddingStart="0dp">
<TextView
android:id="#+id/snackbar_text"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_weight="1"
android:paddingTop="#dimen/design_snackbar_padding_vertical"
android:paddingBottom="#dimen/design_snackbar_padding_vertical"
android:paddingLeft="#dimen/design_snackbar_padding_horizontal"
android:paddingRight="#dimen/design_snackbar_padding_horizontal"
android:textAppearance="#style/TextAppearance.Design.Snackbar.Message"
android:maxLines="#integer/design_snackbar_text_max_lines"
android:layout_gravity="center_vertical|left|start"
android:ellipsize="end"
android:textAlignment="viewStart"
android:text="get some"/>
<Button
android:id="#+id/snackbar_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/design_snackbar_extra_spacing_horizontal"
android:layout_marginStart="#dimen/design_snackbar_extra_spacing_horizontal"
android:layout_gravity="center_vertical|right|end"
android:minWidth="48dp"
android:visibility="gone"
android:textColor="?attr/colorAccent"
style="?attr/borderlessButtonStyle"/>
</view>
The calling code:
_firmwareSnackbar = CustomSnackbar.make((ViewGroup) _rootView, Snackbar.LENGTH_INDEFINITE);
_firmwareSnackbar.setText(_flipper.getContext().getString(R.string.settings_firmware_available));
_firmwareSnackbar.setAction(_flipper.getContext().getString(R.string.settings_firmware_start), new View.OnClickListener() {
#Override
public void onClick(View view) {
_firmwareSnackbar.dismiss();
_firmwareSnackbar = null;
}
});
_firmwareSnackbar.show();
If you are using material components, then add this code to your style.xml file under values
<style name="Widget.SnackBar" parent="Widget.MaterialComponents.Snackbar">
<item name="android:layout_margin">0dp</item>
</style>
then
<style name="AppTheme" parent="Theme.MaterialComponents.NoActionBar">
<!-- Customize your theme here. -->
<item name="snackbarStyle">#style/Widget.SnackBar</item>
</style>
This will change margin for all existing snackBar in the app. So if you want to show a gap around SnackBar you can use padding.
val snackBar = Snackbar.make(homeLayout, "", Snackbar.LENGTH_INDEFINITE)
val snackBarLayout = snackBar.view as Snackbar.SnackbarLayout
snackBarLayout.setPadding(8, 0, 8, 0)
In dimens.xml.
Use this:
<dimen name="design_snackbar_padding_horizontal">0dp</dimen>
But remember that this will get applied to all the snackbars in your application.
Before showing the Snackbar you can remove the parent layout padding in the following way:
//...
_firmwareSnackbar.getView().setPadding(0,0,0,0);
_firmwareSnackbar.show();
Add to theme of App or Activity <item name="snackbarStyle">#style/Widget.Design.Snackbar</item>
You shoud remove paddings from a parent view:
View snackBarLayout = findViewById(R.id.mainLayout);
Snackbar globalSnackbar = Snackbar.make(snackBarLayout, "", Snackbar.LENGTH_INDEFINITE);
Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) globalSnackbar.getView();
layout.setPadding(0,0,0,0);
Related
I am using Material Components for creating the Choice chip. I have followed https://material.io/develop/android/components/chip/ document. There is enough stuff for creating a chip in XML but not get an idea of how to create choice chip programmatically.
I have used following code to creating chip dynamically but it creates action chip by default.
val chip = Chip(activity)
chip.text = ("Chip 1")
chipGpRow.addView(chip)
Check the Mike comment.
Otherwise you can define a simple layout (layout_chip_choice.xml) with the Chip and the style:
<com.google.android.material.chip.Chip
xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/Widget.MaterialComponents.Chip.Choice"
.../>
Then use in your code:
val chip = inflater.inflate(R.layout.layout_chip_choice, chipGpRow, false) as Chip
chip.text = ("Chip 1")
chipGpRow.addView(chip)
following is my code, hope its useful to you :
create item xml for chips and add style that you want
like here style="#style/Widget.MaterialComponents.Chip.Choice"
item_chip_category.xml
<com.google.android.material.chip.Chip xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/popin"
android:gravity="center"
android:paddingLeft="8dp"
android:paddingRight="8dp"
style="#style/Widget.MaterialComponents.Chip.Choice"
android:textAppearance="?android:attr/textAppearance"
android:textColor="#color/secondaryTextColor"
app:chipBackgroundColor="#color/colorAccent" />
activity.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="#font/popin"
android:padding="8dp"
android:text="Python Progrgrams"
android:textAlignment="center"
android:textAppearance="#style/TextAppearance.AppCompat.Medium"
android:textColor="#color/secondaryTextColor"
android:textStyle="bold" />
<com.google.android.material.chip.ChipGroup
android:id="#+id/chipsPrograms"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/text_margin"
android:paddingStart="#dimen/text_margin"
android:paddingEnd="#dimen/text_margin"
app:chipSpacing="8dp"
app:singleSelection="false">
</com.google.android.material.chip.ChipGroup>
</LinearLayout>
Activity.java
public void setCategoryChips(ArrayList<String> categorys) {
for (String category :
categorys) {
Chip mChip = (Chip) this.getLayoutInflater().inflate(R.layout.item_chip_category, null, false);
mChip.setText(category);
int paddingDp = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 10,
getResources().getDisplayMetrics()
);
mChip.setPadding(paddingDp, 0, paddingDp, 0);
mChip.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
}
});
chipsPrograms.addView(mChip);
}
}
You could either 1) create an xml layout for a chip that has the choice style and inflate it in code, similar to the ChipGroupDemoFragment example in the catalog: github.com/material-components/material-components-android/blob/… 2) create a custom theme that sets the default chipStyle to be #style/Widget.MaterialComponents.Chip.Choice I recommend #1 because it allows you the flexibility of dynamically creating chips of multiple styles.
XML
<com.google.android.material.chip.ChipGroup
android:id="#+id/chipGroupEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Activity.java
//init
ChipGroup chipGroupEmail = findViewById(R.id.chipGroupEmail);
//create a function
private void funAddChip(String name) {
Chip chip = new Chip(requireContext());
chip.setText(name);
chip.setCloseIconVisible(true);
chip.setMinWidth(100);
chip.setOnCloseIconClickListener(view -> {
try {
chipGroupEmail.removeView(view);
} catch (Exception e) {
Utils.Log_d("funAddChip Exception:-" + e);
}
});
chipGroupEmail.addView(chip);
}
I don't like the comment on setting the checkable attribute manually instead of the stylistic way. You lose other attributes, like ripple color and state list animator. Inflating a layout with your chip defined and including the style attribute with choice is the only way to do it as of now.
I have been trying to apply a style to a Chip created programmatically with context theme wrapper. This seems like the way to go, but Chip as an extension of AppCompatCheckBox does not define the four-argument constructor where the default style (action) could be overwritten with choice in my case. So the chip is always of type action ><.
I'm implementing a UI where a bottom sheet will appear above the keyboard with an EditText for the user to enter a value. The problem is the View is being partially overlapped by the keyboard, covering up the bottom of the bottom sheet.
Here is the Bottom Sheet and no keyboard.
Here is the Bottom Sheet with the keyboard showing.
What's the best method to ensure the entire Bottom Sheet is shown?
Thanks.
Just reposting #jblejder from this question Keyboard hides BottomSheetDialogFragment since it worked for me, to make it easier for others to find:
The most convenient way that I found to change this is by creating style:
<style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>
</style>
And set this in onCreate method of your BottomSheetDialogFragment:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(DialogFragment.STYLE_NORMAL, R.style.DialogStyle)
}
This is how it looks on my device:
==== UPDATE ====
As already mentioned in the Comments a few times, you might also need to set the state of the BottomSheetDialog to STATE_EXPANDED like in Nordknight's answer below
dialog = new BottomSheetDialog(getContext(), R.style.BottomSheetDialog);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = d.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
},0);
}
});
This might be a redundant answer. Although just pointing out the issue.
If you're using BottomSheetDialogFragment, the only way is to enable the attribute android:windowIsFloating to true. This will enable the whole window to be on top of whatever is trying to take the space behind it.
<style name="BottomSheetDialogThemeNoFloating" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowSoftInputMode">adjustResize|stateVisible</item>
</style>
Then in your onCreate() of your dialog, set this style.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// set the window no floating style
setStyle(DialogFragment.STYLE_NORMAL, R.style.AppRoundedBottomSheetDialogThemeNoFloating)
}
This is handy for those who frequently use bottom sheets and may want to deal with EditText and soft keyboard overlapping each other.
Note: The class KeyboardUtil by mikepenz has an issue in which on certain phones, the content view with input field is automatically pushed above keyboard despite giving bottom padding to the whole content view supplied.
dialog = new BottomSheetDialog(getContext(), R.style.BottomSheetDialog);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = d.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
},0);
}
});
This code works fine at Fragment's onCreateView method (thanks for ADM)
Some answers seem to do the trick better than others but will need modification when using the new material design components instead of the older support libraries while also using kotlin
Hope this will help someone.
BottomSheetDialog(this, R.style.DialogStyle).apply {
setContentView(layoutInflater.inflate(R.layout.bottom_sheet, null))
window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
findViewById<EditText>(R.id.time_et)?.requestFocus()
show()
}
layout/bottom_sheet.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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="wrap_content"
android:background="#ffffff"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Time"
android:textColor="#000000"
android:textSize="24sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<EditText
android:id="#+id/time_et"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="numberSigned"
android:minWidth="50dp"
android:text="15" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="min" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="#000"
android:text="Save"
android:textColor="#fff" />
</LinearLayout>
</ScrollView>
styes.xml (Split for v-21 for using statusBarColor)
<style name="DialogStyle" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>
</style>
A BottomSheetDialog can be helpful for this. it will open with Softkeyboard open with focus on edit text.But user can still close the Softkeyboard and Dialog will be reset to Bottom. Again focusing will make dialog appear at top of Softkeyboard.
public void showDialog() {
final BottomSheetDialog dialog=new BottomSheetDialog(this);
dialog.setContentView(R.layout.item_dialog);
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
dialog.show();
}
You can make the BottomSheetDialog expanded over keyboard . But for this you need to call it after SoftKeyboard Open. the Expand code is .
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
I have tested it on DialogInterface.OnShowListener() but its not working . Tested with it 1 second delay its working . But Delay is not the solution . You need to figure out the on which action you should expand the dialog.
final BottomSheetDialog dialog=new BottomSheetDialog(this);
dialog.setContentView(R.layout.item_dialog);
dialog.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE|
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
}
},2000);
dialog.show();
An updated answer for those using Material Components theme, and also an improved answer to remove the need to add anything into each dialog's onCreate().
In your main AppTheme style, you can add the attribute bottomSheetDialogTheme to apply the style to all of your BottomSheetDialogFragments:
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
<item name="colorPrimary">#color/primary</item>
<item name="colorPrimaryDark">#color/primary_dark</item>
<item name="colorAccent">#color/accent</item>
<item name="bottomSheetDialogTheme">#style/BottomSheetDialogStyle</item>
</style>
So with the above, no need to add anything to your BottomSheetDialogFragment code.
And then, as previous answers, your Dialog style, noting to also match the style to the same Material Components library (or you'll get some weird looking buttons, edittexts etc):
<style name="BottomSheetDialogStyle" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowSoftInputMode">adjustResize</item>
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="colorPrimary">#color/primary</item>
<item name="colorPrimaryDark">#color/primary_dark</item>
<item name="colorAccent">#color/accent</item>
</style>
Note that I am adding my app theme colors back in here; as you can't have multiple inheritance in Android styles, you may want these colors defining here so any buttons and accents align with the rest of your app.
private fun enterMobileNumberPopUp() {
val dialog = BottomSheetDialog(this,R.style.DialogStyle)
val view = layoutInflater.inflate(R.layout.layout_otp, null)
dialog.setContentView(view)
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
dialog.show()}
THIS IS THE MOST EASY WAY AND BEST WAY TO HANDLE BOTTOM SHEET DIALOG
YOU CAN CALL THIS IN METHOD
<style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>
Style reference
This one working
BottomSheetDialog dialog = new BottomSheetDialog(this, R.style.DialogStyle);
View sheetView = getLayoutInflater().inflate(R.layout.dialog_remark, null);
Objects.requireNonNull(dialog.getWindow())
.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE);
dialog.setContentView(sheetView);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
View bottomSheetInternal = d.findViewById(com.google.android.material.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
dialog.show();
add this style to your styles.xml
<style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustPan</item>
</style>
add your layout like this
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="#+id/scrollview"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="8dp"
android:fontFamily="#font/montserratmedium"
android:text="Add Remarks"
android:textColor="#android:color/black"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="24dp"
android:fontFamily="#font/montserratmedium"
android:text="Branch"
android:textColor="#8B8B8B"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:fontFamily="#font/montserratmedium"
android:text="BLR-CO-SINDHUBHAVAN-384"
android:textColor="#android:color/black"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="24dp"
android:fontFamily="#font/montserratmedium"
android:text="Enter Remarks"
android:textColor="#8B8B8B"
android:textSize="18sp" />
<EditText
android:id="#+id/input_remark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_marginTop="8dp"
android:background="#drawable/remark_inputbg"
android:gravity="start"
android:inputType="textMultiLine"
android:lines="5" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:background="#drawable/reset_bg"
android:padding="8dp"
android:text="CANCEL" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:background="#4F4DBB"
android:padding="8dp"
android:text="CANCEL"
android:textColor="#android:color/white" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</ScrollView>
bottomSheetDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
It will work for sure.
Just write the following programmatically
override fun setupDialog(dialog: Dialog, style: Int) {
super.setupDialog(dialog, style)
dialog.window?.setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE or
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
);
}
Kotlin, +viewBinding, +by using the accepted answer's dialog style
val bottomSheet = BottomSheetDialog(this, R.style.BottomSheetDialogStyle)
val binding = [YourSheetBinding].inflate(LayoutInflater.from(YourActivity.this))
bottomSheet.setContentView(binding.root)
bottomSheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
bottomSheet.show()
override fun onStart() {
super.onStart()
bottomSheetBehavior?.skipCollapsed = true
bottomSheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
}
Putting this in BottomSheet helped without setting styles and without ScrollView
(correct me if I'm wrong or if I'm missing something)
This trick solved me
in manifest put
android:windowSoftInputMode="adjustPan"
in your activity
and
bottomSheetDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
bottomSheetDialog.getBehavior().setState(BottomSheetBehavior.STATE_EXPANDED);
For this, I found an AlertDialog worked best. While it doesn't sit flush against the bottom or side of the screen, it still looks good enough.
First, create the AlertDialog with your view.
val view = LayoutInflater.from(context).inflate(R.layout.alert, null)
dialog = AlertDialog.Builder(context)
.setView(view)
.create()
Next, set the gravity.
dialog.window.attributes.gravity = Gravity.BOTTOM
And finally, show it.
dialog.show()
You can also bind the keyboard to stay with the dialog, by using an onDismissListener.
After showing the AlertDialog, I force up the keyboard.
Call this method, passing in your EditText.
fun showKeyboard(view: View?) {
if (view == null) return;
val imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
And for dismissing within the onDismissListener.
private fun hideKeyboard() {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0)
}
My answer might be useful for someone who is still looking for solution. If keyboard is covering edittext in BottomSheetDialogFragment then in setupDialog() method create instance of a class KeyboardUtil and pass your rootview.
#Override
public void setupDialog(final Dialog dialog, int style) {
super.setupDialog(dialog, style);
View view = View.inflate(getActivity(), R.layout.reopen_dialog_layout, null);
new KeyboardUtil(getActivity(), view);
}
Create a new class
public class KeyboardUtil {
private View decorView;
private View contentView;
//a small helper to allow showing the editText focus
ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
decorView.getWindowVisibleDisplayFrame(r);
//get screen height and calculate the difference with the useable area from the r
int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
int diff = height - r.bottom;
//if it could be a keyboard add the padding to the view
if (diff != 0) {
// if the use-able screen height differs from the total screen height we assume that it shows a keyboard now
//check if the padding is 0 (if yes set the padding for the keyboard)
if (contentView.getPaddingBottom() != diff) {
//set the padding of the contentView for the keyboard
contentView.setPadding(0, 0, 0, diff);
}
} else {
//check if the padding is != 0 (if yes reset the padding)
if (contentView.getPaddingBottom() != 0) {
//reset the padding of the contentView
contentView.setPadding(0, 0, 0, 0);
}
}
}
};
public KeyboardUtil(Activity act, View contentView) {
this.decorView = act.getWindow().getDecorView();
this.contentView = contentView;
//only required on newer android versions. it was working on API level 19
if (Build.VERSION.SDK_INT >= 19) {
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
}
}
/**
* Helper to hide the keyboard
*
* #param act
*/
public static void hideKeyboard(Activity act) {
if (act != null && act.getCurrentFocus() != null) {
InputMethodManager inputMethodManager = (InputMethodManager) act.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(act.getCurrentFocus().getWindowToken(), 0);
}
}
public void enable() {
if (Build.VERSION.SDK_INT >= 19) {
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
}
}
public void disable() {
if (Build.VERSION.SDK_INT >= 19) {
decorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
}
}
}
See https://stackoverflow.com/a/61813321/2914140:
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
return dialog
}
But if a layout is not tall enough, you can use https://stackoverflow.com/a/66287187/2914140 instead. It will open BottomSheetDialog almost fullscreen:
<style name="BottomSheetDialogTheme" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowSoftInputMode">adjustResize|stateVisible</item>
</style>
Fiddling with BottomSheetDialogFragmentwasn't really worth it. So I just changed it to a simple DialogFragment and just set its gravity to bottom:
window.setGravity(Gravity.BOTTOM);
Worked like a charm.
I changed the Floating Action Button backgroundTintList color by using the following code:
fab.setBackgroundTintList(ColorStateList.valueOf(mResources.getColor(R.color.fab_color)));
But I end up getting the following on API 4.4.2:
Everything looks fine on API 21 <= but anything below API 21, I have this problem for the FAB.
I am programmatically creating the FAB like so:
FloatingActionButton fab = new FloatingActionButton(this);
CoordinatorLayout.LayoutParams layoutParams = new CoordinatorLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
fab.setLayoutParams(layoutParams);
layoutParams.rightMargin = mResources.getDimensionPixelSize(R.dimen.activity_horizontal_margin);
((CoordinatorLayout) findViewById(R.id.coordinatorLayout)).addView(fab);
CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
p.setAnchorId(R.id.appBarLayout);
p.anchorGravity = Gravity.BOTTOM | Gravity.END;
fab.setLayoutParams(p);
fab.setVisibility(View.VISIBLE);
fab.setBackgroundTintList(ColorStateList.valueOf(mResources.getColor(R.color.fab_color)));
fab.setImageDrawable(getResources().getDrawable(R.drawable.ic_button));
I also happened to run by the official source code for the FloatingActionButton and I saw that they are instantiating a borderDrawable here:
#Override
void setBackgroundDrawable(Drawable originalBackground, ColorStateList backgroundTint,
PorterDuff.Mode backgroundTintMode, int rippleColor, int borderWidth) {
// Now we need to tint the original background with the tint
mShapeDrawable = DrawableCompat.wrap(originalBackground.mutate());
DrawableCompat.setTintList(mShapeDrawable, backgroundTint);
if (backgroundTintMode != null) {
DrawableCompat.setTintMode(mShapeDrawable, backgroundTintMode);
}
final Drawable rippleContent;
if (borderWidth > 0) { // BORDER DRAWABLE RIGHT HERE!!
mBorderDrawable = createBorderDrawable(borderWidth, backgroundTint);
rippleContent = new LayerDrawable(new Drawable[]{mBorderDrawable, mShapeDrawable});
} else {
mBorderDrawable = null;
rippleContent = mShapeDrawable;
}
mRippleDrawable = new RippleDrawable(ColorStateList.valueOf(rippleColor),
rippleContent, null);
mShadowViewDelegate.setBackgroundDrawable(mRippleDrawable);
mShadowViewDelegate.setShadowPadding(0, 0, 0, 0);
}
I ended adding:
app:borderWidth="0dp"
this doesn't create borderDrawable and border is not visible.
just change the coloraccent in styles file
<item name="colorAccent">#color/colorAccent</item>
add color which u want as your background color for FAB
EDIT: okk.. well here is an alternative what you can do .. define this FAB in your xml
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
app:backgroundTint="#color/fab_color"
android:layout_margin="#dimen/fab_margin"
android:src="#android:drawable/ic_dialog_email" />
and it will make changes and then you don't need to be do as programmatically.
To just change background color use: app:backgroundTint="#4000FF00"
Eg:
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="54dp"
android:layout_marginRight="16dp"
android:clickable="true"
android:src="#drawable/ic_edit"
app:layout_anchor="#id/xxxx"
app:rippleColor="#android:color/white"
app:backgroundTint="#00FF00"
app:layout_anchorGravity="bottom|end|right"
/>
But if you want to make it transparent, use app:elevation and app:pressedTranslationZ property.
Eg:
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="54dp"
android:layout_marginRight="16dp"
android:clickable="true"
android:src="#drawable/ic_edit"
app:layout_anchor="#id/xxx"
app:borderWidth="0dp"
app:rippleColor="#android:color/white"
app:backgroundTint="#4000FF00"
app:elevation="0dp"
app:pressedTranslationZ="0dp"
app:layout_anchorGravity="bottom|end|right"
/>
Those properties are used to give view effect on click and elevation to button.
You probably need to change the colors programmatically in a backwards compatible way:
DrawableCompat.setTintList(DrawableCompat.wrap(fab.getDrawable()), tintColor); <- icon
DrawableCompat.setTintList(DrawableCompat.wrap(fab.getBackground()), backgroundTintColor); <- background
Well I think some people still get this situation so It may help somenone
In attributes section there is two backgroundTint attributes second one is for
to change border color I think I hope it helps someone
Basically I want the searachview to expand and collapse when there is a imagebutton behind which should disappear when icon is clicked and view should appear when searchview collapses.
I am using search view not in action bar .When i click on the search icon it expands only half the screen but it should expand complete width but should wrap_content when I close the searchview.
<SearchView
android:id="#+id/searchView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true">
I also tried :
android.view.ViewGroup.LayoutParams params = searchview.getLayoutParams();
params.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
But I am getting error here setLayoutParams it says "add to cast"
At first you're getting an exception, because if you look into search_view.xml located in
\Android\android-sdk\platforms\android-18\data\res\layout\
You'll find out that SearchView is basically simple LinearLayout merging several widgets together. That's why you are getting class cast exception. Instead of
android.view.ViewGroup.LayoutParams params = searchview.getLayoutParams();
use
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) searchview.getLayoutParams();
or just import correct class and then you can simply use this
import android.widget.LinearLayout.LayoutParams;
...
LayoutParams params = (LayoutParams) searchview.getLayoutParams();
than you can use LayoutParams without any prefix.
But I don't think that setting LayoutParams to wrap content will help. I would wrap your SearchView and ImageButton to RelativeLayout, where you could specify view position relative to the other views. Then simply set SearchView width to fill parent, so it could fill remaining space.
Have you tried the XML-attribute android:maxWidth like described here: http://developer.android.com/reference/android/widget/SearchView.html#attr_android:maxWidth
I am using the SearchView from actionbarsherlock and used the corresponding java-method to stretch the SearchView over the available width of the actionbar.
<item
android:id="#+id/action_search"
android:icon="#drawable/search_b"
android:orderInCategory="3"
android:title="Search"
app:showAsAction="always|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView" />
<item
android:id="#+id/action_scan"
android:icon="#drawable/scan_b"
android:title="Scan"
android:orderInCategory="2"
app:showAsAction="ifRoom|collapseActionView" />
<item
android:id="#+id/action_add_cusomer"
android:icon="#drawable/add_cust_b"
android:title="Add Customer"
android:orderInCategory="1"
app:showAsAction="ifRoom|collapseActionView" />
</menu>
After Clicking on Search icon:
Try this according to your needs but dont think to work on your own button, you can move default searchButton to right side with giving wrap_content width parameter and then when you click to search set width to match_parent then again when you close it set width to wrap_content
Use your searchView child of RelativeLayout and be sure about right LayoutParams(RelativeLayout.LayoutParams)
<?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="wrap_content"
android:background="#color/counter_text_color" >
<Button
android:id="#+id/buttonLeftMenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerInParent="true"
android:background="#drawable/ic_drawer" />
<ImageView
android:id="#+id/iv_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#drawable/actionbar_logo" />
<TextView
android:id="#+id/tw_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="YOUR "
android:textSize="24sp" />
<SearchView
android:id="#+id/searchView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#+id/buttonRightMenu" />
<Button
android:id="#+id/buttonRightMenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerInParent="true"
android:background="#drawable/ic_action_settings" />
</RelativeLayout>
and at your class
searchView.setOnSearchClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.RIGHT_OF, R.id.buttonLeftMenu);
params.addRule(RelativeLayout.LEFT_OF, R.id.buttonRightMenu);
searchView.setLayoutParams(params);
}
});
searchView.setOnCloseListener(new OnCloseListener() {
#Override
public boolean onClose() {
// TODO Auto-generated method stub
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.LEFT_OF, R.id.buttonRightMenu);
searchView.setLayoutParams(params);
return false;
}
});
I'm working on an Android app and I have an AlertDialog subclass. I would like to put 2 ImageButtons on the right side of the title area of the dialog (similar to an the ActionBar in an Activity). I'm using setCustomTitle() to do this, which replaces the title area with a custom view of my own creation. This works fine, but the styling of my custom title area is not the same as the standard title styling (height, color, separator, etc).
My question is: with the understanding that styling varies by OS version and manufacturer, how can I style my custom title in the dialog so that it will match the standard title styling for other AlertDialogs?
Here is an image of anAlertDialog with standard styling (this is from ICS, but I want to be able to match any variant -- not this particular style)
And here is an image of an AlertDialog with custom title and buttons (note how the title height and color don't match the standard dialog)
EDIT: I can't just add the ImageButtons to the standard title view, because I don't have access to it. If you know of a (reliable, non-hack) method for me to add buttons to the standard title area, I would accept that as well.
Given that there is new interest in this question, let me elaborate about how I "solved" this.
First, I use ActionBarSherlock in my app. This is not necessary, I suppose, though it helps a lot because the styles and themes defined in the ABS project allow me to mimic the Holo theme on pre-ICS devices, which provides a consistent experience in the app.
Second, my "dialog" is no longer a dialog -- it's an activity themed as a dialog. This makes manipulation of the view hierarchy simpler, because I have complete control. So adding buttons to the title area is now trivial.
Here are the screenshots (2.2 device and 4.1 emulator). Note that the only significant styling difference is the EditText, which I have chosen not to address.
Here is my onCreate in my dialog activity:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_tag);
setTitle(R.string.tag_dialog_title);
View sherlockTitle = findViewById(android.R.id.title);
if (sherlockTitle != null) {
sherlockTitle.setVisibility(View.GONE);
}
View sherlockDivider = findViewById(R.id.abs__titleDivider);
if (sherlockDivider != null) {
sherlockDivider.setVisibility(View.GONE);
}
// setup custom title area
final View titleArea = findViewById(R.id.dialog_custom_title_area);
if (titleArea != null) {
titleArea.setVisibility(View.VISIBLE);
TextView titleView = (TextView) titleArea.findViewById(R.id.custom_title);
if (titleView != null) {
titleView.setText(R.string.tag_dialog_title);
}
ImageButton cancelBtn = (ImageButton) titleArea.findViewById(R.id.cancel_btn);
cancelBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
cancelBtn.setVisibility(View.VISIBLE);
ImageButton okBtn = (ImageButton) titleArea.findViewById(R.id.ok_btn);
okBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// do stuff here
finish();
}
});
okBtn.setVisibility(View.VISIBLE);
}
}
And here is the relevant layout for the activity:
<LinearLayout
android:orientation="vertical"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<LinearLayout
android:id="#+id/dialog_custom_title_area"
android:orientation="vertical"
android:fitsSystemWindows="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingRight="10dp">
<TextView
android:id="#+id/custom_title" style="?android:attr/windowTitleStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:minHeight="#dimen/abs__alert_dialog_title_height"
android:paddingLeft="16dip"
android:paddingRight="16dip"
android:textColor="#ffffff"
android:gravity="center_vertical|left" />
<ImageButton
android:id="#+id/ok_btn"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:minWidth="#dimen/abs__action_button_min_width"
android:minHeight="#dimen/abs__alert_dialog_title_height"
android:scaleType="center"
android:src="#drawable/ic_action_accept"
android:background="#drawable/abs__item_background_holo_dark"
android:visibility="visible"
android:layout_gravity="center_vertical"
android:contentDescription="#string/acc_done"/>
<ImageButton
android:id="#+id/cancel_btn"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:minWidth="#dimen/abs__action_button_min_width"
android:minHeight="#dimen/abs__alert_dialog_title_height"
android:scaleType="center"
android:src="#drawable/ic_action_cancel"
android:background="#drawable/abs__item_background_holo_dark"
android:visibility="visible"
android:layout_gravity="center_vertical"
android:contentDescription="#string/acc_cancel"
/>
</LinearLayout>
<View
android:id="#+id/dialog_title_divider"
android:layout_width="fill_parent"
android:layout_height="2dip"
android:background="#color/abs__holo_blue_light" />
</LinearLayout>
<RelativeLayout
android:id="#+id/list_suggestions_layout"
android:layout_height="wrap_content"
android:layout_width="fill_parent">
<!-- this is where the main dialog area is laid out -->
</RelativeLayout>
</LinearLayout>
And finally, in my AndroidManifext.xml, here is how I define my TagActivity:
<activity
android:icon="#drawable/ic_home"
android:name=".activity.TagActivity"
android:theme="#style/Theme.Sherlock.Dialog"/>
OK, maybe it is not the super perfect solution and maybe it is a bad solution, but I tried this on android 2.3.7 and android 4.1.2:
2.3.7 (real device)
4.1.2 (emulator)
We start by creating a dialog Title style to make sure we have some space for our icons:
res/values/dialogstyles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Dialog" parent="#android:style/Theme.Dialog">
<item name="android:windowTitleStyle">#style/MyOwnDialogTitle</item>
</style>
<style name="MyOwnDialogTitle">
<!-- we need to make sure our images fit -->
<item name="android:layout_marginRight">100dp</item>
</style>
</resources>
res/values-v11/dialogstyles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Dialog" parent="#android:style/Theme.Holo.Dialog">
<item name="android:windowTitleStyle">#style/MyOwnDialogTitle</item>
</style>
</resources>
Then we create our DialogFragment with two tricks:
set the style in the onCreate:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NORMAL, R.style.Dialog);
}
override onCreateView and add our layout (of buttons) to the Dialog (see comments)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//we need the view to remove the tree observer (that's why it is final)
final View view = inflater.inflate(R.layout.dialog_custom, container);
getDialog().setTitle("Shush Dialog");
//register a layout listener to add our buttons
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
#Override
public void onGlobalLayout() {
//inflate our buttons
View menu = LayoutInflater.from(getActivity()).inflate(R.layout.layout_mymenu, null);
//get the root view of the Dialog (I am pretty sure this is the weakest link)
FrameLayout fl = ((FrameLayout) getDialog().getWindow().getDecorView());
//get the height of the root view (to estimate the height of the title)
int height = fl.getHeight() - fl.getPaddingTop() - fl.getPaddingBottom();
//to estimate the height of the title, we subtract our view's height
//we are sure we have the heights btw because layout is done
height = height - view.getHeight();
//prepare the layout params for our view (this includes setting its width)
//setting the height is not necessary if we ensure it is small
//we could even add some padding but anyway!
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, height);
params.gravity = Gravity.RIGHT | Gravity.TOP;
//add the view and we are done
fl.addView(menu, params);
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
else
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
return view;
}
Alright if it just images, then you just have ensure that everything that you create in xml is scaled by density pixels or DP for short. Most simple coding that sets paint are usually set by pixels as well and may need a manual coding version to density pixels.