Android Expandable text view with "View More" Button displaying at center after 3 lines
Asked Answered
H

3

10

I want to display description in a text view, if the description is more than 3 lines i want to display a View more button that expands the text view with complete description (or a dialog with complete description)

I have referred some links
1) How can I implement a collapsible view like the one from Google Play?

The above solution has an arrow like image view at end of third line of text view but i want a button displaying below the text view if description crosses 3 lines.

2) Add "View More" at the end of textview after 3 lines

The above solution has "View More" unaligned( "View" at 3rd line and "More" at 4th line)

I am looking for something like this. enter image description here

Holmic answered 28/7, 2015 at 6:19 Comment(3)
did you get answer ?Citrate
Yes i was able to get it, looking for answer?Holmic
can you post that as answer ? so other member can see it and get help form itCitrate
H
23

This is how i have achieved the desired output,

MytextView which i want to expand is: tvDescription I have a see more button with name: btnSeeMore

To check if the textview has more than 4 lines i had a listener for it as follows,

tvDescription.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    if(expandable) {
                        expandable = false;
                        if (tvDescription.getLineCount() > 4) {
                            btnSeeMore.setVisibility(View.VISIBLE);
                            ObjectAnimator animation = ObjectAnimator.ofInt(tvDescription, "maxLines", 4);
                            animation.setDuration(0).start();
                        }
                    }
                }
            });

I have kept a boolean value to check if textview is already expanded so that there will not be any hickups while collapsing it.

if textview has more than four lines, boolean flag will be true and the button will be visible so this is the code for expanding and collapsing animation.

btnSeeMore.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {

                if (!expand) {
                    expand = true;
                    ObjectAnimator animation = ObjectAnimator.ofInt(tvDescription, "maxLines", 40);
                    animation.setDuration(100).start();
                    btnSeeMore.setImageDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.ic_collapse));
                } else {
                    expand = false;
                    ObjectAnimator animation = ObjectAnimator.ofInt(tvDescription, "maxLines", 4);
                    animation.setDuration(100).start();
                    btnSeeMore.setImageDrawable(ContextCompat.getDrawable(getActivity(),R.drawable.ic_expand));
                }

            }
        });

Comment below for further information

Holmic answered 14/12, 2015 at 5:40 Comment(1)
Don't forget to call "getViewTreeObserver().removeOnGlobalLayoutListener(this);" inside onGlobalListener or you might get into an infinite loop.Pepys
A
20

Easy and Simple way to achieve this is.

sample.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/tvSongDes"
        android:layout_marginStart="@dimen/dimen16"
        android:layout_marginEnd="@dimen/dimen16"
        android:layout_marginTop="@dimen/dimen16"
        android:maxLines="3"
        android:text="Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy Dummy dummy "
        android:layout_width="match_parent"
        android:layout_height="wrap_content"

        />

    <Button
        android:id="@+id/btShowmore"
        android:layout_width="wrap_content"
        android:layout_marginStart="@dimen/dimen16"
        android:text="Showmore..."
        android:textAllCaps="false"
        android:textColor="@android:color/holo_blue_light"
        android:background="@android:color/transparent"
        android:layout_height="wrap_content" />
</LinearLayout>

and inside your Activity onCreate..

 TextView tvSongDes;
    Button btShowmore;
          @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_devotional_songs_play);
                tvSongDes=(TextView)findViewById(R.id.tvSongDes);
                btShowmore=(Button)findViewById(R.id.btShowmore);
                btShowmore.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

               if (btShowmore.getText().toString().equalsIgnoreCase("Showmore..."))
                        {
                            tvSongDes.setMaxLines(Integer.MAX_VALUE);//your TextView
                            btShowmore.setText("Showless");
                        }
                        else
                        {
                            tvSongDes.setMaxLines(3);//your TextView
                            btShowmore.setText("Showmore...");
                        }
                    }
                });

            }

Hoping it will be helpfull for someone.

Advocation answered 29/6, 2017 at 9:53 Comment(1)
it looks really simple and clean. i feel it will be further smart to have a custom view where we could just pass NUMBER_OF_LIINES to limit the in the XML arguments... in other words, It will be better if we would have to use only one View for this, and it takes MAX_LINE_1 and MAX_LINE_2 and text as argCooky
K
0

Latest method , using MotionLayout as the parent layout, no custom views requires, can be done only with xmls files.

'MotionLayout' is a subclass of ConstrainLayout.

Steps are :-

  1. Create the entire layout with ConstraintLayout as the parent layout.

  2. Covert the parent layout to MotionLayout.

  3. Now we need to create a animation through a motionscene file that we will create as motionscene.xml . It will contain the states of our textview and morebutton before and after the click event of the morebutton. And it also contains the transition information.

    The code for this step :-

    <?xml version="1.0" encoding="utf-8"?>
    <MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
    
     <ConstraintSet android:id="@+id/start">
        <Constraint android:id="@+id/disc_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/discription_title">
    
            <CustomAttribute app:attributeName="maxLines"
                app:customIntegerValue="3"/>
    
        </Constraint>
    
    
    </ConstraintSet>
    
    <ConstraintSet android:id="@+id/end">
        <Constraint android:id="@+id/disc_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/discription_title">
    
            <CustomAttribute app:attributeName="maxLines"
                app:customIntegerValue="100"/>
    
        </Constraint>
        <Constraint android:id="@+id/more_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/disc_text">
    
            <CustomAttribute app:attributeName="alpha"
                app:customFloatValue="0.0"/>
    
        </Constraint>
    
    </ConstraintSet>
    
    <Transition
        app:constraintSetEnd="@id/end"
        app:motionInterpolator="easeIn"
    
        app:constraintSetStart="@+id/start"
        app:duration="200">
    
        <OnClick app:clickAction="transitionToEnd"
            app:targetId="@+id/more_text"/>
    
    </Transition>
    </MotionScene>
    
  4. Set this layout as the layoutDiscrition for the parent MotionLayout that we created initially.

    Enjoy the animation!!.

Kemp answered 27/9, 2020 at 16:2 Comment(1)
Can you show a detailed example for this?Womera

© 2022 - 2024 — McMap. All rights reserved.