Delete android window after timeout - android

I was looking through the WindowManager's API but I couldn't find a way to make the window disappear after a certain period of time. My desired functionality is to initially make the window pop up, wait until timeout and then disappear/delete itself.

ViewManager.removeView(View v)

try it:
new Handler().postDelayed(new Runnable(){
public void run() {
yourParentView.removeView(childView);
}
}, TIME);

Try adding and using this method:
/**
* Simple method that will take any view class and remove it from it's parent
* #param viewToRemove the view you want to remove from its parent
*/
private void removeViewFromItsParent(View viewToRemove){
if (viewToRemove == null || viewToRemove.getParent() == null){
Log.w("tag", "view or parent is null, no-operation");
return;
}
ViewGroup viewGroupParent = (ViewGroup) viewToRemove.getParent();
viewGroupParent.removeView(viewToRemove);
}
Something like: removeViewFromItsParent(view);
More info here about ViewGroup including its subclasses and what methods you can use (there are a few remove calls that do slightly different things) : http://developer.android.com/reference/android/view/ViewGroup.html

Related

Correct way to hide and show widgets?

In my app, I need to show and hide widgets like button and textview at a certain time.
and how I am doing is as the following:
private void hideviews() {
image.setVisibility(View.GONE); ///ImageView
title1.setVisibility(View.GONE);///TextView
title2.setVisibility(View.GONE);///TextView
title3.setVisibility(View.GONE);///TextView
title4.setVisibility(View.GONE);///TextView
title5.setVisibility(View.GONE);///TextView
}
private void showviews() {
image.setVisibility(View.VISIBLE);
title1.setVisibility(View.VISIBLE);///TextView
title2.setVisibility(View.VISIBLE);///TextView
title3.setVisibility(View.VISIBLE);///TextView
title4.setVisibility(View.VISIBLE);///TextView
title5.setVisibility(View.VISIBLE);///TextView
}
I don't think this is the correct way to do this.
Because I don't know how many widgets there will be.
Any guidance on how to correctly show widgets is really appreciated.
Get the reference to root layout, iterate through the childs, check if the view at certain index is instance of EditText(or View that you dont need to hide), if not hide it
RelativeLayout root = findViewById(R.id.root)
for(i=0,i<root.getChildCount()-1,i++){
if(! (root.getChildAt(i) instance of EditText)){
root.getChildAt(i).setVisibility(View.GONE)
}
}
Since you don't know how many testviews will be attached, then I believe that the best approach will be to:
get the reference of the parent view group (that contains all the
textviews),
loop through all the childs using getChildAt,
verify whether the object is an instance of TextView/ImageView and if so set its visibility according to your logic
Instead of hiding every widget separately hide the root layout.
RelativeLayout rootLayout;
rootLayout= (RelativeLayout) findViewById(R.id.root_layout);
and use something like this to control the visibility.
public void setLayoutInvisible() {
if (rootLayout.getVisibility() == View.VISIBLE) {
rootLayout.setVisibility(View.GONE);
}
}
public void setLayoutVisible() {
if (rootLayout.getVisibility() == View.GONE) {
rootLayout.setVisibility(View.VISIBLE);
}
}
Make an array of all the views that you want to show/hide:
View[] views = {image, title1, title2, title3, title4, title5};
and then use this to hide them:
for (View view : views) {
view.setVisibility(View.GONE);
}
and use this to show them:
for (View view : views) {
view.setVisibility(View.VISIBLE);
}
although you can combine the 2 code parts in a single procedure:
void fixViews(int state) {
for (View view : views) {
view.setVisibility(state);
}
}
and call it:
fixViews(View.GONE); or fixViews(View.VISIBLE);

Android smoothScrollTo isn't smooth

I'm trying to scroll to a given layout in a ScrollView. My XML is basically composed of a ScrollView implementing various RelativeLayout and I want to programatically scroll to a given one.
I have the following code in my Activity's onCreate method :
// Defining my view
sv = (ScrollView)findViewById(R.id.reward_scroll_view);
// Get Layout's id from intent
Bundle extras = getIntent().getExtras();
if (extras != null) {
idToScroll = extras.getInt("uiToScroll");
sv.post(new Runnable() {
public void run() {
// Scroll to the passed element
RelativeLayout layout = (RelativeLayout) findViewById(idToScroll);
sv.smoothScrollTo(0, layout.getTop());
}
});
}
The "auto-scroll" to a given anchor is working but there is no "smooth" effect, just a raw scroll to the layout. What am I missing ?
You are overriding post method of view.
Scroll view not working smoothly with in UI Thread or Post
Look at this question
I resolved my problem thanks to Aamir's comment, here is how my final code looks like :
Bundle extras = getIntent().getExtras();
if (extras != null) {
// Get Layout's id from intent
idToScroll = extras.getInt("uiToScroll");
layout = (RelativeLayout) findViewById(idToScroll);
// Start 1 second timer
new CountDownTimer(1000, 20) {
public void onTick(long millisUntilFinished) {
// Nothing...
}
// When over, start smoothScroll
public void onFinish() {
sv.smoothScrollTo( 0, layout.getTop() );
}
}.start();
}
My view may have just need some delay to display the scroll effect properly.

Check if view element is added to layout or not programmatically

In my fragment class, I add a child view element programmatically to my layout conditionally :
LinearLayout child = (LinearLayout) inflater.inflate(R.layout.child_view, null);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,100);
container.addView(child, params);
Since the above code will be run conditionally, so, at some point, I would like to check if the child view has added or not, how to make this checking programmatically?
If you creating view via inflater, you can check his parent
if(view.getParent() != null) {...}
I think you can simply use
findViewById(your_view_id)
method: If its result is null the view does not exists, otherwise the view is present
Sorry for late reply but you may try this alternative:
use container.getChildCount(); before adding and after adding a view. Like :
int x = container.getChildCount();
container.addView(child, params);
int y = container.getChildCount();
if(y > x)
Toast.makeText(context, "View Successfully Added!", Toas.LENGTH_SHORT).show();
Or if you have a view instance to find, you could:
if (container.indexOfChild(childView) == -1) {
// Add child to container.
}
With AndroidX you can use ViewGroup.contains(view: View): Boolean extension function.
I cannot write a comment so I write it here as a solution:
From API level 19 you can call isAttachedToWindow() which doesn't help a lot, but if you are aiming API 19 or higher, then this should work by the documentation.
maybe you can try this
child.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
child.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// add to parent
}
});
or this one
child.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
#Override
public void onViewAttachedToWindow(View v) {
}
#Override
public void onViewDetachedFromWindow(View v) {
}
});

Getting list of all Windows in Android

Is it possible to get a list of all Windows in my Android app?
If not, is it possible to get notifications on creation of a new View or a Window?
Cheers :)
For example: I would like to know if there's a visible keyboard view on the screen, or if there's an alert dialog on screen. Is that possible? Can I get the View or Window instance holding it?
Yes this is possible in a number of different ways. All views being displayed on the screen are added to a ViewGroup, which are usually layouts such as R.layout.main, LinearLayout, RelativeLayout, etc.
You can access the views at runtime, after the layouts have been built, using a handler such as onWindowFocusChanged:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
int count = myLayout.getChildCount();
for(int i = 0; i < count; i++)
{
View v = myLayout.getChildAt(i);
...
}
}
You can simply set up a thread inside onWindowFocusChanged that would notify you if a keyboard is created by constantly checking the number of children views of the current layout.
For the keyboard issue, you can use your own keyboard view instance with KeyboardView in your layout: http://developer.android.com/reference/android/inputmethodservice/KeyboardView.html
Use the same principle for the other views you want to handle: manage them yourself in your layout. I don't know if you can in the software you plan to do but this is a way which can work.
You can only get views which are managed by your application.
This includes all views except the status and navigation bars(for higher than HoneyComb). If you choose to have your own InputMethod, that view can be yours as well but you'll need to register the proper keyboard views. See this question for more on that.
Otherwise, if you want to get all the views in your window:
ViewGroup decor = (ViewGroup)activity.getWindow().getDecorView();
int count = decor.getChildCount();
for(int i = 0; i < count; i++) {
View view = decor.getChildAt(i); //voila
}
hey use this code this will help you to find if any dialog is created in your activity
class MyActivity extends Activity {
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
Log.d("TAG", "New Window ATTACHED");
}
}
onAttachedToWindow will be called every time user creates new dialog or something

How to check if the current activity has a dialog in front?

I am using a third-party library and sometimes it pops up a dialog. Before I finish the current activity, I want to check whether there is a dialog popped up in the current context.
Is there any API for this?
You can check it running over the active fragments of that activity and checking if one of them is DialogFragment, meaning that there's a active dialog on the screen:
public static boolean hasOpenedDialogs(FragmentActivity activity) {
List<Fragment> fragments = activity.getSupportFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (fragment instanceof DialogFragment) {
return true;
}
}
}
return false;
}
I faced a similar problem, and did not want to modify all locations where dialogs were being created and shown. My solution was to look at whether the view I was showing had window focus via the hasWindowFocus() method. This will not work in all situations, but worked in my particular case (this was for an internal recording app used under fairly restricted circumstances).
This solution was not thoroughly tested for robustness but I figured I would post in in case it helped somebody.
This uses reflection and hidden APIs to get the currently active view roots. If an alert dialog shows this will return an additional view root. But careful as even a toast popup will return an additional view root.
I've confirmed compatibility from Android 4.1 to Android 6.0 but of course this may not work in earlier or later Android versions.
I've not checked the behavior for multi-window modes.
#SuppressWarnings("unchecked")
public static List<ViewParent> getViewRoots() {
List<ViewParent> viewRoots = new ArrayList<>();
try {
Object windowManager;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
windowManager = Class.forName("android.view.WindowManagerGlobal")
.getMethod("getInstance").invoke(null);
} else {
Field f = Class.forName("android.view.WindowManagerImpl")
.getDeclaredField("sWindowManager");
f.setAccessible(true);
windowManager = f.get(null);
}
Field rootsField = windowManager.getClass().getDeclaredField("mRoots");
rootsField.setAccessible(true);
Field stoppedField = Class.forName("android.view.ViewRootImpl")
.getDeclaredField("mStopped");
stoppedField.setAccessible(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
List<ViewParent> viewParents = (List<ViewParent>) rootsField.get(windowManager);
// Filter out inactive view roots
for (ViewParent viewParent : viewParents) {
boolean stopped = (boolean) stoppedField.get(viewParent);
if (!stopped) {
viewRoots.add(viewParent);
}
}
} else {
ViewParent[] viewParents = (ViewParent[]) rootsField.get(windowManager);
// Filter out inactive view roots
for (ViewParent viewParent : viewParents) {
boolean stopped = (boolean) stoppedField.get(viewParent);
if (!stopped) {
viewRoots.add(viewParent);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return viewRoots;
}
AFAIK - there is no public API for this.
Recommended way is to have a reference to the dialog, and check for isShowing() and call dismiss() if necessary, but since you're using a third party library, this may not be an options for you.
Your best bet is to check the documentation for the library you use. If that doesn't help, you're out of luck.
Hint: Activity switches to 'paused' state if a dialog pops up. You may be able to 'abuse' this behavior ;)
You can override activity method onWindowFocusChanged(boolean hasFocus) and track the state of your activity.
Normally, if some alert dialog is shown above your activity, the activity does not get onPause() and onResume() events. But it loses focus on alert dialog shown and gains it when it dismisses.
For anyone reading this and wondering how to detect a Dialog above fragment or activity, my problem was that inside my base fragment I wanted to detect if I'm displaying a Dialog on top of my fragment. The dialog itself was displayed from my activity and I didn't want to reach it there, so the solution I came up with (Thanks to all answers related to this kind of question) was to get the view (or you can get the view.rootView) of my fragment and check whether any of its children have the focus or not. If none of its children have no focus it means that there is something (hopefully a Dialog) being displayed above my fragment.
// Code inside my base fragment:
val dialogIsDisplayed = (view as ViewGroup).children.any { it.hasWindowFocus() }
Solution in kotlin
Inside Fragment
val hasWindowFocus = activity?.hasWindowFocus()
In Activity
val hasWindowFocus = hasWindowFocus()
If true, there is no Dialog in the foreground
if FALSE , there is a view/dialog in the foreground and has focus.
I am assuming, you are dealing with third party library and you don't have access to dialog object.
You can get the root view from the activity,
Then you can use tree traversal algorithm to see if you can reach any of the child view. You should not reach any of your child view if alert box is displayed.
When alert view is displayed ( check with Ui Automator ), the only element present in UI tree are from DialogBox / DialogActivity. You can use this trick to see if dialog is displayed on the screen. Though it sounds expensive, it could be optimized.
If you are using Kotlin just:
supportFragmentManager.fragments.any { it is DialogFragment }

Categories

Resources