6

I want to ask about how can we create Scroll TextView action bar as Whatsapp lastseen's status. Please open whatsapp and see what is status look like :)

Before: enter image description here

Then it will start scroll and we can see the text like this : "seen yesterday at ....."

And After scroll: enter image description here

Khoa Tran
  • 471
  • 6
  • 16

6 Answers6

3

Inspired with this answer, tried to make this solution. Hope this will work for you.

Step - 1 : Create Typewriter class.

public class Typewriter extends TextView {

        private CharSequence mTextToHide, mTextToDisplay;
        private int mIndex;
        private long mInitialDelay = 2000; //Default 500ms delay
        private long mDelay = 500; //Default 500ms delay
        private Handler mHandler = new Handler();
        private Runnable characterAdder = new Runnable() {
        @Override
        public void run() {
    //            setText(mText.subSequence(0, mIndex++));
    //            if (mIndex <= mText.length()) {
    //                mHandler.postDelayed(characterAdder, mDelay);
    //            }

            if (mTextToHide != null
                && mTextToDisplay != null && mIndex < mTextToHide.length()) {
            Log.d("Typewriter", "mIndex = " + mIndex);
            setText(mTextToDisplay.subSequence(mIndex++, mTextToDisplay.length()));
            mHandler.postDelayed(characterAdder, mDelay);
            }
        }
        };

        public Typewriter(Context context) {
        super(context);
        }

        public Typewriter(Context context, AttributeSet attrs) {
        super(context, attrs);
        }

        public void animateText(CharSequence textToHide, String textToDisplay) {
        mTextToHide = textToHide;
        mTextToDisplay = textToDisplay;
        mIndex = 0;

    //        setText("");
        setText(textToDisplay);
        mHandler.removeCallbacks(characterAdder);
        mHandler.postDelayed(characterAdder, mInitialDelay);
        }

        public void setCharacterDelay(long millis) {
        mDelay = millis;
        }

        public void setInitialDelay(long millis) {
        mInitialDelay = millis;
        }
    }

Step - 2 : Extend it in xml in place of TextView. Replace com.abc.xyz with respective package name.

         <com.abc.xyz.Typewriter
            android:id="@+id/txtAppTitle"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_gravity="left"
            android:layout_marginLeft="@dimen/activity_horizontal_margin"
            android:singleLine="true"
            android:textColor="@color/white"
            android:textSize="@dimen/font_size_toolbar_title" /> 

Step - 3 : Set values from your activity or fragment class. Set parameters as per your requirements.

    public static String LAST_SEEN_TEXT = "last seen ";
    public static String TIME_TEXT = "yesterday at 15:43";

    private Typewriter txtAppTitle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ...

    txtAppTitle = (Typewriter) findViewById(R.id.txtAppTitle);
    // Start after 2000ms
    txtAppTitle.setInitialDelay(2000);
    // Remove a character every 150ms
    txtAppTitle.setCharacterDelay(250);
    txtAppTitle.animateText(LAST_SEEN_TEXT, LAST_SEEN_TEXT + TIME_TEXT);

    ...
    }
Community
  • 1
  • 1
Chitrang
  • 4,840
  • 1
  • 31
  • 49
  • I was imagining it something like this. I am just wondering does it look like a smooth translate animation or not? – dragi May 24 '16 at 17:40
  • Translation is not as smooth as some animation but yes it does look some what similar to it. – Chitrang May 25 '16 at 05:30
1

add following properties :

<TextView
android:text="text"
android:id="@+id/marquee_text" 
android:layout_width="fill_parent"
android:layout_height="wrap_content" 
android:singleLine="true"
android:ellipsize="marquee" 
android:marqueeRepeatLimit=""//once or marquee_forever
android:scrollHorizontally="true" 
android:paddingLeft="15dip" 
android:paddingRight="15dip" 
android:focusable="true" 
android:focusableInTouchMode="true" 
android:freezesText="true">
Logic
  • 2,210
  • 1
  • 20
  • 40
  • Let me try. I didn't use freezesText. I will try and response to you. Thank you. – Khoa Tran Jan 12 '16 at 07:06
  • It doesn't work. I mean I want textview will scroll then stop at "yesterday at 15:43" . Only once time. – Khoa Tran Jan 12 '16 at 07:08
  • after the activity is loaded (i.e, textview is shown) wait for 2seconds(or the time it takes to scroll till end) and then set the text you required to that textview. and then `mTextView.setEllipsize(null);`. now text stops at where you want it to. – Logic Jan 12 '16 at 09:19
  • wait for 2seconds(or the time it takes to scroll till end) <<< How can I know the value of that? – Khoa Tran Jan 13 '16 at 07:56
  • run once and observe the time it is taking to scroll completely till end – Logic Jan 13 '16 at 08:00
  • well, I think your logic is not safe enough. It will depends on screen size, device etc and we can't make sure the time is right value. – Khoa Tran Jan 13 '16 at 16:29
1

Use Marquee to text view.

<TextView
android:text="Really Long Scrolling Text Goes Here.... ..... ............ .... ...."
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="1"
android:scrollHorizontally="true"
android:id="@+id/TextView03"
android:padding="5dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

And in java file you can check that your text is fully scroll. And set RepeatLimit once and set textview single line true . And set right of the image.

 TextView tv = (TextView) this.findViewById(R.id.TextView03);  
 tv.setSelected(true);

I think this will solve your issue.

0

Just add following attributes to your TextView then it works exact you want:

android:singleLine="true" 
android:ellipsize="marquee"
android:marqueeRepeatLimit ="1"
android:scrollHorizontally="true"
android:focusable="true"
android:focusableInTouchMode="true"

you must have to define TextView.setSelected(true); in your Java code

Here is explanation of above attributes from Android documentation:

android:marqueeRepeatLimit

The number of times to repeat the marquee animation. Only applied if the TextView has marquee enabled.

May be an integer value, such as "100".

android:ellipsize

If set, causes words that are longer than the view is wide to be ellipsized instead of broken in the middle. You will often also want to set scrollHorizontally or singleLine as well so that the text as a whole is also constrained to a single line instead of still allowed to be broken onto multiple lines.

EDIT:

you can set android:marqueeRepeatLimit attribute's value to 1 to scroll only one time then it will stop.

I hope it helps you.

Rajesh
  • 12,393
  • 4
  • 47
  • 76
  • I mean it will scroll then stop at "yesterday at 15:43". – Khoa Tran Jan 12 '16 at 07:05
  • Yeah I know it but I don't know how can make it scroll once time and hide text last seen. That's mean the default text it : "last seen at abcxyz" then it will scroll and stop with text "at abcxyz" – Khoa Tran Jan 12 '16 at 07:12
  • i think you can set "at abcxyz" text after some delay using handler and stop scrolling using TextView.setSelected(false); – Rajesh Jan 12 '16 at 07:23
0

This is the perfect answer for you.

Once try below code:

public class MarqueeLayoutActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    TextView textView = new TextView(this);
    textView.setText("I'm the fancy MarqueeLayout.");

    MarqueeLayout marqueeLayout = new MarqueeLayout(this);
    marqueeLayout.setDuration(10000);
    marqueeLayout.addView(textView);
    marqueeLayout.startAnimation();

    setContentView(marqueeLayout);
 }
}

Class which contains the animation of text:

public class MarqueeLayout extends FrameLayout {
private Animation animation;

public MarqueeLayout(Context context) {
    super(context);

    animation = new TranslateAnimation(
            Animation.RELATIVE_TO_SELF, +0.4f,
            Animation.RELATIVE_TO_SELF, -0.2f,
            Animation.RELATIVE_TO_SELF, 0f,
            Animation.RELATIVE_TO_SELF, 0f
    );

    animation.setRepeatCount(Animation.ABSOLUTE);
    animation.setRepeatMode(Animation.ABSOLUTE);
    animation.setFillAfter(true);

}

public void setDuration(int durationMillis) {
    animation.setDuration(durationMillis);
}

public void startAnimation() {
    startAnimation(animation);
 }
}
Saritha G
  • 2,365
  • 1
  • 13
  • 25
0

My Solution:

final TextView textView = (TextView)findViewById(R.id.text);

    textView.setSingleLine();

    textView.animate()
            .translationX(dip2px(MainActivity.this, -100))
            .setDuration(200)
            .setInterpolator(new AccelerateDecelerateInterpolator())
            .setStartDelay(2000)
            .start();

    ValueAnimator anim= ValueAnimator.ofInt(textView.getMaxWidth(),textView.getMaxWidth()+ dip2px(MainActivity.this, 200));
    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int value = (int) animation.getAnimatedValue();
            textView.setMaxWidth(value);
        }
    });
    anim.setDuration(200);
    anim.setStartDelay(2000);
    anim.start();

DP to PX method:

 public static int dip2px(Context context, float dipValue) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, context.getResources().getDisplayMetrics());
}

Sample XML:

<TextView
    android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:maxWidth="120dp"
    android:ellipsize="end"
    android:text="Hello World!, Hello World!" />

you can set your values for your layout.

eralp
  • 113
  • 6