I have been struggling to put this to work. The app resizes well as long as i keep the status bar visible. According to this post it is an android bug, but the issue is closed but not resolved.
From all that i read, playing with Insets should do the trick but i can't put it to work. Not sure even if should go this way.
Following this post i added the below code to OnCreate.
ViewCompat.setOnApplyWindowInsetsListener(getWindow().getDecorView().getRootView(), new OnApplyWindowInsetsListener() {
#Override
public WindowInsetsCompat onApplyWindowInsets(View view, WindowInsetsCompat insets) {
((ViewGroup.MarginLayoutParams) view.getLayoutParams()).topMargin =
insets.getSystemWindowInsetTop();
return insets.consumeSystemWindowInsets();
}
});
It throws the exception:
java.lang.ClassCastException: android.view.WindowManager$LayoutParams
cannot be cast to android.view.ViewGroup$MarginLayoutParams
The post goes on but i am stuck here and have doubts if i am going the right way.
Bellow the testing code i am using if someone wants to try.
Works well until the statusbar is removed by adding <item name="android:windowFullscreen">true</item> to AppTheme.
AndroidManifest.xml:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
activity_mail.xml:
<!-- this control should be position static -->
<TextView
android:layout_height="50dp"
android:layout_width="fill_parent"
android:background="#color/colorPrimaryDark"
android:text="static window at top"
android:gravity="center"
/>
<!-- the resizable view -->
<android.support.v7.widget.RecyclerView
android:id="#+id/my_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:transcriptMode="normal">
</android.support.v7.widget.RecyclerView>
<!-- use this EditText box to call softKeyboard-->
<android.support.v7.widget.AppCompatEditText
android:id="#+id/cv_bottom_bar_edit"
style="#style/Widget.AppCompat.AutoCompleteTextView"
android:layout_width="match_parent"
android:layout_height="50dp"
android:textSize="18sp"
android:background="#color/colorPrimaryDark"
android:gravity="center"
/>
row.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F06060"
android:layout_margin="30dp"
android:padding="5dp"
android:textSize="25sp"
android:gravity="center"
>
MainActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = findViewById(R.id.my_list);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
String[] myDataset = new String[]{"1", "2", "3","4","5","6","7","8","9"};
mAdapter = new MyAdapter(myDataset);
mRecyclerView.setAdapter(mAdapter);
}
Update:
I moved the windowFullscreen attribute from manifest to AppTheme because Android was not reading it from the manifest.
public class AndroidBug5497Workaround extends AppCompatActivity {
// For more information, see https://issuetracker.google.com/issues/36911528
// To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
private ViewGroup contentContainer;
private ViewTreeObserver viewTreeObserver;
private Rect contentAreaOfWindowBounds = new Rect();
private LinearLayout.LayoutParams rootViewLayout; //-->change to the view root control type of your view.
private int usableHeightPrevious = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
contentContainer = findViewById(android.R.id.content);
rootViewLayout = (LinearLayout.LayoutParams) contentContainer.getLayoutParams();
}
#Override
protected void onPause() {
super.onPause();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.removeOnGlobalLayoutListener(listener);
}
}
#Override
protected void onResume() {
super.onResume();
if (viewTreeObserver == null || !viewTreeObserver.isAlive()) {
viewTreeObserver = contentContainer.getViewTreeObserver();
}
viewTreeObserver.addOnGlobalLayoutListener(listener);
}
#Override
protected void onDestroy() {
super.onDestroy();
contentContainer = null;
viewTreeObserver = null;
}
ViewTreeObserver.OnGlobalLayoutListener listener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds);
int usableHeightNow = contentAreaOfWindowBounds.height();
if (usableHeightNow != usableHeightPrevious) {
rootViewLayout.height = usableHeightNow;
contentContainer.layout(contentAreaOfWindowBounds.left, contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom);
contentContainer.requestLayout();
usableHeightPrevious = usableHeightNow;
}
}
};
}
Got it from facebook/react-native issue on github. Slight simplified for a common activity. Works good with portrait and landscape, from api 21, but it not much more tested than that. Use with care.
Notice this line:
((ViewGroup.MarginLayoutParams) view.getLayoutParams()).topMargin =
insets.getSystemWindowInsetTop();//what's the parent of "view"
According to getLayoutParams says, you should know what's the parent of "view" ,for example, if the parent is FrameLayout, then do like this:
((FrameLayout.LayoutParams) view.getLayoutParams()).topMargin =
insets.getSystemWindowInsetTop();
If the parent is relativelayout or linearlayout, also switch to definite type like above.
Edited: try this:
((WindowManager.LayoutParams) view.getLayoutParams()).topMargin =
insets.getSystemWindowInsetTop();
Related
I have a view with a Edittext field on top of an ImageView. When the keyboard comes up I want the window to resize so that EditText is no longer hidden by the keyboard. In the AndroidManifest file I declared android:windowSoftInputMode="adjustResize" and the screen is resized but the issue is that I want the ImageView to not be re-sized.
How can I make the ImageView unaffected?
Could I inflate an additional layout with just the ImageView or will the resize still affect it?
The full solution involves a few key points
Use RelativeLayout, so that Views can be setup to overlap one another
Align the EditText with the bottom of the Windows using android:layout_alignParentBottom="true"
Use android:windowSoftInputMode="adjustResize" in your manifest, so that the bottom of the Window changes when the keyboard pops up (as you mentioned)
Put the ImageView inside a ScrollView so that the ImageView can be larger than the Window, and disable scrolling on the ScrollView by using ScrollView#setEnabled(false)
Here is the layout file
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.so3.MainActivity">
<ScrollView
android:id="#+id/scroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/stickfigures"/>
</ScrollView>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#android:color/holo_blue_bright"
android:text="Please enter text"
android:textSize="40sp"
android:gravity="center_horizontal"/>
</RelativeLayout>
Here is my Activity
package com.so3;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ScrollView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ScrollView sv = (ScrollView)findViewById(R.id.scroll);
sv.setEnabled(false);
}
}
My AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.so3" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.so3.MainActivity"
android:windowSoftInputMode="adjustResize"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Screen shots of my solution
Adding ScrollView was making my image scrollable which I wanted to avoid so I used this samples-keyboardheight calculator and onKeyboardHeightChanged recalculated position of the bottom Edittext placed it above Keyboard and used this flag in Manifest.
android:windowSoftInputMode="adjustNothing|stateHidden"
Here is KeyboardHeightProvider :
import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager.LayoutParams;
import android.widget.PopupWindow;
/**
* The keyboard height provider, this class uses a PopupWindow
* to calculate the window height when the floating keyboard is opened and closed.
*/
public class KeyboardHeightProvider extends PopupWindow {
/** The tag for logging purposes */
private final static String TAG = "sample_KeyboardHeightProvider";
/** The keyboard height observer */
private KeyboardHeightObserver observer;
/** The cached landscape height of the keyboard */
private int keyboardLandscapeHeight;
/** The cached portrait height of the keyboard */
private int keyboardPortraitHeight;
/** The view that is used to calculate the keyboard height */
private View popupView;
/** The parent view */
private View parentView;
/** The root activity that uses this KeyboardHeightProvider */
private Activity activity;
/**
* Construct a new KeyboardHeightProvider
*
* #param activity The parent activity
*/
public KeyboardHeightProvider(Activity activity) {
super(activity);
this.activity = activity;
LayoutInflater inflator = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
this.popupView = inflator.inflate(R.layout.popupwindow, null, false);
setContentView(popupView);
setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_RESIZE | LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
parentView = activity.findViewById(android.R.id.content);
setWidth(0);
setHeight(LayoutParams.MATCH_PARENT);
popupView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (popupView != null) {
handleOnGlobalLayout();
}
}
});
}
/**
* Start the KeyboardHeightProvider, this must be called after the onResume of the Activity.
* PopupWindows are not allowed to be registered before the onResume has finished
* of the Activity.
*/
public void start() {
if (!isShowing() && parentView.getWindowToken() != null) {
setBackgroundDrawable(new ColorDrawable(0));
showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0);
}
}
/**
* Close the keyboard height provider,
* this provider will not be used anymore.
*/
public void close() {
this.observer = null;
dismiss();
}
/**
* Set the keyboard height observer to this provider. The
* observer will be notified when the keyboard height has changed.
* For example when the keyboard is opened or closed.
*
* #param observer The observer to be added to this provider.
*/
public void setKeyboardHeightObserver(KeyboardHeightObserver observer) {
this.observer = observer;
}
/**
* Get the screen orientation
*
* #return the screen orientation
*/
private int getScreenOrientation() {
return activity.getResources().getConfiguration().orientation;
}
/**
* Popup window itself is as big as the window of the Activity.
* The keyboard can then be calculated by extracting the popup view bottom
* from the activity window height.
*/
private void handleOnGlobalLayout() {
Point screenSize = new Point();
activity.getWindowManager().getDefaultDisplay().getSize(screenSize);
Rect rect = new Rect();
popupView.getWindowVisibleDisplayFrame(rect);
// REMIND, you may like to change this using the fullscreen size of the phone
// and also using the status bar and navigation bar heights of the phone to calculate
// the keyboard height. But this worked fine on a Nexus.
int orientation = getScreenOrientation();
int keyboardHeight = screenSize.y - rect.bottom;
if (keyboardHeight == 0) {
notifyKeyboardHeightChanged(0, orientation);
}
else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
this.keyboardPortraitHeight = keyboardHeight;
notifyKeyboardHeightChanged(keyboardPortraitHeight, orientation);
}
else {
this.keyboardLandscapeHeight = keyboardHeight;
notifyKeyboardHeightChanged(keyboardLandscapeHeight, orientation);
}
}
/**
*
*/
private void notifyKeyboardHeightChanged(int height, int orientation) {
if (observer != null) {
observer.onKeyboardHeightChanged(height, orientation);
}
}
public interface KeyboardHeightObserver {
void onKeyboardHeightChanged(int height, int orientation);
}
}
popupwindow.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/popuplayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:orientation="horizontal"/>
Here is MainActivity.java :
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends AppCompatActivity implements KeyboardHeightProvider.KeyboardHeightObserver {
private KeyboardHeightProvider keyboardHeightProvider;
private ViewGroup relativeView;
private float initialY;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
keyboardHeightProvider = new KeyboardHeightProvider(this);
relativeView = findViewById(R.id.bottomEditor);
relativeView.post(() -> initialY = relativeView.getY());
View view = findViewById(R.id.activitylayout);
view.post(() -> keyboardHeightProvider.start());
}
#Override
public void onKeyboardHeightChanged(int height, int orientation) {
if(height == 0){
relativeView.setY(initialY);
relativeView.requestLayout();
}else {
float newPosition = initialY - height;
relativeView.setY(newPosition);
relativeView.requestLayout();
}
}
#Override
public void onPause() {
super.onPause();
keyboardHeightProvider.setKeyboardHeightObserver(null);
}
#Override
public void onResume() {
super.onResume();
keyboardHeightProvider.setKeyboardHeightObserver(this);
}
#Override
public void onDestroy() {
super.onDestroy();
keyboardHeightProvider.close();
}
}
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activitylayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
/>
<RelativeLayout
android:id="#+id/bottomEditor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
>
<EditText
android:id="#+id/edit_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:layout_toStartOf="#+id/btn_send"
android:hint="Add caption"
android:paddingBottom="12dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingStart="8dp"
android:paddingTop="12dp"
/>
<ImageButton
android:id="#+id/btn_send"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignBottom="#+id/edit_message"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="4dp"
android:layout_marginRight="4dp"
app:srcCompat="#android:drawable/ic_menu_send"
/>
</RelativeLayout>
</RelativeLayout>
P.S. : Keyboard height calculation code is copied from siebeprojects
Here is demo example app of implementation.
final View activityRootView = findViewById(R.id.mainScroll);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightView = activityRootView.getHeight();
int widthView = activityRootView.getWidth();
if (1.0 * widthView / heightView > 1) {
Log.d("keyboarddddd visible", "no");
relativeLayoutForImage.setVisibility(View.GONE);
relativeLayoutStatic.setVisibility(View.GONE);
//Make changes for Keyboard not visible
} else {
Log.d("keyboarddddd visible ", "yes");
relativeLayoutForImage.setVisibility(View.VISIBLE);
relativeLayoutStatic.setVisibility(View.VISIBLE);
//Make changes for keyboard visible
}
}
});
For me i did not want to assume that keyboards heights are a certain measurement. Whatever view your concerned about make a onTouchListener and then do this:
setOnTouchListener(new OnTouchListener() {
Runnable shifter=new Runnable(){
public void run(){
try {
int[] loc = new int[2];
//get the location of someview which gets stored in loc array
findViewById(R.id.someview).getLocationInWindow(loc);
//shift so user can see someview
myscrollView.scrollTo(loc[0], loc[1]);
}
catch (Exception e) {
e.printStackTrace();
}
}}
};
Rect scrollBounds = new Rect();
View divider=findViewById(R.id.someview);
myscollView.getHitRect(scrollBounds);
if (!divider.getLocalVisibleRect(scrollBounds)) {
// the divider view is NOT within the visible scroll window thus we need to scroll a bit.
myscollView.postDelayed(shifter, 500);
}
});
//essentially we make a runnable that scrolls to a new location of some view that you WANT visible on the screen. you execute that runnable only if its not within the scrollviews bounds (its not on the screen). This way it shifts the scrollview to the referenced view (in my case 'someview' which was a line divider).
In my opinion the easiest way to do this it is this combination of the two changes:
android:windowSoftInputMode="adjustResize"
in your AndroidManifest.xml
+
getWindow().setBackgroundDrawable(your_image_drawable);
in your activity in #onCreate() method
It works for me.
The best solution is to use a DialogFragment
Show dialog
DialogFragment.show(getSupportFragmentManager(), DialogFragment.TAG);
Full screen
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = new Dialog(getActivity(), R.style.MainDialog) { //set the style, the best code here or with me, we do not change
#Override
public void onBackPressed() {
super.onBackPressed();
getActivity().finish();
}
};
return dialog;
}
Style
<style name="MainDialog" parent="#android:style/Theme.Dialog">
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:windowFrame">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">false</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:background">#null</item>
<item name="android:windowAnimationStyle">#null</item>
</style>
Layout Activity
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
Layout dialog fragment
<?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="#color/transparent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:background="#color/background_transparent_60"
android:gravity="center_vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="#dimen/spacing_1_8dp"
android:layout_marginLeft="#dimen/spacing_1_8dp"
android:layout_marginRight="#dimen/spacing_1_8dp"
android:layout_weight="1"
android:hint="#string/comment_entry_hint"
android:inputType="textMultiLine"
android:maxLines="4"
android:textColor="#color/white"
android:textColorHint="#color/secondary_text_hint"
android:textSize="#dimen/text_2_12sp" />
<ImageView
android:layout_width="#dimen/livestream_comment_height"
android:layout_height="#dimen/livestream_comment_height"
android:layout_margin="#dimen/spacing_1_8dp"
android:src="#drawable/ic_send" />
</LinearLayout>
</RelativeLayout>
The solution that worked for me was in AndroidManifest.xml in that activity tag just put
android:windowSoftInputMode="stateHidden|adjustResize|adjustNothing"
All set..Hope this will work for you.
final View activityRootView = findViewById(R.id.mainScroll);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightView = activityRootView.getHeight();
int widthView = activityRootView.getWidth();
if (1.0 * widthView / heightView > 1) {
Log.d("keyboarddddd visible", "no");
relativeLayoutForImage.setVisibility(View.GONE);
relativeLayoutStatic.setVisibility(View.GONE);
//Make changes for Keyboard not visible
//relativeLayoutForImage.setVisibility(View.VISIBLE);
//relativeLayoutStatic.setVisibility(View.VISIBLE);
} else {
Log.d("keyboarddddd visible ", "yes");
relativeLayoutForImage.setVisibility(View.VISIBLE);
relativeLayoutStatic.setVisibility(View.VISIBLE);
//Make changes for keyboard visible
// relativeLayoutForImage.setVisibility(View.GONE);
//relativeLayoutStatic.setVisibility(View.GONE);
}
}
});
I am using MergeRecycleAdapter with recyclerview to add multiple views and adapters.When I put them inside cardview and Edittext view is focused keyboard is opening and immediately closing.Without cardview it works fine like Resizing screen. For that I have written one sample activity.I couldn't figure out where I am missing.
Manifest
<activity
android:name=".activity.KeyboardActivity"
android:configChanges="navigation|orientation|screenSize"
android:label="#string/ibhubs"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Layout xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="afterDescendants"
android:focusable="false"
android:isScrollContainer="false" />
</android.support.v7.widget.CardView>
</LinearLayout>
Activity code
public class KeyboardActivity extends BaseActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.keyboard_merge_recycler_adapter);
initializeViews();
}
private void initializeViews() {
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
MergeRecycleAdapter mergeRecycleAdapter = new MergeRecycleAdapter();
for (int i = 0; i < 10; i++) {
EditText editText = new EditText(this);
editText.setText(String.valueOf(i));
mergeRecycleAdapter.addView(editText);
}
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(mergeRecycleAdapter);
}
}
I am new bie in android.
Below is my senerio what i have and what i actually need.
I have one activity where i have declare one custom view which contains a set of button which click event display respective fragments.
This custom view will be appear on top of each fragment.
Now suppose on first button of custom view i am display fragment a fragment which display list-view..
on click on list-view it show another fragment i.e detail fragment
In detail fragment.. i have one button where i need to show an fragment overlay on main activity ... as on full screen.. how can i achive this?
In my opinion easiest way lead to this behavior is use Activity Overlay or DialogFragment. Example:
Activity Overlay
MainActivity.java
public class MainActivity extends AppCompatActivity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.buttonShow);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
}
MainActivity.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/mainLayout"
tools:context=".MainActivity"
android:background="#android:color/holo_orange_dark">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Main Activity"
android:textSize="30dp"
android:layout_centerInParent="true"/>
<Button
android:layout_width="150dp"
android:layout_height="50dp"
android:text="show"
android:id="#+id/buttonShow"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
SecondActivity.java
public class SecondActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
}
SecondActivity.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".SecondActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_orange_light">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Second Activity"
android:textSize="30dp"
android:layout_centerInParent="true"/>
</RelativeLayout>
</RelativeLayout>
Styles.xml
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
</style>
<style name="TransparentFloatingActivity" parent="AppTheme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
</resources>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.arturszymanski.test" >
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:theme="#style/TransparentFloatingActivity"
android:name=".SecondActivity"
android:label="#string/title_activity_second" >
</activity>
</application>
</manifest>
DialogFragment
MyDialogFragment.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MyDialogFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_orange_light">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="FullScreen Fragment"
android:textSize="30dp"
android:layout_centerInParent="true"/>
</RelativeLayout>
MyDialogFragment.java
public class MyDialogFragment extends DialogFragment
{
private int margin;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
margin = 10;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_my_dialog, container, false);
}
#Override
public void onResume() {
int dialogHeight = MainActivity.displayMetrics.heightPixels - (margin * 2) - MainActivity.StatusBarHeight;
int dialogWidth = MainActivity.displayMetrics.widthPixels - (margin * 2);
getDialog().getWindow().setLayout(dialogWidth, dialogHeight);
super.onResume();
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity
{
public static DisplayMetrics displayMetrics;
public static int StatusBarHeight;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
StatusBarHeight = getStatusBarHeight();
Button button = (Button) findViewById(R.id.buttonShow);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
MyDialogFragment dialogFragment = new MyDialogFragment();
dialogFragment.show(getFragmentManager(), "Dialog");
}
});
}
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
}
Other Files
Other files are the same as in example above.
If i follow your question than, You should use a RelativeLayout as overlay in main activity's layout. and set visibility according to your need.
layout_activity_main.xml
<RelativeLayout
android:width="match_parent"
android:height="match_parent">
<LinearLayout>
// your toolbar
// You fragment container
// your main layout goes here
</LinearLayout>
<RelativeLayout
android:id="#+id/overlay"
android:width="match_parent"
android:height="match_parent">
</RelativeLayout>
</RelativeLayout>
like this :
<LinearLayout id = "#+id/container">
<ToolBar id ="#+id/toolbar>
</ToolBar>
<FrameLayout id ="#+id/main_containt"/>
</LinearLayout>
getSupportFragmentManager().add(new Fragment(),R.id.container).commit();
use container as the container of fragment;
I have a view with a Edittext field on top of an ImageView. When the keyboard comes up I want the window to resize so that EditText is no longer hidden by the keyboard. In the AndroidManifest file I declared android:windowSoftInputMode="adjustResize" and the screen is resized but the issue is that I want the ImageView to not be re-sized.
How can I make the ImageView unaffected?
Could I inflate an additional layout with just the ImageView or will the resize still affect it?
The full solution involves a few key points
Use RelativeLayout, so that Views can be setup to overlap one another
Align the EditText with the bottom of the Windows using android:layout_alignParentBottom="true"
Use android:windowSoftInputMode="adjustResize" in your manifest, so that the bottom of the Window changes when the keyboard pops up (as you mentioned)
Put the ImageView inside a ScrollView so that the ImageView can be larger than the Window, and disable scrolling on the ScrollView by using ScrollView#setEnabled(false)
Here is the layout file
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.so3.MainActivity">
<ScrollView
android:id="#+id/scroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/stickfigures"/>
</ScrollView>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#android:color/holo_blue_bright"
android:text="Please enter text"
android:textSize="40sp"
android:gravity="center_horizontal"/>
</RelativeLayout>
Here is my Activity
package com.so3;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ScrollView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ScrollView sv = (ScrollView)findViewById(R.id.scroll);
sv.setEnabled(false);
}
}
My AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.so3" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.so3.MainActivity"
android:windowSoftInputMode="adjustResize"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Screen shots of my solution
Adding ScrollView was making my image scrollable which I wanted to avoid so I used this samples-keyboardheight calculator and onKeyboardHeightChanged recalculated position of the bottom Edittext placed it above Keyboard and used this flag in Manifest.
android:windowSoftInputMode="adjustNothing|stateHidden"
Here is KeyboardHeightProvider :
import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager.LayoutParams;
import android.widget.PopupWindow;
/**
* The keyboard height provider, this class uses a PopupWindow
* to calculate the window height when the floating keyboard is opened and closed.
*/
public class KeyboardHeightProvider extends PopupWindow {
/** The tag for logging purposes */
private final static String TAG = "sample_KeyboardHeightProvider";
/** The keyboard height observer */
private KeyboardHeightObserver observer;
/** The cached landscape height of the keyboard */
private int keyboardLandscapeHeight;
/** The cached portrait height of the keyboard */
private int keyboardPortraitHeight;
/** The view that is used to calculate the keyboard height */
private View popupView;
/** The parent view */
private View parentView;
/** The root activity that uses this KeyboardHeightProvider */
private Activity activity;
/**
* Construct a new KeyboardHeightProvider
*
* #param activity The parent activity
*/
public KeyboardHeightProvider(Activity activity) {
super(activity);
this.activity = activity;
LayoutInflater inflator = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
this.popupView = inflator.inflate(R.layout.popupwindow, null, false);
setContentView(popupView);
setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_RESIZE | LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
parentView = activity.findViewById(android.R.id.content);
setWidth(0);
setHeight(LayoutParams.MATCH_PARENT);
popupView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (popupView != null) {
handleOnGlobalLayout();
}
}
});
}
/**
* Start the KeyboardHeightProvider, this must be called after the onResume of the Activity.
* PopupWindows are not allowed to be registered before the onResume has finished
* of the Activity.
*/
public void start() {
if (!isShowing() && parentView.getWindowToken() != null) {
setBackgroundDrawable(new ColorDrawable(0));
showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0);
}
}
/**
* Close the keyboard height provider,
* this provider will not be used anymore.
*/
public void close() {
this.observer = null;
dismiss();
}
/**
* Set the keyboard height observer to this provider. The
* observer will be notified when the keyboard height has changed.
* For example when the keyboard is opened or closed.
*
* #param observer The observer to be added to this provider.
*/
public void setKeyboardHeightObserver(KeyboardHeightObserver observer) {
this.observer = observer;
}
/**
* Get the screen orientation
*
* #return the screen orientation
*/
private int getScreenOrientation() {
return activity.getResources().getConfiguration().orientation;
}
/**
* Popup window itself is as big as the window of the Activity.
* The keyboard can then be calculated by extracting the popup view bottom
* from the activity window height.
*/
private void handleOnGlobalLayout() {
Point screenSize = new Point();
activity.getWindowManager().getDefaultDisplay().getSize(screenSize);
Rect rect = new Rect();
popupView.getWindowVisibleDisplayFrame(rect);
// REMIND, you may like to change this using the fullscreen size of the phone
// and also using the status bar and navigation bar heights of the phone to calculate
// the keyboard height. But this worked fine on a Nexus.
int orientation = getScreenOrientation();
int keyboardHeight = screenSize.y - rect.bottom;
if (keyboardHeight == 0) {
notifyKeyboardHeightChanged(0, orientation);
}
else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
this.keyboardPortraitHeight = keyboardHeight;
notifyKeyboardHeightChanged(keyboardPortraitHeight, orientation);
}
else {
this.keyboardLandscapeHeight = keyboardHeight;
notifyKeyboardHeightChanged(keyboardLandscapeHeight, orientation);
}
}
/**
*
*/
private void notifyKeyboardHeightChanged(int height, int orientation) {
if (observer != null) {
observer.onKeyboardHeightChanged(height, orientation);
}
}
public interface KeyboardHeightObserver {
void onKeyboardHeightChanged(int height, int orientation);
}
}
popupwindow.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/popuplayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:orientation="horizontal"/>
Here is MainActivity.java :
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends AppCompatActivity implements KeyboardHeightProvider.KeyboardHeightObserver {
private KeyboardHeightProvider keyboardHeightProvider;
private ViewGroup relativeView;
private float initialY;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
keyboardHeightProvider = new KeyboardHeightProvider(this);
relativeView = findViewById(R.id.bottomEditor);
relativeView.post(() -> initialY = relativeView.getY());
View view = findViewById(R.id.activitylayout);
view.post(() -> keyboardHeightProvider.start());
}
#Override
public void onKeyboardHeightChanged(int height, int orientation) {
if(height == 0){
relativeView.setY(initialY);
relativeView.requestLayout();
}else {
float newPosition = initialY - height;
relativeView.setY(newPosition);
relativeView.requestLayout();
}
}
#Override
public void onPause() {
super.onPause();
keyboardHeightProvider.setKeyboardHeightObserver(null);
}
#Override
public void onResume() {
super.onResume();
keyboardHeightProvider.setKeyboardHeightObserver(this);
}
#Override
public void onDestroy() {
super.onDestroy();
keyboardHeightProvider.close();
}
}
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activitylayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
/>
<RelativeLayout
android:id="#+id/bottomEditor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
>
<EditText
android:id="#+id/edit_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:layout_toStartOf="#+id/btn_send"
android:hint="Add caption"
android:paddingBottom="12dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingStart="8dp"
android:paddingTop="12dp"
/>
<ImageButton
android:id="#+id/btn_send"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignBottom="#+id/edit_message"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="4dp"
android:layout_marginRight="4dp"
app:srcCompat="#android:drawable/ic_menu_send"
/>
</RelativeLayout>
</RelativeLayout>
P.S. : Keyboard height calculation code is copied from siebeprojects
Here is demo example app of implementation.
final View activityRootView = findViewById(R.id.mainScroll);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightView = activityRootView.getHeight();
int widthView = activityRootView.getWidth();
if (1.0 * widthView / heightView > 1) {
Log.d("keyboarddddd visible", "no");
relativeLayoutForImage.setVisibility(View.GONE);
relativeLayoutStatic.setVisibility(View.GONE);
//Make changes for Keyboard not visible
} else {
Log.d("keyboarddddd visible ", "yes");
relativeLayoutForImage.setVisibility(View.VISIBLE);
relativeLayoutStatic.setVisibility(View.VISIBLE);
//Make changes for keyboard visible
}
}
});
For me i did not want to assume that keyboards heights are a certain measurement. Whatever view your concerned about make a onTouchListener and then do this:
setOnTouchListener(new OnTouchListener() {
Runnable shifter=new Runnable(){
public void run(){
try {
int[] loc = new int[2];
//get the location of someview which gets stored in loc array
findViewById(R.id.someview).getLocationInWindow(loc);
//shift so user can see someview
myscrollView.scrollTo(loc[0], loc[1]);
}
catch (Exception e) {
e.printStackTrace();
}
}}
};
Rect scrollBounds = new Rect();
View divider=findViewById(R.id.someview);
myscollView.getHitRect(scrollBounds);
if (!divider.getLocalVisibleRect(scrollBounds)) {
// the divider view is NOT within the visible scroll window thus we need to scroll a bit.
myscollView.postDelayed(shifter, 500);
}
});
//essentially we make a runnable that scrolls to a new location of some view that you WANT visible on the screen. you execute that runnable only if its not within the scrollviews bounds (its not on the screen). This way it shifts the scrollview to the referenced view (in my case 'someview' which was a line divider).
In my opinion the easiest way to do this it is this combination of the two changes:
android:windowSoftInputMode="adjustResize"
in your AndroidManifest.xml
+
getWindow().setBackgroundDrawable(your_image_drawable);
in your activity in #onCreate() method
It works for me.
The best solution is to use a DialogFragment
Show dialog
DialogFragment.show(getSupportFragmentManager(), DialogFragment.TAG);
Full screen
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = new Dialog(getActivity(), R.style.MainDialog) { //set the style, the best code here or with me, we do not change
#Override
public void onBackPressed() {
super.onBackPressed();
getActivity().finish();
}
};
return dialog;
}
Style
<style name="MainDialog" parent="#android:style/Theme.Dialog">
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:windowFrame">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">false</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:background">#null</item>
<item name="android:windowAnimationStyle">#null</item>
</style>
Layout Activity
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
Layout dialog fragment
<?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="#color/transparent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:background="#color/background_transparent_60"
android:gravity="center_vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="#dimen/spacing_1_8dp"
android:layout_marginLeft="#dimen/spacing_1_8dp"
android:layout_marginRight="#dimen/spacing_1_8dp"
android:layout_weight="1"
android:hint="#string/comment_entry_hint"
android:inputType="textMultiLine"
android:maxLines="4"
android:textColor="#color/white"
android:textColorHint="#color/secondary_text_hint"
android:textSize="#dimen/text_2_12sp" />
<ImageView
android:layout_width="#dimen/livestream_comment_height"
android:layout_height="#dimen/livestream_comment_height"
android:layout_margin="#dimen/spacing_1_8dp"
android:src="#drawable/ic_send" />
</LinearLayout>
</RelativeLayout>
The solution that worked for me was in AndroidManifest.xml in that activity tag just put
android:windowSoftInputMode="stateHidden|adjustResize|adjustNothing"
All set..Hope this will work for you.
final View activityRootView = findViewById(R.id.mainScroll);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightView = activityRootView.getHeight();
int widthView = activityRootView.getWidth();
if (1.0 * widthView / heightView > 1) {
Log.d("keyboarddddd visible", "no");
relativeLayoutForImage.setVisibility(View.GONE);
relativeLayoutStatic.setVisibility(View.GONE);
//Make changes for Keyboard not visible
//relativeLayoutForImage.setVisibility(View.VISIBLE);
//relativeLayoutStatic.setVisibility(View.VISIBLE);
} else {
Log.d("keyboarddddd visible ", "yes");
relativeLayoutForImage.setVisibility(View.VISIBLE);
relativeLayoutStatic.setVisibility(View.VISIBLE);
//Make changes for keyboard visible
// relativeLayoutForImage.setVisibility(View.GONE);
//relativeLayoutStatic.setVisibility(View.GONE);
}
}
});
Below is the Gmail No Connection alert. How would I go about achieveing this in my app?
Note: this is a question regarding the UI implementation, and not determining whether there is a connection.
EDIT::
Is the bottom notification an anctivity themed as a dialog and placed at the bottom or is it some sort of AlertDialog?
maybe that example can help you https://github.com/DanielRasta/Material-Design-Alert-Box-
EDIT 2 :
Material Design have Snackbar class too
Edit 1 :
Well, the idea is to call dialog activity in front. So to do that :
1 - Create alertbox_activity.xml layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#8A8A8A">
<TextView
android:id="#+id/alertbox_message"
android:layout_width="match_parent"
android:paddingTop="10dp"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:background="#8A8A8A"
android:textSize="20sp"
android:typeface="sans"
android:gravity="center" />
</LinearLayout>
2 - Create an activity called AlertBoxActivity.java and paste this code
public class AlertBoxActivity extends Activity {
// ===========================================================
// Constants
// ===========================================================
private static final int EXIT_DELAY= 3500;
public static final String KEY_BUNDLE_MESSAGE_TEXT = "AlertBoxActivity::message_text";
public static final String KEY_BUNDLE_PARENT_WIDTH = "AlertBoxActivity::parent_width";
private static final String ERROR_GEN = "Oops.. Something went wrong.";
private Runnable Exit(){
return new Runnable(){
#Override
public void run() {
finish();
}
};
}
// ===========================================================
// Methods for/from super class
// ===========================================================
#Override
public void onCreate(Bundle pBundle) {
super.onCreate(pBundle);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.alertbox_activity);
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
TextView textViewMessage = (TextView) findViewById(R.id.alertbox_message);
String strNotificationToShow = ERROR_GEN;
int myParentWidth = getWindow().getAttributes().width;
try {
Bundle extras = getIntent().getExtras();
if(extras != null) {
strNotificationToShow = extras.get(KEY_BUNDLE_MESSAGE_TEXT).toString();
myParentWidth = extras.getInt(KEY_BUNDLE_PARENT_WIDTH);
}
else{
myParentWidth = getWindow().getAttributes().width;
}
}
catch(Exception e) {
e.printStackTrace();
strNotificationToShow = ERROR_GEN;
myParentWidth = getWindow().getAttributes().width;
}
finally{
textViewMessage.setText(strNotificationToShow);
}
WindowManager.LayoutParams params = getWindow().getAttributes();
params.width = myParentWidth;
params.gravity = Gravity.BOTTOM;
getWindow().setAttributes(params);
Window window = getWindow();
window.setAttributes((android.view.WindowManager.LayoutParams) params);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
new Handler().postDelayed(Exit(), EXIT_DELAY);
}
}
3 - Add these lines to your manifest.xml
<activity
android:name="com.package.AlertBoxActivity"
android:label="#string/app_name"
android:theme="#style/Theme.AppCompat.Dialog">
<intent-filter>
<action android:name="android.intent.action.ALERT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
4 - Call it
Intent i = new Intent("android.intent.action.ALERT");
i.putExtra(AlertBoxActivity.KEY_BUNDLE_MESSAGE_TEXT, "YOUR ALERT GOES HERE!");
i.putExtra(AlertBoxActivity.KEY_BUNDLE_PARENT_WIDTH, getWindow().getAttributes().width);
startActivity(i);
Done.
I am not sure if this is how Google implement their dialog but here is my Go around. I created a class that will be styled as a dialog in the manifest. So when I need to show the alert I simply start the Intent and its diaplayed. In the Activity I have a PostDelayed Handler taht will wait for 3.5 seconds and end the activity to give a toast like animation (similar to Gmail :-) )
Find Code Below
static final int EXIT_DELAY= 3500;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.layout_pesabox_alert);
WindowManager.LayoutParams params = getWindow().getAttributes();
params.x = 5;
params.height = 150;
params.width = 700;
params.y = 5;
params.gravity = Gravity.BOTTOM;
this.getWindow().setAttributes(params);
Window window = this.getWindow();
window.setAttributes((android.view.WindowManager.LayoutParams) params);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
new Handler().postDelayed(Exit(), EXIT_DELAY);
}
private Runnable Exit(){
return new Runnable(){
#Override
public void run() {
finish();
}
};
}
The Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="#+id/detailsText"
android:layout_width="wrap_content"
android:paddingTop="10dp"
android:paddingLeft="10dp"
android:paddingRight="15dp"
android:layout_height="wrap_content"
android:drawableLeft="#android:drawable/ic_dialog_alert"
android:drawablePadding="25dp"
android:text="#string/connection"
android:textColor="#ffffff"
android:textSize="25sp"
android:typeface="sans" />
</LinearLayout>
A really old post but if anyone else is looking for google like "Bottom Toast like Notification". Refer to Snackbar Material Design. Its also available in the support library. How to use Snackbar with backward compatibility is pretty well explained in this blog.