1

I'm new to using RxJava and still getting familiar with a lot of concept in it. Trying to use it in a project and what I want to do is subscribe a click event of a view to change the visibility of another view. Here is my trial that works.

RxView.clicks(info_overlay).map { _ -> View.GONE }.subscribe {
            AppCache().hasSeenInfoScreen = true
            info_overlay_child_take_a_helfie.visibility = it
            info_overlay_child_subscription.visibility = it
            info_overlay_child_description.visibility = it
            info_overlay_child_header.visibility = it
        }

However, I also want to subscribe to visibility of info_overlay . So that the visibility of info_overlay affects other views as well.

How do i achieve this and the click observable together.

Belvi Nosakhare
  • 3,107
  • 5
  • 32
  • 65
  • I don't think you can subscribe to the visibility property. Instead, try subscribing to whatever code triggers a change in visibility. – ESala Jan 11 '18 at 20:33

2 Answers2

2

The most closest thing looks like this:

 RxView.globalLayouts(info_overlay)
        .map { info_overlay.visibility }
        .distinct()
        .subscribe { newVisibility ->
            info_overlay.run {
                (0 until childCount)
                    .map(this::getChildAt)
                    .forEach { view -> view.visibility = newVisibility }
            }
        }

In case if you don't need to change all children views use method as following:

 RxView.globalLayouts(info_overlay)
        .map { info_overlay.visibility }
        .distinct()
        .subscribe { newVisibility ->
            info_overlay_child_take_a_helfie.visibility = newVisibility
            ...
        }

Explaining. I've taken idea from this answer https://stackoverflow.com/a/32778292/4727432

myView.setTag(myView.getVisibility());
myView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        int newVis = myView.getVisibility();
        if((int)myView.getTag() != newVis) {
            myView.setTag(myView.getVisibility());
            //visibility has changed
        }
    }
});

Roughly speaking, code aboves does the same as RxView.globalLayouts(). After that I map value to view visibility. I've added distinct to make invoking subscribe only in case if visiblity changes.

hluhovskyi
  • 9,556
  • 5
  • 30
  • 42
0

There is no way to subscribe/listen to the visibility changes of a View, at least not without extending and overriding. None observable is provided by RxBinding neither.

Anyway, using kotlin you could achieve this using delegates, extensions properties and observing to it. but I suspect this could be painful and you will must be limited to use the extension property everywhere in place of visibility

crgarridos
  • 8,758
  • 3
  • 49
  • 61