3

I've implemented a navigation drawer in my app as instructed in the android documentation.

Everything is working fine but as some of my fragments are using tabs I would like to 'scroll out' the tabviews simultaneously as the drawer is expanded. Like illustrated here: Like illustrated here. The onDrawerSlide() method from my actionBarToggle would be perfect for it as it passes the percentage of how far the drawer is expanded.

I changed the navigationmode of the actionbar in actionBarToggle's onDrawerOpened() and onDrawerClosed() methods and everything is working well. But I want some kind of animation because it's looking very brusque at the moment. [Drawer opened - puff tabs are gone puff; Drawer closed- puff tabs are there again puff]

My current code.

    drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    mDrawerToggle =
            new ActionBarDrawerToggle(this, drawerLayout, R.drawable.ic_drawer,
                    R.string.navigation, R.string.closed) {

                public void onDrawerClosed(View view) {
                    supportInvalidateOptionsMenu();
                }

                public void onDrawerOpened(View drawerView) {
                    setTitle(getString(R.string.navigation));
                    setIcon(R.drawable.abc_ic_search_api_holo_light);

                    supportInvalidateOptionsMenu();
                }

                @Override
                public void onDrawerSlide(View drawerView, float slideOffset) {
                    // TODO animation 
                    super.onDrawerSlide(drawerView, slideOffset);
                }
            };

I expect something like getting the tabhost/view or whatever and setting it's height depending on the slideOffset.

                @Override
                public void onDrawerSlide(View drawerView, float slideOffset) {
                    TabView tabView = actionBar.getTabView(); // how do I get the view where the tabs are shown?
                    ViewGroup.LayoutParams tabViewLayoutParams = tabView.getLayoutParams();
                    ViewGroup.LayoutParams tabViewNewLayoutParams = new ViewGroup.LayoutParams(a.width, (int)((1 - slideOffset) * normalTabHeight))
                    drawer.setLayoutParams(tabViewNewLayoutParams );

                    super.onDrawerSlide(drawerView, slideOffset);     
        }

How can I get the view where the tabs are in?

How can I get the view where the tabs are in?

I'm using the support library for API 7+ and thus the SupportActionBar.

How is the "tabhost" called included in the actionbar? Is it even possible to get this "tabview/host" and change the height of it on runtime programmatically?

Endzeit
  • 4,810
  • 5
  • 29
  • 52
  • There doesn't seem to be any ids assigned to the tabs container in the support v7 library. You could find the child by trawling through the container hierarchy manually, but it might change in the future. Also note that the tabs can appear inside the top action bar on wide screens and portrait mode. – corsair992 Jan 12 '14 at 16:35
  • @corsair992 As ActionBar.Tab does not extend View I can't call getParent() or is there another way to get the container? I know about that. The 'animation' should only be for devices and cases where the tabs are displayed like in the images. Nevertheless thanks for your reply. :) – Endzeit Jan 12 '14 at 19:17
  • Here's some code to get the tabs container from it's current position in the hierarchy: `((ViewGroup)getWindow().findViewById(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ? android.support.v7.appcompat.R.id.action_bar_container : Resources.getSystem().getIdentifier("action_bar_container", "id", "android"))).getChildAt(2);` Note that this will return null if the container is included in the top action bar. – corsair992 Jan 12 '14 at 20:28
  • @corsair992 Thanks for the code snippet. :) This actually works and returns the needed view. But I can't change the height of it. Changing the layout params seems not to work at all. But it is the right view as I've changed the background color and it worked. Do you have any idea how to accomplish this? – Endzeit Jan 13 '14 at 16:56
  • Changing the `LayoutParams` dimensions won't affect anything until the next layout. You can read about how to implement `View` animation in the [API guides](http://developer.android.com/guide/topics/graphics/view-animation.html). – corsair992 Jan 13 '14 at 18:12
  • @corsair992 Thanks for the help. :) I'll see if it works. Regardless of it's the solution of my problem or not you can get the 100 reputation points if you want. Just post an answer below, you were a big help to me. I'll notify you if it works for me or not. – Endzeit Jan 13 '14 at 18:33
  • Actually, sorry, but I gave you the wrong advice. You want the tab container animation to correspond to the `DrawerLayout` swiping, which would require a custom `Animation`. Also, `View` animation doesn't change the size of it's container, so it won't accomplish what you want. Neither will changing the height in the `LayoutParams` and forcing the parent to relayout the container work, because the layout performs it's own measurements with a custom height. ... – corsair992 Jan 14 '14 at 14:32
  • ... There _is_ a public method to change the height of the tab container, but the `ScrollingTabContainerView` class itself is not public in the framework, although it _is_ public in the support library. So the only thing you could do is to either change the height via reflection (not recommented in performance-intensive operations like animations), or change the library to always use it's own implementation instead of the framework's. I'll add an answer to that affect. – corsair992 Jan 14 '14 at 14:32

1 Answers1

1

The problem is that the action bar tabs container does it's own height measurement, so assigning a custom height to it's LayoutParams has no effect on it's layout. There is a public method to change it's height, but the container class itself is not exposed by the framework.

The only way to change it's height without using reflection would be to change the support library to use it's own implementation even in post-Honeycomb devices instead of delegating to the framework, and possibly adding a method in the tab container for a hiding scroll animation similar to the navigation drawer. Or you could use your own tab implementation, possibly copying the code from the action bar.

Another possibility would be to use fade animation if you don't need to reclaim the tab space in your layout.

corsair992
  • 3,050
  • 22
  • 33
  • Regarding using making the support library always use its onw implementation i did something similar with the sherlock actionbar. You could refer this answer http://stackoverflow.com/questions/9652075/how-to-customize-android-actionbar-to-show-a-custom-view-before-the-tabs/17469817#17469817 – Pasquale Anatriello Jan 14 '14 at 17:31
  • Thanks for you answer. I actually want to reclaim the tab space so that the navigation drawer also is expanding in its height. Otherwise there would be just a blank space which would look awful. Therefore a fade animation won't be a solution. How can I call this method if it's class is private, ignoring that it's only possible for pre-ICS at first? Please excuse that I ask so many questions which may be elementary but I'm a non professional and still pretty new to android development. – Endzeit Jan 14 '14 at 17:42
  • @Endzeit: The class is hidden in the framework, but it's public in the support library. If you're using the support library implementation, then you can cast the container to `ScrollingTabContainerView` and call `setContentHeight()` on it to set it's height, then call `forceLayout()` on it's parent to force it to do a relayout. However, this won't achieve exactly what you're looking for, as it will cause the `View` to shrink instead of scroll. Perhaps using a `TranslateAnimation` in conjunction with resizing will achieve what you want. Or you can copy over some code from the `DrawerLayout`. – corsair992 Jan 14 '14 at 18:22
  • @Endzeit: If you use a `TranslateAnimation`, then you will need to provide your own custom implementation of it, which will do a custom transformation in reaction to navigation drawer scrolling. Otherwise you could modify the `ScrollingTabContainerView` class in the support library, and provide a method which would scroll it out at a specified point using custom drawing or layout logic. You can take a look at how `DrawerLayout` does this. Either way would be somewhat complicated to implement, but if you really want to do it then it should be possible (at least the second one). – corsair992 Jan 14 '14 at 18:37
  • Thanks a lot for all your help! I'll try one of your proposals in the new future. Unfortunatelly I'm pretty busy at the moment so I won't find the time to do it. – Endzeit Jan 15 '14 at 15:40