Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FrameLayout setVisibility is not working

Tags:

android

I'm trying to set a FrameLayout to View.GONE along with many other views in reaction to the screen being tilted to landscape.

So far it seems to work for all views except for ONE FrameLayout. It just will not go!

I'm setting it to View.GONE at the same time in the same way as all the other views but it persists:

List<View> viewsToHide = getAllNonFullscreenViews();
for (View v : viewsToHide) {
    v.setVisibility(View.GONE);
}

I've check that the view is actually being found and set it to GONE individually. I've called clearAnimation() because I do animate it at one point and I've heard it could be an issue.

View dropdownContainer = getActivity().findViewById(R.id.dropdownContainerView);
dropdownContainer.clearAnimation();
dropdownContainer.setVisibility(View.GONE);

I've tried to set it to GONE individually on the ui thread. Again setting breakpoints and making sure the view is actually found and set to GONE.

getActivity().runOnUiThread(new Runnable() {
    @Override
    public void run() {
        View dropdownContainer = getActivity().findViewById(R.id.dropdownContainerView);
        dropdownContainer.clearAnimation();
        dropdownContainer.setVisibility(View.GONE);
    }
});

I've tried the same thing again but after a delay

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        View dropdownContainer = getActivity().findViewById(R.id.dropdownContainerView);
        dropdownContainer.clearAnimation();
        dropdownContainer.setVisibility(View.GONE);
    }
}, 3000);

What's particularly strange is when I check the view after a delay, it is actually set to GONE?! But I can still see it on the screen. It's also definitely the right View because if i set it to GONE straight away and not in reaction to anything, the view does go away as expected.

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        //check the dropdown
        View dropdown = getActivity().findViewById(R.id.dropdownContainerView);
        int visibility = dropdown.getVisibility();
        if (visibility == View.VISIBLE) {
            Log.d("dropdown", "is visible");
        } else if (visibility == View.INVISIBLE) {
            Log.d("dropdown", "is invisible");
        } else if (visibility == View.GONE) {
            Log.d("dropdown", "is gone"); //Runs this
        }
    }
}, 4000);

EDIT: the xml

I'm inserting this FrameLayout programatically in another view.

So the "parent" view.

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/containerFrame">

    <LinearLayout
        android:id="@+id/detailBg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/detail_bg"
        android:orientation="vertical" >

    <LinearLayout
        android:orientation="vertical"
        android:id="@+id/dropdownContainer"
        android:layout_width="fill_parent"
        android:layout_height="48dp">
    </LinearLayout>

    <View
        android:id="@+id/detailSpacer"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/light_gray" />

    <LinearLayout
        android:id="@+id/detailContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" />

    </LinearLayout>
</FrameLayout>

The view that i'm trying to hide:

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dropdownContainerView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

<RelativeLayout
    android:id="@+id/selectedView"
    android:layout_width="fill_parent"
    android:layout_height="48dp"
    android:background="#ffffff">

<View
    android:id="@+id/grayline1"
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:layout_alignParentTop="true"
    android:background="@color/light_gray" />

<View
    android:id="@+id/grayline2"
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:layout_alignParentBottom="true"
    android:background="@color/light_gray" />

<TextView
    android:id="@+id/selectedText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:paddingLeft="20dp"
    android:layout_centerVertical="true"
    android:gravity="center"
    android:textSize="18sp"
    android:textColor="#0081C8"/>

</RelativeLayout>
</FrameLayout>

And I'm adding it like so:

FrameLayout parentFrame = (FrameLayout) getActivity().findViewById(R.id.containerFrame);
dropdownView = new DropdownView(getActivity(), options, 0, this);
parentFrame.addView(dropdownView, 1);

EDIT: Animation

As mentioned, the view that I'm trying to hide can be animated in response to a tap. Although the view still won't disappear even if the animation is never run to begin with. Here is the animation code:

    final Boolean shouldOpen = !isDropdownShowing;

    RelativeLayout selectionView = (RelativeLayout) findViewById(R.id.selectedView);
    final int listHeight = dropdownListView.getHeight();
    final int heightOfSelectionView = selectionView.getHeight();

    TranslateAnimation translateAnimation;
    if (shouldOpen) {
        translateAnimation = new TranslateAnimation (0.0f, 0.0f, heightOfSelectionView - listHeight, 0);
        int y = heightOfSelectionView;
        dropdownListView.setY(y);
    } else {
        translateAnimation = new TranslateAnimation (0.0f, 0.0f, 0, 0 - listHeight);
    }

    translateAnimation.setFillAfter(true);
    translateAnimation.setFillEnabled(true);
    translateAnimation.setDuration(300L);
    translateAnimation.setRepeatCount(0);

    translateAnimation.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {

        }

        @Override
        public void onAnimationEnd(Animation animation) {
            if (shouldOpen) {
                isDropdownShowing = true;
                dropdownListView.setY(heightOfSelectionView);
            } else {
                isDropdownShowing = false;
                dropdownListView.setY(0 - listHeight);
            }

            dropdownListView.clearAnimation();

        }

        @Override
        public void onAnimationRepeat(Animation animation) {

        }
    });

    dropdownListView.startAnimation(translateAnimation);
like image 205
pbevis Avatar asked Oct 20 '22 22:10

pbevis


1 Answers

I think you're setting the visibility only of the FrameLayout and not navigating on the child views and setting it's visibility. Which is why the other views are still drawn on you're screen and only the FrameLayout is being set to gone.

To do this you need to make loop of the parentView which is in your case the FrameLayout like this:

for (int i = 0; i < frameLayout.getChildCount(); i++) {
    View v = frameLayout.getChildAt(i);
    v.setVisibility(View.GONE);
    v.postInvalidate();
}

Also use the postInvalidate to refresh the views. Do the animation as well inside the loop. Hope this helps.

like image 178
KaHeL Avatar answered Oct 23 '22 20:10

KaHeL