Showing posts with label UI/UX. Show all posts
Showing posts with label UI/UX. Show all posts

Tuesday, 13 June 2023

Jetpack Compose Deep Dive: Unleashing the Power of Modern UI Development.

 In the ever-evolving world of Android app development, staying up-to-date with the latest technologies and frameworks is crucial. Jetpack Compose, a declarative UI toolkit for building native Android applications, has taken the developer community by storm. Its simplicity, flexibility, and powerful features have transformed the way we create user interfaces. In this blog post, we'll take a deep dive into Jetpack Compose, exploring its key concepts and showcasing the immense potential it holds for modern UI development.

The Declarative Paradigm:

Jetpack Compose introduces a paradigm shift in UI development by embracing a declarative approach. Unlike the traditional imperative model, where you define how to modify UI elements step by step, Compose focuses on describing what the UI should look like at any given moment. This fundamental change simplifies UI development, enhances code readability, and enables easier maintenance and testing.

Composable Functions:

At the heart of Jetpack Compose are composable functions. These functions are the building blocks of your UI, representing individual UI elements or entire screens. By annotating a function with the @Composable keyword, you indicate that it creates a UI component. Composable functions can accept parameters, define local variables, and return the UI hierarchy, leveraging the power of Kotlin language features.

State Management:

Managing state is a crucial aspect of any UI framework, and Jetpack Compose provides elegant solutions for this. The state and mutableStateOf APIs allow you to define mutable state variables within composable functions. When the state changes, only the affected parts of the UI are recomposed, resulting in efficient rendering and optimal performance. Additionally, Compose provides hooks like remember and LaunchedEffect for handling complex state interactions and side effects.

Material Design:

Jetpack Compose seamlessly integrates with Material Design guidelines, offering a vast array of pre-built components and styles. With a simple function call, you can create buttons, cards, dialogs, and more, adhering to Material Design principles. These components are highly customizable, allowing you to tailor them to your app's specific needs. Compose also provides powerful theming capabilities, making it effortless to create consistent and visually appealing UIs.

Animation and Gestures:

Creating engaging and interactive user experiences often requires animations and gestures. Jetpack Compose provides a rich set of APIs for handling these aspects with ease. The animate*AsState functions enable you to animate properties like alpha, scale, and position effortlessly. Compose also offers gesture detection APIs for capturing user touch events, such as pointerInput and Modifier.draggable. These features empower developers to build fluid and dynamic UIs.

Testing and Debugging:

Jetpack Compose prioritizes testability and debugging, making the development process more efficient. Composable functions are simple units of code that can be tested independently. You can write UI tests using Compose's built-in testing libraries, ensuring that your UI behaves as expected. Compose's debugging tools, such as the Layout Inspector and Live Preview, provide valuable insights into the UI hierarchy and assist in identifying and resolving layout issues.

Seamless Integration:

Jetpack Compose is designed to coexist with existing Android UI frameworks, allowing for gradual adoption in existing projects. You can embed Compose UI components within traditional View-based layouts using the AndroidView and ComposeView widgets, enabling a smooth transition to the Compose world. Additionally, Compose seamlessly integrates with other Jetpack libraries, such as ViewModel, LiveData, and Navigation, leveraging their benefits in your Compose-based apps.

Conclusion:

Jetpack Compose represents a paradigm shift in Android UI development, offering a modern and efficient way to build native user interfaces. Its declarative approach, composable functions, and powerful state management capabilities simplify and enhance the developer experience. By seamlessly integrating with Material Design, supporting animations and gestures, and providing robust testing and debugging tools, Jetpack Compose empowers developers to create visually stunning and interactive apps. As the Android ecosystem continues to evolve, embracing Jetpack Compose is a wise choice for staying at the forefront of modern UI development.

Thursday, 14 November 2019

Display Status Using Timeline View For Android.

A timeline is a display of a list of events in chronological order. Timelines can use any suitable scale representing time, suiting the subject and data; many use a linear scale, in which a unit of distance is equal to a set amount of time.

In this tutorial, we will see how to implement timeline view in Android. Below is the mock-up how we are expected to build,

Refer the below link for complete sample code:-

Download Sample Code

Have a look on few code snippets,

//ctimeline_row.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <RelativeLayout
        android:layout_width="72dp"
        android:layout_height="match_parent">


        <View
            android:id="@+id/crowUpperLine"
            android:layout_width="25dp"
            android:layout_height="match_parent"
            android:layout_above="@+id/crowImg"
            android:layout_centerInParent="true"
            android:layout_centerVertical="true"
            android:background="@android:color/darker_gray" />

        <View
            android:id="@+id/crowLowerLine"
            android:layout_width="25dp"
            android:layout_height="match_parent"
            android:layout_below="@+id/crowImg"
            android:layout_centerInParent="true"
            android:layout_centerVertical="true"
            android:background="@android:color/darker_gray" />


        <View
            android:id="@+id/crowBackground"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_centerInParent="true"
            android:layout_centerVertical="true" />

        <ImageView
            android:id="@+id/crowImg"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_centerInParent="true"
            android:layout_centerVertical="true"
            android:layout_marginTop="-12.5dp"
            android:layout_marginBottom="-12.5dp" />


    </RelativeLayout>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="16dp"
        android:paddingBottom="10dp"
        android:paddingRight="16dp">

        <TextView
            android:id="@+id/crowDate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Date"
            android:paddingTop="10dp"
            android:textAppearance="?android:attr/textAppearanceSmall" />

        <TextView
            android:id="@+id/crowTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/crowDate"
            android:layout_centerVertical="true"
            android:text="Title"
            android:textAppearance="?android:attr/textAppearanceListItem"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/crowDesc"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/crowTitle"
            android:layout_centerVertical="true"
            android:text="Description"
            android:textAppearance="?android:attr/textAppearanceSearchResultSubtitle" />

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#d7f2eb"
            />
    </RelativeLayout>

</LinearLayout>

//activity_main.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/timeline_listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@null"
        android:dividerHeight="0dp" />
</LinearLayout>

//TimelineRow.java
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package com.elitetechnologies.timelineview.TimelineView;


import android.graphics.Bitmap;

import java.util.Date;


public class TimelineRow {

    private int id;
    private Date date = null;
    private String title = null;
    private String description = null;
    private Bitmap image = null;
    private int bellowLineColor = 0;
    private int bellowLineSize = 6;
    private int imageSize = 50;
    private int backgroundColor = 0;
    private int backgroundSize = 50;
    private int dateColor = 0;
    private int titleColor = 0;
    private int descriptionColor = 0;

    public TimelineRow(int id) {
        this.id = id;
    }

    public TimelineRow(int id, Date date) {
        this.id = id;
        this.date = date;
    }


    public TimelineRow(int id, Date date, String title, String description) {
        this.id = id;
        this.date = date;
        this.title = title;
        this.description = description;
    }

    public TimelineRow(int id, Date date, String title, String description, Bitmap image, int bellowLineColor, int bellowLineSize, int imageSize) {
        this.id = id;
        this.date = date;
        this.title = title;
        this.description = description;
        this.image = image;
        this.bellowLineColor = bellowLineColor;
        this.bellowLineSize = bellowLineSize;
        this.imageSize = imageSize;
    }

    public TimelineRow(int id, Date date, String title, String description, Bitmap image, int bellowLineColor, int bellowLineSize, int imageSize, int backgroundColor, int backgroundSize) {
        this.id = id;
        this.date = date;
        this.title = title;
        this.description = description;
        this.image = image;
        this.bellowLineColor = bellowLineColor;
        this.bellowLineSize = bellowLineSize;
        this.imageSize = imageSize;
        this.backgroundColor = backgroundColor;
        this.backgroundSize = backgroundSize;
    }

    public TimelineRow(int id, Date date, String title, String description, Bitmap image, int bellowLineColor, int bellowLineSize, int imageSize, int backgroundColor, int backgroundSize, int dateColor, int titleColor, int descriptionColor) {
        this.id = id;
        this.date = date;
        this.title = title;
        this.description = description;
        this.image = image;
        this.bellowLineColor = bellowLineColor;
        this.bellowLineSize = bellowLineSize;
        this.imageSize = imageSize;
        this.backgroundColor = backgroundColor;
        this.backgroundSize = backgroundSize;
        this.dateColor = dateColor;
        this.titleColor = titleColor;
        this.descriptionColor = descriptionColor;
    }

    public int getBackgroundSize() {
        return backgroundSize;
    }

    public void setBackgroundSize(int backgroundSize) {
        this.backgroundSize = backgroundSize;
    }

    public int getBackgroundColor() {
        return backgroundColor;
    }

    public void setBackgroundColor(int backgroundColor) {
        this.backgroundColor = backgroundColor;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public int getImageSize() {
        return imageSize;
    }

    public void setImageSize(int imageSize) {
        this.imageSize = imageSize;
    }

    public int getBellowLineSize() {
        return bellowLineSize;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setBellowLineSize(int bellowLineSize) {
        this.bellowLineSize = bellowLineSize;
    }

    public int getBellowLineColor() {
        return bellowLineColor;
    }

    public void setBellowLineColor(int bellowLineColor) {
        this.bellowLineColor = bellowLineColor;
    }

    public Bitmap getImage() {
        return image;
    }

    public void setImage(Bitmap image) {
        this.image = image;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getDateColor() {
        return dateColor;
    }

    public void setDateColor(int dateColor) {
        this.dateColor = dateColor;
    }

    public int getTitleColor() {
        return titleColor;
    }

    public void setTitleColor(int titleColor) {
        this.titleColor = titleColor;
    }

    public int getDescriptionColor() {
        return descriptionColor;
    }

    public void setDescriptionColor(int descriptionColor) {
        this.descriptionColor = descriptionColor;
    }

}

//TimelineViewAdapter.java
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
package com.elitetechnologies.timelineview.TimelineView;



import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.GradientDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.elitetechnologies.timelineview.R;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;


public class TimelineViewAdapter extends ArrayAdapter<TimelineRow> {
    private Context context;
    private Resources res;
    private List<TimelineRow> RowDataList;
    private String AND;

    public TimelineViewAdapter(Context context, int resource, ArrayList<TimelineRow> objects, boolean orderTheList) {
        super(context, resource, objects);
        this.context = context;
        res = context.getResources();
        AND ="and";
        if (orderTheList)
            this.RowDataList = rearrangeByDate(objects);
        else
            this.RowDataList = objects;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        TimelineRow row = RowDataList.get(position);

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.ctimeline_row, null);

        TextView rowDate = (TextView) view.findViewById(R.id.crowDate);
        TextView rowTitle = (TextView) view.findViewById(R.id.crowTitle);
        TextView rowDescription = (TextView) view.findViewById(R.id.crowDesc);
        ImageView rowImage = (ImageView) view.findViewById(R.id.crowImg);
        View rowUpperLine = (View) view.findViewById(R.id.crowUpperLine);
        View rowLowerLine = (View) view.findViewById(R.id.crowLowerLine);


        final float scale = getContext().getResources().getDisplayMetrics().density;


        if (position == 0 && position == RowDataList.size() - 1) {
            rowUpperLine.setVisibility(View.INVISIBLE);
            rowLowerLine.setVisibility(View.INVISIBLE);
        } else if (position == 0) {
            int pixels = (int) (row.getBellowLineSize() * scale + 0.5f);

            rowUpperLine.setVisibility(View.INVISIBLE);
            rowLowerLine.setBackgroundColor(row.getBellowLineColor());
            rowLowerLine.getLayoutParams().width = pixels;
        } else if (position == RowDataList.size() - 1) {
            int pixels = (int) (RowDataList.get(position - 1).getBellowLineSize() * scale + 0.5f);

            rowLowerLine.setVisibility(View.INVISIBLE);
            rowUpperLine.setBackgroundColor(RowDataList.get(position - 1).getBellowLineColor());
            rowUpperLine.getLayoutParams().width = pixels;
        } else {
            int pixels = (int) (row.getBellowLineSize() * scale + 0.5f);
            int pixels2 = (int) (RowDataList.get(position - 1).getBellowLineSize() * scale + 0.5f);

            rowLowerLine.setBackgroundColor(row.getBellowLineColor());
            rowUpperLine.setBackgroundColor(RowDataList.get(position - 1).getBellowLineColor());
            rowLowerLine.getLayoutParams().width = pixels;
            rowUpperLine.getLayoutParams().width = pixels2;
        }

        if (position == 0 ||  position == RowDataList.size() - 1) {
            Bitmap tintBitmap = tintImage(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_srcdstpoint), Color.parseColor("#c44227"));
            row.setImage(tintBitmap);
        }else{
            Bitmap tintBitmap = tintImage(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_nodes), Color.parseColor("#f29d9d"));
            row.setImage(tintBitmap);
        }

        if(position<=2) {
            row.setBellowLineSize(12);
            row.setBellowLineColor(Color.parseColor("#9df2b1"));
        }


        rowDate.setText(getPastTime(row.getDate()));
        if (row.getDateColor() != 0)
            rowDate.setTextColor(row.getDateColor());
        if (row.getTitle() == null)
            rowTitle.setVisibility(View.GONE);
        else {
            rowTitle.setText(row.getTitle());
            if (row.getTitleColor() != 0)
                rowTitle.setTextColor(row.getTitleColor());
        }
        if (row.getDescription() == null)
            rowDescription.setVisibility(View.GONE);
        else {
            rowDescription.setText(row.getDescription());
            if (row.getDescriptionColor() != 0)
                rowDescription.setTextColor(row.getDescriptionColor());
        }

        if (row.getImage() != null) {
            rowImage.setImageBitmap(row.getImage());
        }

        int pixels = (int) (row.getImageSize() * scale + 0.5f);
        rowImage.getLayoutParams().width = pixels;
        rowImage.getLayoutParams().height = pixels;

        View backgroundView = view.findViewById(R.id.crowBackground);
        if (row.getBackgroundColor() == 0)
            backgroundView.setBackground(null);
        else {
            if (row.getBackgroundSize() == -1) {
                backgroundView.getLayoutParams().width = pixels;
                backgroundView.getLayoutParams().height = pixels;
            } else {
                int BackgroundPixels = (int) (row.getBackgroundSize() * scale + 0.5f);
                backgroundView.getLayoutParams().width = BackgroundPixels;
                backgroundView.getLayoutParams().height = BackgroundPixels;
            }
            GradientDrawable background = (GradientDrawable) backgroundView.getBackground();
            if (background != null) {
                background.setColor(row.getBackgroundColor());
            }
        }


        ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) rowImage.getLayoutParams();
        marginParams.setMargins(0, (int) (pixels / 2) * -1, 0, (pixels / 2) * -1);

        return view;
    }

    private String getPastTime(Date date) {

        if (date == null) return "";
        StringBuilder dateText = new StringBuilder();
        Date today = new Date();
        long diff = (today.getTime() - date.getTime()) / 1000;

        long years = diff / (60 * 60 * 24 * 30 * 12);
        long months = (diff / (60 * 60 * 24 * 30)) % 12;
        long days = (diff / (60 * 60 * 24)) % 30;
        long hours = (diff / (60 * 60)) % 24;
        long minutes = (diff / 60) % 60;
        long seconds = diff % 60;

        if (years > 0) {
            appendPastTime(dateText, years, R.plurals.years, months, R.plurals.months);
        } else if (months > 0) {
            appendPastTime(dateText, months, R.plurals.months, days, R.plurals.days);
        } else if (days > 0) {
            appendPastTime(dateText, days, R.plurals.days, hours, R.plurals.hours);
        } else if (hours > 0) {
            appendPastTime(dateText, hours, R.plurals.hours, minutes, R.plurals.minutes);
        } else if (minutes > 0) {
            appendPastTime(dateText, minutes, R.plurals.minutes, seconds, R.plurals.seconds);
        } else if (seconds >= 0) {
            dateText.append(res.getQuantityString(R.plurals.seconds, (int) seconds, (int) seconds));
        }

        return dateText.toString();
    }

    private void appendPastTime(StringBuilder s,
                                long timespan, int nameId,
                                long timespanNext, int nameNextId) {

        s.append(res.getQuantityString(nameId, (int) timespan, timespan));
        if (timespanNext > 0) {
            s.append(' ').append(AND).append(' ');
            s.append(res.getQuantityString(nameNextId, (int) timespanNext, timespanNext));
        }
    }

    private ArrayList<TimelineRow> rearrangeByDate(ArrayList<TimelineRow> objects) {
        if (objects.get(0) == null) return objects;
        int size = objects.size();
        for (int i = 0; i < size - 1; i++) {
            for (int j = i + 1; j < size; j++) {
                if(objects.get(i).getDate()!= null && objects.get(j).getDate() != null)
                    if (objects.get(i).getDate().compareTo(objects.get(j).getDate()) <= 0)
                        Collections.swap(objects, i, j);
            }

        }
        return objects;
    }

    private static Bitmap tintImage(Bitmap bitmap, int color) {
        Paint paint = new Paint();
        paint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
        Bitmap bitmapResult = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmapResult);
        canvas.drawBitmap(bitmap, 0, 0, paint);
        return bitmapResult;
    }
}

//MainActivity.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package com.elitetechnologies.timelineview;

import android.annotation.SuppressLint;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;

import com.elitetechnologies.timelineview.TimelineView.TimelineRow;
import com.elitetechnologies.timelineview.TimelineView.TimelineViewAdapter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

public class MainActivity extends AppCompatActivity {

    //Create Timeline Rows List
    private ArrayList<TimelineRow> timelineRowsList = new ArrayList<>();
    ArrayAdapter<TimelineRow> myAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);// Create Timeline rows List
        // Add Random Rows to the List
        for (int i = 0; i < 15; i++) {
            //add the new row to the list
            timelineRowsList.add(createRandomTimelineRow(i));
        }
        //Create the Timeline Adapter
        myAdapter = new TimelineViewAdapter(this, 0, timelineRowsList,
                //if true, list will be sorted by date
                true);
        //Get the ListView and Bind it with the Timeline Adapter
        ListView timeline_listView = (ListView) findViewById(R.id.timeline_listView);
        timeline_listView.setAdapter(myAdapter);
        myAdapter.notifyDataSetChanged();

        //if you wish to handle the clicks on the rows
        AdapterView.OnItemClickListener adapterListener = new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                TimelineRow row = timelineRowsList.get(position);
                Toast.makeText(MainActivity.this, row.getTitle()+"at position"+position, Toast.LENGTH_SHORT).show();
            }
        };
        timeline_listView.setOnItemClickListener(adapterListener);
    }

    //Method to create new Timeline Row
    private TimelineRow createRandomTimelineRow(int id) {
        // Create new timeline row (pass your Id)
        TimelineRow myRow = new TimelineRow(id);

        //to set the row Date (optional)
        myRow.setDate(getRandomDate());
        //to set the row Title (optional)
        myRow.setTitle("Title " + id);
        myRow.setTitleColor(Color.parseColor("#3295a8"));
        //to set the row Description (optional)
        myRow.setDescription("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
        myRow.setDescriptionColor(Color.parseColor("#32a8a4"));
        //to set row Below Line Color (optional)
        myRow.setBellowLineColor(Color.LTGRAY);
        return myRow;
    }

    @SuppressLint("NewApi")
    public Date getRandomDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        Date startDate = null;
        Date endDate = new Date();
        try {
            startDate = sdf.parse("14/02/2020");
            long random = ThreadLocalRandom.current().nextLong(startDate.getTime(), endDate.getTime());
            endDate = new Date(random);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return endDate;
    }

}