Code Monkey home page Code Monkey logo

expandablelayout's Introduction

ExpandableLayout

An Android layout class that supports animating the expansion and collapse of its child views.

I built this because all of the available libraries I tested were missing features or behaving unexpectedly in certain cases (e.g. rotation handling).

This library offloads as much work as possible to the parent layout to ensure that the rendering and size calculations behave as expected. This means that even complex features such as LinearLayout's weight tag are properly supported.

Try the demo

Google Play Store badge

Features

ExpandableLayout supports animating:

  • Views with fixed and variable heights:

simple

  • "Accordion" expansion (using two expandable layouts)

accordion

  • RecyclerView items

recycler

  • Horizontal expansion

horizontal

Usage

Add the Jitpack maven repository if you don't have it yet:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Reference the library from your module's build.gradle:

dependencies {
    [...]
    implementation 'com.github.cachapa:ExpandableLayout:2.9.2'
}

Add ExpandableLayout as a container to the layout or views you want to make expandable:

<net.cachapa.expandablelayout.ExpandableLayout
    android:id="@+id/expandable_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:el_duration="1000"
    app:el_expanded="true"
    app:el_parallax="0.5">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:text="Fixed height" />

</net.cachapa.expandablelayout.ExpandableLayout>

Also supported are el_duration and el_expanded tags, for specifying the duration of the animation and whether the layout should start expanded, respectively. el_parallax can be set to a value between 0 and 1 to control how the child view is translated during the expansion.

To trigger the animation, simply grab a reference to the ExpandableLayout from your Java code and and call either of expand(), collapse() or toggle().

A full demo of the library is included with the project.

License

Copyright 2016 Daniel Cachapa.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Footnotes

Gifs were generated using the following script: https://gist.github.com/cachapa/aa829bfc717fc4f1d52c568d7ae8521e

expandablelayout's People

Contributors

cachapa avatar danchaltiel avatar fiona0419 avatar litao0621 avatar radarhere avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

expandablelayout's Issues

How to stop. to go upper side the item in screen. when click on recycler view any item.

I think it is happen when click the any item. many time it expand from bottom of item. some time it expand from top side from item. and when i click first item in recycler view. it expand top side from item. and some time it expand bottom side. most time it expand top side. when it expand top side from item. this time the first item expanded view hide behind the toolbar. so this is the error i think. if u have any solution then give me. plaese give any solution

Is it possible to collapse when click on "expanded" content

I'm using RecyclerView. When I click on an Item the content (Relative Layout) is expanded well. To collapse this expanded content I have to click on Item.

Is it possible to collapse the expanded content after clicking on it (in my case click on a Relative Layout).

Thank you for making this awesome library. <3

Issue using expandable layout in recycler view

The first time I expand an item, I don't get onClicked event, only after I expand/collapse a second time and I don't know why.

Here's my code :

`public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.ViewHolder>{
private static final int UNSELECTED = -1;
private List restaurantList;
private static int selectedItem = UNSELECTED;
private RecyclerView recyclerView;
private Context context;

//constructor, call on creation
public RestaurantAdapter(ArrayList<Restaurant> restaurantList, RecyclerView recyclerView, Context context) {
    this.restaurantList = restaurantList;
    this.recyclerView = recyclerView;
    this.context = context;
}

// Create new views (invoked by the layout manager)
@Override
public RestaurantAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                       int viewType) {
    // create a new view
    View v =  LayoutInflater.from(parent.getContext())
            .inflate(R.layout.list_item_layout, parent, false);
    // set the view's size, margins, paddings and layout parameters
    Log.w("RestaurantAdapter", "View created");

    ViewHolder vh = new ViewHolder(v);
    return vh;
}

@Override
public void onBindViewHolder(RestaurantAdapter.ViewHolder holder, int position) {
    Restaurant restaurant = restaurantList.get(position);
    holder.name.setText(restaurant.getName());
    holder.distance.setText(restaurant.getDistance() + " m");
    Log.w("RestaurantAdapter", "Data binded");

    holder.bind();
}

@Override
public int getItemCount() {
    return restaurantList.size();
}

public List<Restaurant> getRestaurantList() {
    return restaurantList;
}

public void setRestaurantList(List<Restaurant> restaurantList) {
    this.restaurantList = restaurantList;
}

// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, ExpandableLayout.OnExpansionUpdateListener{
    // each data item is just a string in this case

    private TextView name, distance;
    private Button details;
    private ExpandableLayout expandableLayout;
    private LinearLayout layoutTextView;
    private ViewHolder holder;



    private ViewHolder(View v) {
        super(v);
        name = (TextView) v.findViewById(R.id.listTitle);
        distance = (TextView) v.findViewById(R.id.listDistance);
        expandableLayout = v.findViewById(R.id.expandable_layout);
        layoutTextView = v.findViewById(R.id.layoutTextView);
        details = (Button) v.findViewById(R.id.details);
        expandableLayout.setInterpolator(new OvershootInterpolator());
        expandableLayout.setOnExpansionUpdateListener(this);
        layoutTextView.setOnClickListener(this);



    }

    @Override
    public void onClick(View v) {
        Log.w("RestaurantAdapter", "View clicked");
        final ViewHolder holder = (ViewHolder) recyclerView.findViewHolderForAdapterPosition(selectedItem);

        if(holder != null) {
            holder.details.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent i = new Intent(context, RestaurantActivity.class);
                    Toast.makeText(context, "Activity Launched", Toast.LENGTH_SHORT).show();
                    holder.layoutTextView.setSelected(false);
                    holder.expandableLayout.collapse();
                }
            });

            holder.layoutTextView.setSelected(false);
            holder.expandableLayout.collapse();
        }


        int position = getAdapterPosition();
        if (position == selectedItem) {
            selectedItem = UNSELECTED;

        } else {
            layoutTextView.setSelected(true);
            expandableLayout.expand();
            selectedItem = position;
        }
    }



    @Override
    public void onExpansionUpdate(float expansionFraction, int state) {
        Log.d("ExpandableLayout", "State: " + state);
        if (state == ExpandableLayout.State.EXPANDING) {
            recyclerView.smoothScrollToPosition(getAdapterPosition());
        }
    }

    private void bind() {
        int position = getAdapterPosition();
        boolean isSelected = position == selectedItem;

        layoutTextView.setSelected(isSelected);
        expandableLayout.setExpanded(isSelected, false);
    }

}

}
`

crashes when the ExpandableLayout contains LinearLayout or any ViewGroup

I have this code in RecyclerView:

        <net.cachapa.expandablelayout.ExpandableLayout
            android:id="@+id/expandable_note"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:el_duration="200"
            app:el_expanded="false">

            <View
                android:layout_gravity="top"
                android:layout_width="match_parent"
                android:layout_height="10dp"
                android:background="@drawable/gradient_shadow"/>

            <EditText
                android:id="@+id/et_note"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/hint_note"
                android:padding="16dp"/>


        </net.cachapa.expandablelayout.ExpandableLayout>

The error message is this:

android.view.InflateException: Binary XML file line #204: Binary XML file line #204: Error inflating class <unknown>

I tried to wrap the views to LinearLayour, RelativeLayout and Framelayout inside the ExpandableLayout, however, i still get the same error

It works only when I put single view inside the ExpandableLayout

Feature request: Listener for state changed

Hi, can we have a listener for state changed ?. Something like: onExpaned, onCollapsed...

I tried to use onExpansionUpdateListener but the expansionFraction param won't return the correct value 0 or 1, and it's performance related if I have to check expansionFraction many times during the animation.

Call API and set child view dynamically not displaying data when view scrolled

Hi,

Kindly help me out for this situation.

I'm having recyclerview and on view click I used your library for expand and collapse. Issue here is expandableview layout has been created dynamically based on the API response. So on the time of API loading if I scroll the layout then the view not updated with the records from API.

I guess onBindView will get called on scroll and view got refreshed. But I'm not sure how to load childview data when scrolled.

I inserted "notifiyItemChanged" in OnBindHolder but it throws exception layout can be refreshed on scroll Illegal state exception. Kindly share your thoughts.

prefix attributes names

There is a collision with the attribute orientation when using this lib with others that also define an attribute "orientation". This would be fixed by renaming "orientation" into "el_orientation"

Using Expandable Layout in Recycler View

Sometimes before closing when the view is scrolled out(fling action) and recycled, the expandable layout bugs out with partially opened view with the height expanded only part way, when calling collapse on that the height doesn't reduce but the views inside disappear.

Also the duration is set as 1000ms.

Also sometimes it won't expand at all, also the expandable area is not a small one like in the example, its around 200dp in height.

BounceInterpolator only settle after the second click

I am using Bounce Interpolator with the Expandable layout but when i expand i need to click at least two time for it close again. If i don't use any interpolator everything works like it should.

if (details.isExpanded()) {
    details.collapse();
    vPrecoComum.animate().alpha(1).start();
    details.animate().alpha(0).setDuration(300).start();
    expandButton.animate().rotation(0).start();
} else {
    details.expand();
    vPrecoComum.animate().alpha(0).start();
    details.animate().alpha(1).setDuration(300).start();
     expandButton.animate().rotation(180).start();
}

I tried debugging it end i saw that the expansion value is 1.0000545 on the first click.

Setting expansion level smoothly?

I was trying to emulate a semi collapsed/expanded view - similar to how Google Play Store uses READ MORE / READ LESS for its app descriptions page.

I set it up so that the expansion level is set to 20% using the setExpansion() method. However, the state change is rather abrupt. I realize this is intended behavior but is there a way to pass an expansion level and it smoothly expands/collapses to that point?

Releases page out of date

Hi,

It really confused me that the releases page was out of date - I often look there in github repos to find the latest version. Perhaps if you are no longer using it you should delete the existing releases?

Can`t create ExpandableLinearLayout programmatically.

I tried to create ExpandableLinearLayout programmatically but there is only one LayoutParams constructor LayoutParams(Context c, AttributeSet attrs).

Could you override other LinearLayout.LayoutParams constroctors without AttributeSet parametr?

Love your library

You should mention in your read me that if you're adding inflated views to the Expandable Layout programmatically you need to put the app:layout_expandable="true" attribute on the root view in your xml layout in order for it to work.

Expanding/collapsing Inhibits

If expandableLayout is at the bottom of layout and child view(im using listView) going out of the screen to bottom, animation of expanding and collapsing start lagging. But if i have a lot of items in listView, animation disappears at all.
How can i fix it?

Unable to resolve library

Hi, thank you for this cool library! However, when I tried to use it in my project, syncing the gradle always results in

Error:(69, 13) Failed to resolve: net.cachapa.expandablelayout:expandablelayout:[latest_version]

I'm using latest Android Studio (2.3) and latest support library in my project. Importing this repo as module triggers error: com.novoda.bintray-release is not found (can't find it in AS maven central lookup either).

Is there any additional step that I need to do to add this into my gradle dependency?

PS: I've also tried changing the [latest_version] to 1.2.0 or any other version but the error still there. I've tried looking up your lib in the maven central lookup in AS, but there's nothing...

Skipped frames

The expand/collapse causes big frame skipping on Nexus 7 device when this layout is used in recycler view, but behaves seemingly on other devices. What might be the cause of such behavior?

Make item fully visible after expanding

I just noticed that if i scroll to the last item and click to expand, then part of the opened view is invisible. How can i scroll down to make the whole view visible?

Every 8th item being expanded in RecyclerView

Issue: When I click a card item in a RecyckerView every 8th item is expanded as well as the item clicked.

Example: There are 24 items in a List. I click item position 1, it expands. Scrolling down the list, also the 8th item is expanded, 16th and 24th.

Expected behaviour: Only the clicked item is expanded

     /**
     * Toggle the expanded state on a card item
     *
     * @param holder The ViewHolder
     * @param position The position of the card that was clicked
     */
    public void toggleExpandedCard(ListViewHolder holder, int position) {
        final String expandIcon = context.getResources().getString(R.string.mc_chevron_down);
        final String collapseIcon = context.getResources().getString(R.string.mc_chevron_up);

        Log.d(TAG, "Expanded position is: " + expandedPosition);
        Log.d(TAG, "Clicked position is " +  position);

        // If nothing is expanded, expand as normal
        if (expandedPosition == RecyclerView.NO_POSITION) {
            holder.mExpandIcon.setText(collapseIcon);
            holder.mDetailedView.expand();
            expandedPosition = position;
            return;
        }

        // If not clicking the currently expanded item
        // Close the other first
        if (expandedPosition != position) {
            ListViewHolder expandedViewHolder
                    = (ListViewHolder) recyclerView.findViewHolderForAdapterPosition(expandedPosition);
            if (expandedViewHolder != null) {
                expandedViewHolder.mDetailedView.collapse();
                expandedViewHolder.mExpandIcon.setText(expandIcon);
            }
            holder.mDetailedView.expand();
            holder.mExpandIcon.setText(collapseIcon);

            expandedPosition = position;

            return;
        }

        holder.mExpandIcon.setText(expandIcon);
        holder.mDetailedView.collapse();
        expandedPosition = RecyclerView.NO_POSITION;

        toggleExpansion(position);
    }

Release notes

It would be nice to have a release notes for new versions of the library to have an overview of the changes/improvements.

Thank you for your work.

Auto-scroll to the bottom in the demo

When using the library with a RecycleView, at startup and whenever you update your adapter, it will automatically scroll to the bottom of the recycleview.

Not a big deal, you just have to add the check of the state in the RecyclerViewFragment to prevent it.

    @Override
    public void onExpansionUpdate(float expansionFraction, int state) {
        if(state!=ExpandableLayout.State.COLLAPSED)
            recyclerView.smoothScrollToPosition(getAdapterPosition());
    }

Actually this is not really an issue, but I think this can prevent some unexpected behaviour and still be consistent to the general case.

Collapsed Layout?

It would be really helpful to support a collapsed layout as well for situations where you want to show some content, then expand to show more. In my case the description of an article.

Error inflating class

Hi,

When i use ExpandableLayout with RecyclerView, the Android doesn't allow to inflate class.

The error report:

"FATAL EXCEPTION: main android.view.InflateException: Binary XML file line #38: Error inflating class net.cachapa.expandablelayout.ExpandableLayout"

And points to the following line of my code:

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.expandable_minha_consulta_row, parent, false);

animation in scroll view did not run properly

When i click the item of recycler view . the item go upside of screen and hide below toolbar. issue come in recycle srollbar. when click of item item that still stand at one place and except whole recycler view go upside of screen and hide behind the toolbar

Expand Horizontal right to left

Hi, I am currently using your library for a layout that expands vertically in my project, and it works perfectly. But now I have a feature that needs another layout to be expanded from right to left (horizontal).
I can achieve this by using the old ExpandableLinearLayout with android:orientation="horizontal" and android:layoutDirection="rtl", but there is a glitch in the animation and it's deprecated anyway.
I try to use ExpandableLayout but it somehow expands the layout from the middle, please help.

how to use layout_expandable arrr?

<declare-styleable name="ExpandableLayout">
        <attr name="el_duration" format="integer" />
        <attr name="el_expanded" format="boolean" />
        <attr name="el_parallax" format="float" />
        <attr name="layout_expandable" format="boolean" />
        <attr name="android:orientation"/>
    </declare-styleable>

how to use layout_expandable attr? or how to realize it?

Expanding last visible item

In RecyclerView, when I'm expanding my last visible element, it expands out of the screen. When I want to see the expanded layout I need to manually scroll RecyclerView. Is there an option to automatically scroll the RecyclerView so when I open last visible element it automatically scrolls the recyclerView as well?

ExpandableLayout stucks

When I expand an ExpandaleLayout a second time the animation of stucks, but expanding the first time is no problem.

Does anyone know this problem and can help me.

Cannot change layout background color for collapsed and expanded view

I am trying to change layout background color for collapsed and expanded view in a recyclerview, here I'm able expand and collapse the same view. But when I tried to tap other content the previously selected view background color remains unchanged. Is there any way to change the collapsed and expanded color background.

Multiple RecyclerViews

Hello,
I am using a vertical RecyclerView and in every item of this RecyclerView I have a horizontal RecyclerView. What I'm trying to achieve is when I click on an item of vertical one, its horizontal child should expand. It works actually, but my inner RecyclerView's items are disappearing after expanding. If I call adapter.notifyDataSetChanged when State==Expanded inner recyclerview shows properly, but as you can imagine I cannot see expanding animation if I do that. Besides, I'm fetching photos from firebase and whenever I call notifyDataSetChanged this causes heavy network operation again and again.

Long story short, is there a way prevent my inner RecyclerView being disappearing so I won't need to call notifyDataSetChanged again? Thanks in advance.

collapse(false) and expand(false) do not work.

If I understand correctly, these methods should expand/collapse view instantly without animation, but they do nothing.

I have expandable view in recycler. I fill it (it contains LinearLayout) with additional views in adapter.
Expanding/Collapse works correctly when there is animation, but if there is no animation nothing happens.

Please advise.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.