118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TickerView
2 |
3 | [](https://jitpack.io/#Vinayrraj/TickerView)
4 |
5 | What is TickerView?
6 | ===============
7 | TickerView is a simple Android UI component for displaying horizontally scrolling Views placed inside this TickerView. For reference you may see how [MoneyControl Tablet](https://play.google.com/store/apps/details?id=com.moneycontrol) (shows stock price in scrolling view at the bottom of screen) and Phone app shows the Stock prices. The TickerView scrolls child views with smooth animation.
8 |
9 | Live Demo
10 | ---------------
11 | Google Play Store: [https://play.google.com/store/apps/details?id=com.vinay.ticker](https://play.google.com/store/apps/details?id=com.vinay.ticker)
12 |
13 |
14 | GIF
15 | ---------------
16 |
17 | 
18 |
19 |
20 | Getting started
21 | ---------------
22 |
23 | Add it in your root `build.gradle` at the end of repositories:
24 |
25 | ```groovy
26 |
27 | allprojects {
28 | repositories {
29 | maven { url 'https://jitpack.io' }
30 | }
31 | }
32 |
33 | ```
34 |
35 | Add the ticker dependency to your `build.gradle`.
36 |
37 | ```groovy
38 |
39 | dependencies {
40 | implementation 'com.github.Vinayrraj:TickerView:v0.1-alpha'
41 | }
42 |
43 | ```
44 |
45 | Usage
46 | -----
47 |
48 | Define the `TickerView` in XML:
49 |
50 | ```xml
51 |
52 |
56 | ```
57 |
58 | Then in java code, add the views to the TickerView:
59 |
60 | ```java
61 |
62 | // Get the TickerView object
63 | final TickerView tickerView = findViewById(R.id.tickerView);
64 |
65 | // Add multiple views to be shown in the ticker
66 | for (int index = 0; index < 50; index++) {
67 | // childViews
68 | TextView tv = new TextView(this);
69 | tv.setLayoutParams(new LinearLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT));
70 | tv.setText(String.valueOf(index + 1));
71 | tv.setBackgroundColor(ContextCompat.getColor(this, android.R.color.white));
72 | tv.setTextColor(ContextCompat.getColor(this, android.R.color.black));
73 | tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 22);
74 | tv.setPadding(10, 5, 10, 5);
75 |
76 | tickerView.addChildView(tv);
77 | }
78 |
79 | // Call the showTickers() to show them on the screen
80 | tickerView.showTickers();
81 |
82 | ```
83 |
84 |
85 |
86 | Documentation
87 | -----
88 |
89 | Usage Documentation: [https://vinayrraj.github.io/TickerView/](https://vinayrraj.github.io/TickerView/) ,
90 |
91 | Javadoc for the library can be viewed at: [https://vinayrraj.github.io/TickerView/java-docs/](https://vinayrraj.github.io/TickerView/java-docs/)
92 |
93 |
94 | How it Works?
95 | -----
96 |
97 | TickerView extends HorizontalScrollView, which contains a LinearLayout. With the method setChildViews(List childViews)" or "addChildView(View childView)", we add child views to be plotted in the scrolling TickerView.
98 | Once Views are added to the TickerView, we set the left Margin for the First View and the right Margin for the Last View equalent to the width of the screen, so that the view statys on the screen for a certain time frame.
99 | Additionally, we have added a Marker View as the last view on the list, so that as soon as that view's Rect bounds (with width and height equal to the width and height of parent) intersects with the Rect object of the last Marker View. As soon as this contition is met, we reset the position of scroll and the auto scrolling starts back from the first View.
100 |
101 | Now to Automate the Scrolling process, we have created a Timer (which runs TimerTask) which schedule the movement/displacement given by the getDisplacement() method and the process continues till the view is detatched from windlow.
102 |
103 |
104 | Credits
105 | -----
106 |
107 | vinayrraj@gmail.com
108 |
109 | [https://twitter.com/vinayrraj](https://twitter.com/vinayrraj)
110 |
--------------------------------------------------------------------------------
/docs/com/vinay/ticker/lib/package-use.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Package com.vinay.ticker.lib
7 |
8 |
9 |
10 |
11 |
12 |
22 |
25 |
26 |
The TickerView class is a complex view which contains a LinearLayout which may contain any number of Views passed to it,
87 | to be shown in horizontal layout.
The TickerView class is a complex view which contains a LinearLayout which may contain any number of Views passed to it,
87 | to be shown in horizontal layout.
The TickerView class is a complex view which contains a LinearLayout which may contain any number of Views passed to it,
78 | to be shown in horizontal layout.
This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
73 |
74 |
75 |
76 |
77 |
Package
78 |
Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain six categories:
79 |
80 |
Interfaces (italic)
81 |
Classes
82 |
Enums
83 |
Exceptions
84 |
Errors
85 |
Annotation Types
86 |
87 |
88 |
89 |
Class/Interface
90 |
Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:
91 |
92 |
Class inheritance diagram
93 |
Direct Subclasses
94 |
All Known Subinterfaces
95 |
All Known Implementing Classes
96 |
Class/interface declaration
97 |
Class/interface description
98 |
99 |
100 |
Nested Class Summary
101 |
Field Summary
102 |
Constructor Summary
103 |
Method Summary
104 |
105 |
106 |
Field Detail
107 |
Constructor Detail
108 |
Method Detail
109 |
110 |
Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.
111 |
112 |
113 |
Annotation Type
114 |
Each annotation type has its own separate page with the following sections:
115 |
116 |
Annotation Type declaration
117 |
Annotation Type description
118 |
Required Element Summary
119 |
Optional Element Summary
120 |
Element Detail
121 |
122 |
123 |
124 |
Enum
125 |
Each enum has its own separate page with the following sections:
126 |
127 |
Enum declaration
128 |
Enum description
129 |
Enum Constant Summary
130 |
Enum Constant Detail
131 |
132 |
133 |
134 |
Use
135 |
Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its Use page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.
136 |
137 |
138 |
Tree (Class Hierarchy)
139 |
There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with java.lang.Object. The interfaces do not inherit from java.lang.Object.
140 |
141 |
When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
142 |
When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
143 |
144 |
145 |
146 |
Index
147 |
The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.
148 |
149 |
150 |
Prev/Next
151 |
These links take you to the next or previous class, interface, package, or related page.
152 |
153 |
154 |
Frames/No Frames
155 |
These links show and hide the HTML frames. All pages are available with or without frames.
156 |
157 |
158 |
All Classes
159 |
The All Classes link shows all classes and interfaces except non-static nested types.
160 |
161 |
162 |
Serialized Form
163 |
Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
73 |
74 |
75 |
76 |
77 |
Package
78 |
Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain six categories:
79 |
80 |
Interfaces (italic)
81 |
Classes
82 |
Enums
83 |
Exceptions
84 |
Errors
85 |
Annotation Types
86 |
87 |
88 |
89 |
Class/Interface
90 |
Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:
91 |
92 |
Class inheritance diagram
93 |
Direct Subclasses
94 |
All Known Subinterfaces
95 |
All Known Implementing Classes
96 |
Class/interface declaration
97 |
Class/interface description
98 |
99 |
100 |
Nested Class Summary
101 |
Field Summary
102 |
Constructor Summary
103 |
Method Summary
104 |
105 |
106 |
Field Detail
107 |
Constructor Detail
108 |
Method Detail
109 |
110 |
Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.
111 |
112 |
113 |
Annotation Type
114 |
Each annotation type has its own separate page with the following sections:
115 |
116 |
Annotation Type declaration
117 |
Annotation Type description
118 |
Required Element Summary
119 |
Optional Element Summary
120 |
Element Detail
121 |
122 |
123 |
124 |
Enum
125 |
Each enum has its own separate page with the following sections:
126 |
127 |
Enum declaration
128 |
Enum description
129 |
Enum Constant Summary
130 |
Enum Constant Detail
131 |
132 |
133 |
134 |
Use
135 |
Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its Use page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.
136 |
137 |
138 |
Tree (Class Hierarchy)
139 |
There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with java.lang.Object. The interfaces do not inherit from java.lang.Object.
140 |
141 |
When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
142 |
When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
143 |
144 |
145 |
146 |
Index
147 |
The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.
148 |
149 |
150 |
Prev/Next
151 |
These links take you to the next or previous class, interface, package, or related page.
152 |
153 |
154 |
Frames/No Frames
155 |
These links show and hide the HTML frames. All pages are available with or without frames.
156 |
157 |
158 |
All Classes
159 |
The All Classes link shows all classes and interfaces except non-static nested types.
160 |
161 |
162 |
Serialized Form
163 |
Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
The TickerView class is a complex view which contains a LinearLayout which may contain any number of Views passed to it,
162 | to be shown in horizontal layout.
The TickerView class is a complex view which contains a LinearLayout which may contain any number of Views passed to it,
162 | to be shown in horizontal layout.
218 |
219 |
220 |
221 |
--------------------------------------------------------------------------------
/tickerview/src/main/java/com/vinay/ticker/lib/TickerView.java:
--------------------------------------------------------------------------------
1 | package com.vinay.ticker.lib;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.Rect;
6 | import android.os.Build;
7 | import android.support.annotation.RequiresApi;
8 | import android.support.v4.content.ContextCompat;
9 | import android.util.AttributeSet;
10 | import android.view.Gravity;
11 | import android.view.View;
12 | import android.view.ViewTreeObserver;
13 | import android.widget.HorizontalScrollView;
14 | import android.widget.LinearLayout;
15 | import android.widget.TextView;
16 |
17 | import java.util.ArrayList;
18 | import java.util.List;
19 | import java.util.Timer;
20 | import java.util.TimerTask;
21 |
22 | /**
23 | * The {@code TickerView} class is a complex view which contains a {@code LinearLayout} which may contain any number of {@code View}s passed to it,
24 | * to be shown in horizontal layout.
25 | *
26 | * These child {@code View}s scroll horizontally in the main view holder, from left to right.
27 | * The speed of the view scrolling can be controlled by setting up the {@code displacement} value of views. Also can be controlled by user by finger gesture / sling motion.
28 | *
29 | * @see HorizontalScrollView
30 | */
31 | public class TickerView extends HorizontalScrollView {
32 |
33 | private int displacement = 1;
34 | private int scrollPos = 0;
35 | private Timer scrollTimer = null;
36 | private TimerTask scrollerSchedule;
37 | private TextView lastTicker;
38 | private List childViews = null;
39 | private LinearLayout linearLayout;
40 |
41 |
42 | public TickerView(Context context) {
43 | super(context);
44 | init(context, null);
45 | }
46 |
47 | public TickerView(Context context, AttributeSet attrs) {
48 | super(context, attrs);
49 | init(context, null);
50 | }
51 |
52 | public TickerView(Context context, AttributeSet attrs, int defStyleAttr) {
53 | super(context, attrs, defStyleAttr);
54 | init(context, null);
55 | }
56 |
57 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
58 | public TickerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
59 | super(context, attrs, defStyleAttr, defStyleRes);
60 | init(context, null);
61 | }
62 |
63 | /**
64 | * If the views are added to the container view, the tickers start showing up. This method calls {@code showTickers()}
65 | */
66 | @Override
67 | protected void onAttachedToWindow() {
68 | super.onAttachedToWindow();
69 | showTickers();
70 | }
71 |
72 | /**
73 | * If the views are added to the container view, this method, removed all scheduled {@code TimerTask}s by calling {@code destroyAllScheduledTasks()}
74 | */
75 | @Override
76 | protected void onDetachedFromWindow() {
77 | destroyAllScheduledTasks();
78 | super.onDetachedFromWindow();
79 | }
80 |
81 |
82 | /**
83 | * This method initialized the View container by adding a horizontal {@code LinearLayout} onside the root view.
84 | *
85 | * @param context
86 | * @param attributeSet
87 | */
88 | private void init(Context context, AttributeSet attributeSet) {
89 | LinearLayout linearLayout = new LinearLayout(context);
90 | linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
91 | linearLayout.setOrientation(LinearLayout.HORIZONTAL);
92 | linearLayout.setGravity(Gravity.CENTER_VERTICAL);
93 | setHorizontalFadingEdgeEnabled(false);
94 | setVerticalFadingEdgeEnabled(false);
95 | setForegroundGravity(Gravity.CENTER_VERTICAL);
96 | setHorizontalScrollBarEnabled(false);
97 | setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.background_dark));
98 | setDisplacement(displacement);
99 | }
100 |
101 |
102 | /**
103 | * Use this method to get the speed of sticker movement, displacement speed of ticker views.
104 | *
105 | * @return the speed of view's rate of displacement
106 | */
107 | public int getDisplacement() {
108 | return displacement;
109 | }
110 |
111 | /**
112 | * This method is used to set the variable speed of displacement of auto-scrolling of views.
113 | *
114 | * @param displacement value by which the auto-scrolling displacement occurs
115 | */
116 | public void setDisplacement(int displacement) {
117 | this.displacement = (int) Math.ceil((displacement) * 5.0 / 100.0);
118 | }
119 |
120 |
121 | /**
122 | * Saves the views collection to be plotted in the ticker view.
123 | *
124 | * @param childViews {@code List} which contains all the views to be added into the {@code TickerView}
125 | */
126 | public void setChildViews(List childViews) {
127 | this.childViews = childViews;
128 | }
129 |
130 | /**
131 | * User may individually add views to be shown into the {@code TickerView}
132 | *
133 | * @param childView {@code View} to be added as child to the {@code TickerView}.
134 | */
135 | public void addChildView(View childView) {
136 | if (childViews == null) {
137 | childViews = new ArrayList<>();
138 | }
139 | this.childViews.add(childView);
140 | }
141 |
142 | /**
143 | * This method to show the child views added by {@code addChildView()} or {@code setChildViews(List childViews)} methods.
144 | * Method Details:
145 | * 1. This method first removes any older child views already shown inside the {@code TickerView}
146 | * 2. Adds all the passed views to the {@code TickerView} by the methods {@code addChildView()} or {@code setChildViews(List childViews)}.
147 | * 3. Corresponding Layout params are set for all the views, the first and last components are set with width equal to screen width, so that the view scrooling starts at left side of screen and the last component completes the cycle at rigjt end of screen, then only the new cycle begins.
148 | * 4. An empty marker view is placed at the end of the view list so that, as soon as the ScrollBounds of that view comes into the {@code Rect}, we start a new cycle and starts scrolling form the first record.
149 | * 5. We add {@code ViewTreeObserver.OnGlobalLayoutListener} to intercept changes in global layout and start auto scrolling by calling {@code startAutoScrolling()} method.
150 | */
151 | public void showTickers() {
152 | if (linearLayout != null) {
153 | linearLayout.removeAllViews();
154 | }
155 | removeAllViewsInLayout();
156 | linearLayout = new LinearLayout(getContext());
157 |
158 | final LinearLayout.LayoutParams lp_par = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);
159 | final LinearLayout.LayoutParams lp_par_0 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);
160 | final LinearLayout.LayoutParams lp_par_last = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);
161 | linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
162 |
163 | lp_par.setMargins(10, 3, 5, 3);
164 | lp_par_0.setMargins(((Activity) getContext()).getWindowManager().getDefaultDisplay().getWidth(), 3, 5, 3);
165 | lp_par_last.setMargins(5, 3, ((Activity) getContext()).getWindowManager().getDefaultDisplay().getWidth(), 3);
166 | if (childViews != null && !childViews.isEmpty()) {
167 | for (int index = 0; index < childViews.size(); index++) {
168 | if (index == 0) {
169 | linearLayout.addView(childViews.get(index), lp_par_0);
170 | } else if (index == childViews.size() - 1) {
171 | linearLayout.addView(childViews.get(index), lp_par_last);
172 |
173 | } else {
174 | linearLayout.addView(childViews.get(index), lp_par);
175 | }
176 | }
177 | lastTicker = new TextView(getContext());
178 | lastTicker.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
179 | lastTicker.setVisibility(INVISIBLE);
180 | linearLayout.addView(lastTicker, lp_par);
181 |
182 | ViewTreeObserver vto = getViewTreeObserver();
183 | vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
184 |
185 | public void onGlobalLayout() {
186 | getViewTreeObserver().removeOnGlobalLayoutListener(this);
187 | startAutoScrolling();
188 | }
189 | });
190 | addView(linearLayout);
191 | }
192 | }
193 |
194 | /**
195 | * This method initiates scheduler for auto scrolling, If there is already a scheduled {@code Timer}, this method will first cancel the timer and reschedule it. On Regular intervals,
196 | * this {@code Timer} runs a {@code moveScrollView()} method on UI thread to scroll the views by the provided {@code getDisplacement()} value.
197 | *
198 | * This only schedules a timer if the {@code getDisplacement()} value is greater than 0.
199 | */
200 | public void startAutoScrolling() {
201 | if (scrollTimer != null) {
202 | scrollTimer.cancel();
203 | }
204 | scrollTimer = new Timer();
205 | final Runnable timer_tick = new Runnable() {
206 | public void run() {
207 | moveScrollView();
208 | }
209 | };
210 |
211 | if (scrollerSchedule != null) {
212 | scrollerSchedule.cancel();
213 | scrollerSchedule = null;
214 | }
215 | scrollerSchedule = new TimerTask() {
216 | @Override
217 | public void run() {
218 | try {
219 | ((Activity) getContext()).runOnUiThread(timer_tick);
220 | } catch (Exception e) {
221 | e.printStackTrace();
222 | if (this != null) {
223 | this.cancel();
224 | }
225 | }
226 | }
227 | };
228 |
229 | if (displacement > 0) {
230 | scrollTimer.schedule(scrollerSchedule, 30, 30);
231 | }
232 |
233 | }
234 |
235 | /**
236 | * All the smooth scrolling/moving logic is implemented in this method. This method moves the Ticker views by the provided displacement value.
237 | *
238 | * The logic in place is to get a {@code Rect} and set it for custom last marker ticker(invisible). An additional {@code Rect} object is created whose horizontal bounds are
239 | * for how much the view has scrolled added to its width. Once we have both of these objects, we simply check if the {@code Rect}object for last custom ticker view (invisible)
240 | * intersects with the current screen {@code Rect} object, as soon as the condition is met, which means the last hidden view has scrolled on to the screen, which in tern means all the ticker items have been shown, we set the scroll position to 0 again,, and the scrolling starts from the first Tivker view again.
241 | */
242 | public void moveScrollView() {
243 |
244 | try {
245 | scrollPos = (int) (getScrollX() + displacement);
246 |
247 | final Rect bounds = new Rect();
248 | lastTicker.getHitRect(bounds);
249 |
250 | final Rect scrollBounds = new Rect(getScrollX(), getScrollY(), getScrollX()
251 | + getWidth(), getScrollY() + getHeight());
252 |
253 | if (Rect.intersects(scrollBounds, bounds)) {
254 | // is visible
255 | scrollPos = 0;
256 | scrollTo(scrollPos, 0);
257 | } else {
258 | smoothScrollTo(scrollPos, 0);
259 | }
260 | } catch (Exception e) {
261 | e.printStackTrace();
262 | }
263 | }
264 |
265 | /**
266 | * This method cancels {@code Timer} and {@code TimerTask} and there callback.
267 | */
268 | public void destroyAllScheduledTasks() {
269 | clearTimerTaks(scrollerSchedule);
270 | clearTimers(scrollTimer);
271 |
272 | scrollerSchedule = null;
273 | scrollTimer = null;
274 |
275 | }
276 |
277 | /**
278 | * This method cancels {@code Timer}.
279 | */
280 | private void clearTimers(Timer timer) {
281 | if (timer != null) {
282 | timer.cancel();
283 | }
284 | }
285 |
286 | /**
287 | * This method cancels {@code TimerTask}.
288 | */
289 | private void clearTimerTaks(TimerTask timerTask) {
290 | if (timerTask != null) {
291 | timerTask.cancel();
292 | }
293 | }
294 | }
295 |
--------------------------------------------------------------------------------