25

I'm looking at best way of creating an Accordion-style widget such as on this page. Is there a way of achieving same effect using standard Android toolkit or do I need to build custom widget? If so - which one would you recommend extending if any?

2

4 Answers 4

31

And in case you still wonder - this can be pretty much done with pair of button/layout stacked inside of the linear layout. Pseudo code follows

<LinearLayout android:orientation="vertical">
    <Button android:text="Panel 1"/>
    <SomeKindOfLayout android:id="@+id/panel1">
            <!-- widgets in first panel go here -->
    </SomeKindOfLayout>
    <Button android:text="Panel 2"/>
    <SomeKindOfLayout android:id="@+id/panel2" android:visibility="gone">
            <!-- widgets in second panel go here -->
    </SomeKindOfLayout>
    <Button android:text="Panel 3"/>
    <SomeKindOfLayout android:id="@+id/panel3" android:visibility="gone">
            <!-- widgets in third panel go here -->
    </SomeKindOfLayout>
    <Button android:text="Panel 4"/>
    <SomeKindOfLayout android:id="@+id/panel4" android:visibility="gone">
            <!-- widgets in fourth panel go here -->
    </SomeKindOfLayout></LinearLayout>

Another thing to possibly try is stacking ExpandableListView-s on top of each other

4
  • 5
    I had to share it with the world :) For the record - this is a snippet given to me by @commonsguy on the maillist (android.developers)
    – Bostone
    Commented Jul 23, 2009 at 2:44
  • Hellow I am dynamiaclly creating the buttons for the accordion as its not sure about the number of button in the list. for every button I have LinearLayout with some views inside it. Can anybody let me know how to get the onclicklistner of the respective accordion button, so that I can toggle between visiblity and Gone for respective LinearLayouts. Commented Jul 12, 2010 at 12:51
  • Does this work if you stick ListView's in as SomeKindOfLayout? I seem to remember Android only likes you to have one ListView per layout. Commented Apr 25, 2013 at 22:27
  • 1
    You can have as meny ListViews as you like in one layout. Its just that is you want to use your layout in ListActivity (or ListFragment) you should have only one ListView with android:id="@android:id/list" Commented Jan 14, 2014 at 7:55
22

I have pushed android accordion view project at github. We use it for our customers, tested on 2.2, 2.3.x, 3.2 and 4.0.3. Works pretty good for us.

Going to add animation on fold/unfold in next step.

Here is small screenshot:

enter image description here

5
  • Hi Maciej, I successfully run your accordion application and it looks very good. I wanted to port into my application, how can I do that? I tried copying the files, but I'm having problems with ic_resource not found. Am I doing it the right way? should one copy all the files out? Commented May 29, 2013 at 17:01
  • 1
    @NicholasTJ I think you should ask about it on github... but since you asked here: project is android library project, read more about it here developer.android.com/tools/projects/index.html#LibraryProjects. You can build with maven and get apklib - see here code.google.com/p/maven-android-plugin/wiki/ApkLib Commented May 29, 2013 at 18:43
  • Thanks for the tip, I appreciate it, I'll read on the links you provided. Commented May 29, 2013 at 18:52
  • 1
    But i am unable to add my own objects( TextView, Buttons etc ) init. How do i do that? Commented May 10, 2014 at 19:46
  • 1
    Cant get this to work... No documentation at all.. My problem is the same as the comment above, how do we add our own objects in this? Do we use a layout as a container and add everything in there?
    – SudoPlz
    Commented May 26, 2014 at 16:17
8

I have to risk myself and say that the @Bostone answer is the most appropriate. I will give you my code below so you can see. Thanks for the GitHub Maciej Łopaciński, but as @SudoPlz said in the comments, there is no documentation at all. I didn't knew where to start. I try to do it with Eclipse and Android Studio and in neither I could run the project to start figuring out how its work. Besides, the last commit in that project was about 1 year ago, wich makes me fear a lot that if something goes wrong I will be stuck in a dead end. So without further delay, here is my solution based in @Bostone:

1.- First you have to create a Button and a Layout nested in a ScrollView:

    <ScrollView 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=".TasksListActivity">


            <Button
                android:id="@+id/magic_btn"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Magic Btn"/>
            <LinearLayout
                android:id="@+id/magic_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:visibility="gone">

        </LinearLayout>
</ScrollView>

2.- After that go to your corresponding JAVA, there find the button and set an onClickListener, inside the onClickListener you will find the layout.

Button findMagicBtn = (Button) findViewById(R.id.magic_btn);
        findMagicBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

3.- So now inside the onClickListener we will find the layout. As you can see in the first step the layout is set by default to GONE, but now we have to set it to visible. The problem is, how can I make it gone again and vice-versa? So we will add a condition for getting the visibility of the layout and based on that it will be hidden or show up:

Button findMagicBtn = (Button) findViewById(R.id.magic_btn);
        findMagicBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                LinearLayout findMagicLl = (LinearLayout) findViewById(R.id.magic_layout);
                if (findMagicLl.getVisibility() == View.VISIBLE) {
                    findMagicLl.setVisibility(View.GONE);
                } else {
                    findMagicLl.setVisibility(View.VISIBLE);
                }
            }
        });

This can be put over each other as many times you want.

So now if you really want to make it look like an accordion you can pimp the button. You could put an arrow on the right of it, using by example:

findMagicBtn.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.right_arrow, 0);

You should do that inside the onClickListener and use the condition to change the direction of the arrow, by changing the drawable (if is gone and down arrow, and if is visible an up arrow).

Also, you can make it look more natural by adding an animation, like this:

ScaleAnimation animation = new ScaleAnimation(1f, 1f, 1f, 0f, Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f);
animation.setDuration(180);
animation.setFillAfter(true);
findMagicLl.startAnimation(animation);

You will have to consider that the above animation must be done while the view is visible. Please be aware that setFillAfter(true), will change the size of the container permanently so if you do so, maybe you don't want to use VIEW.GONE anymore. This question has a wonderfull explanation about the Scale Animation

4
  • I used your way to simulate an accordion, however, the inner LinearLayout does not expand according to its child control. Inside of that layout, I am placing a ListView with some elements. The effect when I run it is that only the first element is shown, but I can scroll the listview to see other items one at a time. All the accordion is being created programmatically. Can you give me a hint on how to solve this and to show the whole list view without the scroll?
    – jstuardo
    Commented Oct 18, 2015 at 1:05
  • @jstuardo Im sorry but I think your problem has to do with the listviews, listviews always load enough elements to fit the available size in the screen. So what, if there is no size available... in listviews the next element outside of the viewable is created only if the user need to see it, this is cause it save memory. I'll be sad if my fix have that problem, but I think you can fix it changing the linearlayout heigh properties. Try match parent. Also see what happen without using the visibility gone by default. ... maybe you can override listview behaviour. Let me know.
    – cutiko
    Commented Oct 18, 2015 at 1:16
  • @jstuardo Had a similar problem, you might want to read this: stackoverflow.com/questions/18411494/… stackoverflow.com/a/32881309/4017501 stackoverflow.com/a/31818632/4017501
    – cutiko
    Commented Oct 19, 2015 at 17:49
  • 1
    instead of go with library, we should implement above with animation. Commented Dec 31, 2015 at 7:39
3

In my app, I used Riya Gayasen's accordion view. It was very easy to get started and worked well. Here is what I did.

  1. Download the zip of source code from https://github.com/riyagayasen/Android_accordion_view.
  2. Unzip and copy 'easyaccordion' folder to your project's root directory (the directory containing the 'app' folder)
  3. In your project root settings.gradle file add :easyaccordion. Here is how my file looks like: include ':app',':easyaccordion'
  4. In your app/build.gradle file add the following line to the dependencies block. implementation 'com.riyagayasen.android:easyaccordion:1.0.3'
  5. And that's it. You can start using the component inside your layout.
0

Not the answer you're looking for? Browse other questions tagged or ask your own question.