An Android TextView that always displays an auto refreshing relative time span with respect to a reference time

Overview

android-ago

This library provides RelativeTimeTextView, a custom TextView that takes a reference time and always displays the relative time with respect to the reference point, automatically refreshing the display text as needed. This is a common pattern seen in several apps like chat apps, social networking, email etc.

Here is a screenshot from the sample app

This library can be seen as a wrapper on top of the excellent android.text.format.DateUtils class. Note that the library does not expose all the options provided by the DateUtils class. I have left out many features because I couldn't decide what would be the best way to achieve the flexibility - dozens of XML attributes? Contributions in this regard are welcome.

Why should I use this instead of DateUtils class?

Because this library automatically refreshes the display text as needed. It internally uses DateUtils class.

Imagine you use DateUtils directly without using this library.

  • Imagine that it is 9 am now. You set a reference time of 9:05 am. Your TextView displays in 5 mins
  • Now the time becomes 9:01 am. You still display in 5 mins even though you should be showing in 4 mins

To do this correctly, you will need to keep refreshing the text views every minute. However, even that is not necessary. If the reference time is 3 hours from now, you only need to refresh every hour - not every minute.

This library handles all of this for you. RelativeTimeTextView automatically refreshes the display text only as often as necessary.

Obtaining

Gradle

Add the following to your build.gradle

dependencies {
    compile 'com.github.curioustechizen.android-ago:library:1.4.0'
}

Important: v1.3.4 Fixed a major bug (#47). If you are using an older version, please update to at least 1.3.4 now.

Eclipse+ADT

  1. Clone the repo
  2. In Eclipse, go to File -> New -> Other. Expand Android and select Android Project from Existing Code
  3. Browse to the android-ago sub-folder of the cloned repo and hit Finish

Usage

  • Include RelativeTimeTextView in your layouts.
  • Set the reference time either using setReferenceTime method or using the XML attribute reference_time.

In your layout:

<com.github.curioustechizen.ago.RelativeTimeTextView
    android:id="@+id/timestamp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/margin_primary" />

In your Java code:

RelativeTimeTextView v = (RelativeTimeTextView)findViewById(R.id.timestamp); //Or just use Butterknife!
v.setReferenceTime(new Date().getTime());

See the sample project for a concrete example.

Customization

By default, this library simply calls DateUtils.getRelativeTimeSpanString. This might not be sufficient for you. For example, you might need to add a prefix. RTTV provides a hook for such cases - the getRelativeTimeDisplayString method. You can override this method and add whatever prefixes or suffixes you need.

Here is a simple example:

<!-- strings.xml -->
<string name="format_relative_time_with_prefix">Updated %1$s</string>
class PrefixRttv extends RelativeTimeTextView {
    @Override
    protected CharSequence getRelativeTimeDisplayString(long referenceTime, long now) {
        final String relativeTime = super.getRelativeTimeDisplayString(referenceTime, now);
        return getResources.getString(R.string.format_relative_time_with_prefix, relativeTime);
    }    
}

More examples in the sample project

Advanced customization

What if the string returned by DateUtils.getRelativeTimeSpanString does not suit you? Well, you can still use RTTV for its auto-refresh capability and take over complete control of the display string itself. Simply override getRelativeTimeDisplayString and don't call through to the super method. Instead, perform your own logic and return whatever string you wish here.

<!-- strings.xml -->
<string name="future">Some day, in the distance future</string>
<string name="past">Once upon a time, long long ago</string>
<string name="now">Right NOW!</string>
class FullyCustomRttv extends RelativeTimeTextView {
    @Override
    protected CharSequence getRelativeTimeDisplayString(long referenceTime, long now) {
        //Notice that we don't call super here.
        int resourceId = 0;
        if(referenceTime == now) resourceId = R.id.now;
        else if(referenceTime > now) resourceId = R.id.future;
        else resourceId = past;
        
        return getResources().getString(resourceId);
    }    
}

See the examples in the sample project for more details.

Who's Using this Library?

See here. If you would like to add your app to this list, please edit the wiki.

Android version support statement

The library has been tested on API 11 and above. However, theoretically, it works on API 3 and above since all it uses is [DateUtils#getRelativeTimeSpanString](http://developer.android.com/reference/android/text/format/DateUtils.html#getRelativeTimeSpanString(long, long, long, int)).

The minSdkVersion has been set to 8, however do not expect support from me for API version < 11.

Usage with Data Binding

See android-ago-sample-databinding for an example of how to use this library with the Android data binding library. Thanks to @Dev-IL for providing this sample.

License

Copyright 2017 Kiran Rao

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.
Comments
  • in 0 mins

    in 0 mins

    Seems to happen basically the moment a new item is added with timestamp = now, shortly after that, the value changes to "Just now" as expected

    bug Help wanted 
    opened by broakenmedia 14
  • Removing the

    Removing the "ago" word

    Is there any way to remove the "ago" word from the RelativeTimeTextView? To be more clear for example if the RelativeTimeTextView is showing this String "16 min. ago" can I convert it to "16 min." this way is more user friendly ...you know shortest text is always better
    thanks in advance

    opened by abdulmalekDery 6
  • RelativeTimeTextView and memory leaks

    RelativeTimeTextView and memory leaks

    I think this library is causing some memory leaks - can you please fix?

    I tested this with LeakCanary: https://github.com/square/leakcanary

    And it keeps on detecting a memory leak here:

    01-27 21:07:53.075 4217-4353/? D/LeakCanary: In com.example.simon.recyclerviewlistwithmongo:1.0:1.
    01-27 21:07:53.075 4217-4353/? D/LeakCanary: * com.example.simon.activities.PostDetailActivity has leaked:
    01-27 21:07:53.075 4217-4353/? D/LeakCanary: * GC ROOT android.view.ViewRootImpl$WindowInputEventReceiver.mMessageQueue
    01-27 21:07:53.075 4217-4353/? D/LeakCanary: * references android.os.MessageQueue.mMessages
    01-27 21:07:53.075 4217-4353/? D/LeakCanary: * references android.os.Message.callback
    01-27 21:07:53.075 4217-4353/? D/LeakCanary: * references com.github.curioustechizen.ago.RelativeTimeTextView$UpdateTimeRunnable.this$0
    01-27 21:07:53.075 4217-4353/? D/LeakCanary: * references com.github.curioustechizen.ago.RelativeTimeTextView.mContext
    01-27 21:07:53.075 4217-4353/? D/LeakCanary: * references android.support.v7.view.ContextThemeWrapper.mBase
    01-27 21:07:53.075 4217-4353/? D/LeakCanary: * leaks com.example.simon.activities.PostDetailActivity instance
    01-27 21:07:53.075 4217-4353/? D/LeakCanary: * Reference Key: f949ab86-5469-40cf-9f6b-bae54f1eedfa
    01-27 21:07:53.075 4217-4353/? D/LeakCanary: * Device: Genymotion generic Samsung Galaxy S2 - 4.1.1 - API 16 - 480x800 vbox86p
    01-27 21:07:53.075 4217-4353/? D/LeakCanary: * Android Version: 4.1.1 API: 16 LeakCanary: 1.3.1
    01-27 21:07:53.075 4217-4353/? D/LeakCanary: * Durations: watch=5009ms, gc=116ms, heap dump=259ms, analysis=9831ms
    
    

    Suggest fix: Please replace the context that is passed in RelativeTimeTextView.mContext with an ApplicationContext.

    Thanks!

    bug Help wanted 
    opened by Winghin2517 6
  • Once the `UpdateTimeRunnable` is detached and the `weakRefRttv` cleared, it is never attached again

    Once the `UpdateTimeRunnable` is detached and the `weakRefRttv` cleared, it is never attached again

    In the stopTaskForPeriodicallyUpdatingRelativeTime() method, the mUpdateTimeTask is detached, resulting in the weak reference that connects it the the RelativeTimeView being cleared. In the startTaskForPeriodicallyUpdatingRelativeTime() method, the same mUpdateTimeTask is reused, but the weak reference is still null. As a consequence, the run() method in the runnable cannot update the text view.

    It should be pretty easy to reproduce. Any action that results in the stopTaskForPeriodicallyUpdatingRelativeTime() method being called should cause the time to stop being updated. For example, minimize the app and restore it.

    bug 
    opened by corneliudascalu 4
  • Feature request: Support for Data Binding

    Feature request: Support for Data Binding

    I'm building an app that relies heavily on data binding. I was trying to include an instance of RelativeTimeTextView with XML bindings for app:relative_time_prefix and app:reference_time - however this results in a compilation-time error:

    Error:java.lang.RuntimeException: Found data binding errors.
            ****/ data binding error ****msg:Cannot find the setter for attribute 'app:relative_time_prefix' with parameter type java.lang.String.
    

    I'm not sure if what's causing this is the fact attributes/fields aren't set as @Bindable or Observable.., or that the property setters aren't named like the binding expects (if I understand the Data Binding documentation correctly).

    Needless to say that when I remove the bindings of these fields from my XML, the compilation succeeds.

    It would be awesome if somebody could add this support - and help make the library more future-proof :)


    I'm using the following XML (irrelevant portions removed):

    <data>
        <variable name="message" type="..."/>
    </data>
    ....
    <com.github.curioustechizen.ago.RelativeTimeTextView
        android:id="@+id/time_n_sender"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        app:relative_time_prefix='@{"by " + message.senderName + ", "}'
        app:reference_time='@{message.timestamp}'
        tools:textColor="@color/gray"
        tools:text="by Mike, 30/02/2016 22:22:10"/>
    

    P.S. Does the format dd/MM/yyyy HH:mm:ss constitute a valid for app:reference_time?

    opened by Dev-iL 4
  • Frequent IndexOutOfBoundsException

    Frequent IndexOutOfBoundsException

    Fatal Exception: java.lang.IndexOutOfBoundsException Invalid index 1, size is 1 java.util.ArrayList.throwIndexOutOfBoundsException (ArrayList.java:251) java.util.ArrayList.get (ArrayList.java:304) android.widget.TextView.sendAfterTextChanged (TextView.java:7119) android.widget.TextView.setText (TextView.java:3574) android.widget.TextView.setText (TextView.java:3425) android.widget.TextView.setText (TextView.java:3400) com.github.curioustechizen.ago.RelativeTimeTextView.updateTextDisplay (RelativeTimeTextView.java:146) com.github.curioustechizen.ago.RelativeTimeTextView.access$200 (RelativeTimeTextView.java:22) com.github.curioustechizen.ago.RelativeTimeTextView$UpdateTimeRunnable.run (RelativeTimeTextView.java:265)

    bug 
    opened by pankajbatra 4
  • minSdkVersion?

    minSdkVersion?

    The actual library says android:minSdkVersion="14" but the sample app has android:minSdkVersion="8".

    Which is correct?

    I'm trying to add Gradle build files and it won't compile without fixing this.

    opened by intrications 4
  • Time is one hour behind on old Galaxy Tab 3 using Android 4.4.2

    Time is one hour behind on old Galaxy Tab 3 using Android 4.4.2

    HI and thanks for grate lib. Using 'com.github.curioustechizen.android-ago:library:1.3.4' and XML looks like:

         <com.github.curioustechizen.ago.RelativeTimeTextView
                    android:id="@+id/timestamp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginEnd="2dp"
                    android:layout_marginRight="2dp"
                    tools:text="Just Now"/>
    

    The time is always one hour behind. The device clock is set correctly. I am in Sweden btw. What do you think? In Sweden we have summer time adjustment that mean during summer time is set forward one hour. It feels like your lib dont take that into consideration since the time I see on the Galaxy tab 3 is normal European time(correct time) (but it will for me in Sweden be one our behind)( We do this time thing to get more daylight sunlight) https://www.timeanddate.com/time/change/sweden/malmo

    I have also a Galaxy Note 4 running android 6.0.1 and time is correct all ok

    opened by erikswed 3
  • Lack of consistent capitalization (English)

    Lack of consistent capitalization (English)

    Description

    Capitalization of the "Just Now" time text is inconsistent with the other English words and phrases used in this library.

    Version

    1.3.2

    Severity

    Minor

    Steps to Reproduce

    1. Set a time on the RelativeTimeTextView.
    2. Observe the results as the time ages.

    Actual behavior

    The relative time text starts with "Just Now" and progresses to "1 min. ago", "Yesterday", "November 16", etc.

    Expected behavior

    The "Just Now" phrase is consistent with the other words/phrases used in this library. If the time text contains more than one word, I recommend capitalizing the first word and making the remaining words lowercase similar to today's "1 min. ago" format.

    So "Just now" would become "Just now".

    enhancement 
    opened by ryandt 3
  • setReferenceTime get

    setReferenceTime get "0 time ago"

    When I set mReferenceTime lower than currentTimeMillis method getRelativeTimeDisplayString returned "0 time ago" For example: I have mReferenceTime = 10, and currentTimeMillis = 8. Method getRelativeTimeDisplayString will be return "0 time ago"

    Any ideas?

    opened by ibabuk 3
  • How to change Time text to custome one?

    How to change Time text to custome one?

    I want to change the Time's text to something like 5s, 5m instead of 5 seconds ago and 5 minutes ago. I don't know where to change to custom text.

    The reason i want to minimize is, it takes too much space when designing custom row layout.

    Thanks,

    enhancement 
    opened by YuvPrime 2
  • Modify time update interval

    Modify time update interval

    I'm wanting to show ETAs that will commonly be less than 60 minutes but may occasionally be up to 120 minutes. In the case that the ETA is 60 minutes or less, the ETA text of my RelativeTextView updates every minute. In the case where an ETA is greater than 60 minutes, the ETA text updates every hour. However, I need the ETA to update every minute regardless of the difference between now and the reference time.

    Current interval logic:

    if (difference > DateUtils.WEEK_IN_MILLIS) {
       interval = DateUtils.WEEK_IN_MILLIS;
    } else if (difference > DateUtils.DAY_IN_MILLIS) {
       interval = DateUtils.DAY_IN_MILLIS;
    } else if (difference > DateUtils.HOUR_IN_MILLIS) {
       interval = DateUtils.HOUR_IN_MILLIS;
    }
    

    I think it would be helpful to add the ability to modify the time update interval. This could be achieved in a couple ways. A) Add a public setter to set and override the time interval. B) Allow subclasses to override the method that determines the interval.

    I prefer option B as it provides more flexibility to the client.

    @curioustechizen What are your thoughts on adding the ability to modify the time update interval?

    opened by ryandt 1
Releases(v1.3.3)
  • v1.3.3(Apr 2, 2017)

    v1.3.3 [Apr 2, 2017]

    • [CHANGE]: Bumped versions of compileSdkVersion, targetSdkVersion, Gradle, Android Gradle plugin and buildToolsVersion
    • [TRANSLATIONS]: Spanish, Ukrainian, Norwegian, Arabic, Dutch, Romanian
    Source code(tar.gz)
    Source code(zip)
  • v1.3.2(Jun 12, 2016)

  • v1.3.1(May 15, 2016)

  • v1.3.0(Feb 14, 2015)

    • [CHANGE]: Set minSdk to 8
    • [CHANGE]: Cleaned up unnecessary resources
    • [MISC]: Update to latest build tools
    • [NEW]: Included tasks for publishing to Maven Central
    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Dec 16, 2014)

    Changelog:

    • Fixed NPE seen when the RelativeTimeTextView has an initial visibility="gone"
    • Fixed a bug that caused the RelativeTimeTextView to not show anything if the reference time was only set using the XML attribute reference_time
    • Updated gradle files to 1.0.0
    Source code(tar.gz)
    Source code(zip)
  • v1.1.1(Sep 2, 2014)

    Changes:

    • Added option to add prefix and suffix to the RelativeTimeTextView (Credit @xiprox )
    • Updated to recent versions of gradle, gradle plugin, build tools.
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Aug 25, 2014)

Owner
Kiran Rao
Android developer
Kiran Rao
A simple and flexible Checked TextView or Checkable TextView

CheckableTextView Checkable TextView [KOTLIN] ⚡ A simple and flexible Checked TextView or Checkable TextView written in Kotlin ⚡ What's New Animation

null 110 Nov 20, 2022
Mentions-TextView - Make Mentions and hashtags clickable in Textview

Mentions Textview Custome Textview with Mentions and hashtags being clickable. D

null 2 Jan 9, 2022
AutosizeEditText for Android is an extension of native EditText that offer a smooth auto scale text size.

AutoscaleEditText AutosizeEditText for Android is an extension of native EditText that offer a smooth auto scale text size. Latest Version How to use

Txus Ballesteros 354 Nov 28, 2022
Awesome Android Typeahead library - User mention plugin, UI widget for auto complete user mention using the at sign (@) like Twitter or Facebook.

android-typeahead Awesome Android Typeahead library - User mention plugin, UI widget for auto complete user mention using the at sign (@) like Twitter

Arab Agile 11 Jun 4, 2019
Simple extension for account suggestion and auto completion.

AccountAutoCompleteEditText Just a simple implementation for use of auto complete text view with device account suggestion Usage Just simply put an cu

Keishin Yokomaku 100 Feb 22, 2022
Android's TextView that can expand/collapse like the Google Play's app description

ExpandableTextView ExpandableTextView is an Android library that allows developers to easily create an TextView which can expand/collapse just like th

Manabu S. 4k Dec 28, 2022
A library to show emoji in TextView, EditText (like WhatsApp) for Android

Discontinued This projected is discontinued. Please consider using other alternative, i.e EmojiCompat. Contact me if you want to continue working on a

Hieu Rocker 3.6k Jan 5, 2023
Android experiment showing a sinking TextView

Titanic is an Android experiment reproducing this effect.

Romain Piel 1.8k Dec 15, 2022
Advanced Android TextView

Advanced Android TextView Companion app for my Advanced Android TextView talk, demostrating: Animated CompoundDrawable Text shadow Custom font Non-bre

Chiu-Ki Chan 1.2k Dec 9, 2022
This is based on an open source autosizing textview for Android.

SizeAdjustingTextView This is based on an open source autosizing textview for Android I found a few weeks ago. The initial approach didn't resize mult

Elliott Chenger 255 Dec 29, 2022
An extension of Android's TextView, EditText and Button that let's you use the font of your choice

AnyTextView (deprecated) Note: AnyTextView is no longer being maintained. I recommend replacing AnyTextView with the Calligraphy library instead. Frus

Hans Petter Eide 165 Nov 11, 2022
Form validation and feedback library for Android. Provides .setText for more than just TextView and EditText widgets. Provides easy means to validate with dependencies.

android-formidable-validation Form validation and feedback library for Android. Provides .setText for more than just TextView and EditText widgets. Pr

Linden 147 Nov 20, 2022
Simple way to create linked text, such as @username or #hashtag, in Android TextView and EditText

Simple Linkable Text Simple way to create link text, such as @username or #hashtag, in Android TextView and EditText Installation Gradle Add dependenc

Aditya Pradana Sugiarto 76 Nov 29, 2022
Lightweight android library for highlighting sections of a textview, with optional callbacks.

Linker Lightweight android library for highlighting Strings inside of a textview (ignoring case), with optional callbacks. Language: Java MinSDK: 17 J

Josh Gainey 35 Apr 30, 2022
Android slanted TextView.

SlantedTextView Android slanted TextView . 中文版 Preview Gradle compile 'com.haozhang.libary:android-slanted-textview:1.2' XML Layout <com.haozhang.lib.

Hand Zhang 2.2k Dec 26, 2022
() An Android TextView with a shimmering effect

Shimmer for Android This library is DEPRECATED, as I don't have time to mainatin it anymore. But feel free to go through the code and copy that into y

Romain Piel 2k Jan 7, 2023
a super textview for android

SuperTextView 重磅推出SuperTextView2.x版本,属性参数相比1.x有些变化,1.x的用户升级2.x的时候请注意 1、功能描述 SuperTextView是一个功能强大的View,可以满足日常大部分布局样式,开发者可已自行组合属性配置出属于自己风格的样式!可能描述起来没有概念

Allen 3.7k Dec 29, 2022
Build valid HTML for Android TextView

HTML Builder Build valid HTML for Android TextView. Description There is a lovely method on the android.text.Html class, fromHtml(), that converts HTM

Jared Rummler 527 Dec 25, 2022
ExpandableTextView - Read More TextView for Android

ExpandableTextView Read More TextView for Android Usage Gradle dependencies { implementation 'com.wayne.expandabletextview:expandable-textview:1.1

You kwangwoo 31 Oct 12, 2022