Marquee effect for Linear Layout
It can be accomplished using Recycleview and a autoscroll runnable .adding the code snippet here
1. MainActivity (MarqueeViewSample.java)
package com.test.mo.test;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.util.Log;import android.view.View;/*** Created by jovin.pj on 29-07-2015.*/public class MarqueeViewSample extends Activity {private final Runnable SCROLLING_RUNNABLE = new Runnable() { @Override public void run() { final int duration = 10; final int pixelsToMove = 10; marqueList.smoothScrollBy(pixelsToMove, 0); mHandler.postDelayed(this, duration); }};private final Handler mHandler = new Handler(Looper.getMainLooper());private RecyclerView marqueList;//private boolean loading = true;private boolean foundTotalPixel = true;private int pastVisiblesItems, visibleItemCount, totalItemCount;private int totalMovedPixel;private int totalPixel;/** * Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); marqueList = (RecyclerView) findViewById(R.id.marqueList); final LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); marqueList.setLayoutManager(layoutManager); marqueList.setAdapter(new ScrollAdapter()); marqueList.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { totalMovedPixel = totalMovedPixel + dx; visibleItemCount = layoutManager.getChildCount(); totalItemCount = layoutManager.getItemCount(); pastVisiblesItems = layoutManager.findFirstVisibleItemPosition(); if (foundTotalPixel) { if (totalItemCount > 2) { View headerView = layoutManager.getChildAt(0); View itemView = layoutManager.getChildAt(1); if (itemView != null && headerView != null) { /*total visible scrolling part is total pixel's of total item's count and header view*/ totalPixel = /*-c.getTop() +*/ ((totalItemCount - 2) * itemView.getWidth()) + (1 * headerView.getWidth()); Log.v("...", "Total pixel x!" + totalPixel); foundTotalPixel = false; } } } //if (loading) { //if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) { if (!foundTotalPixel && totalMovedPixel >= totalPixel) { // loading = false; Log.v("...", "Last Item Wow !"); Log.v("...", "totalMovedPixel !" + totalMovedPixel); // use this to turn auto-scrolling off: //mHandler.removeCallbacks(SCROLLING_RUNNABLE); marqueList.setAdapter(null); marqueList.setAdapter(new ScrollAdapter()); pastVisiblesItems = visibleItemCount = totalItemCount = 0; totalMovedPixel = 0; } } // } }); // use this to turn auto-scrolling on: mHandler.post(SCROLLING_RUNNABLE); }}
2. SampleAdapter(ScrollAdapter.java)
package com.test.mo.test;import android.support.v7.widget.RecyclerView;import android.util.DisplayMetrics;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.LinearLayout;/** * Created by jovin.pj on 29-07-2015. */public class ScrollAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {private static final int TYPE_HEADER = 0;private static final int TYPE_ITEM = 1;private static final int TYPE_FOOTER = 2;@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecyclerView.ViewHolder viewHolder = null; if (viewType == TYPE_ITEM) { //inflate your layout and pass it to view holder View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.scroll_child, parent, false); viewHolder = new ViewHolderItem(view); } else if (viewType == TYPE_HEADER || viewType == TYPE_FOOTER) { //inflate your layout and pass it to view holder //View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_footer, parent, false); View view = new View(parent.getContext()); DisplayMetrics metrics = parent.getContext().getResources().getDisplayMetrics(); int width = metrics.widthPixels; view.setLayoutParams(new LinearLayout.LayoutParams(width, LinearLayout.LayoutParams.WRAP_CONTENT)); viewHolder = new ViewHolderHeaderOrFooter(view); } return viewHolder;}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {}@Overridepublic int getItemCount() { // 1 for header and 1 for footer return 4 + 1 + 1;}@Overridepublic int getItemViewType(int position) { if (isPositionHeader(position)) return TYPE_HEADER; else if (isPositionFooter(position)) return TYPE_FOOTER; return TYPE_ITEM;}private boolean isPositionHeader(int position) { return position == 0;}private boolean isPositionFooter(int position) { return position == getItemCount() - 1;}// Provide a reference to the views for each data item// Complex data items may need more than one view per item, and// you provide access to all the views for a data item in a view holderpublic static class ViewHolderItem extends RecyclerView.ViewHolder { // each data item is just a string in this case public View mView; public ViewHolderItem(View v) { super(v); mView = v; }}// Provide a reference to the views for each data item// Complex data items may need more than one view per item, and// you provide access to all the views for a data item in a view holderpublic static class ViewHolderHeaderOrFooter extends RecyclerView.ViewHolder { // each data item is just a string in this case public View mView; public ViewHolderHeaderOrFooter(View v) { super(v); mView = v; } }}
3. Main Activity's Layout file(main.xml)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/marqueList" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:clipToPadding="false" /></LinearLayout>
4. Adapter's Layout File(scroll_child.xml)
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" ><TextView android:id="@+id/txtPercent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:paddingLeft="30dp" android:paddingRight="30dp" android:text="0.14%" /><View android:layout_width="match_parent" android:layout_height="1px" android:background="@android:color/darker_gray" /><TextView android:id="@+id/txtData" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:paddingLeft="30dp" android:paddingRight="30dp" android:text="data" /></LinearLayout>
increase or decrease pixelsToMove
, this variables value to change the speed
You can solve this using a library, MarqueeView which I have been using for some time and its works great. Here is the link for it.
Usage
In XML,
<asia.ivity.android.marqueeview.MarqueeView android:id="@+id/marqueeView150" android:layout_width="150dp" android:layout_height="wrap_content" marquee:speed="5" marquee:pause="1000" marquee:autoStart="true" > <TextView android:id="@+id/textView2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do." android:textSize="20sp" android:textStyle="bold" android:singleLine="true" android:ellipsize="end" tools:ignore="HardcodedText"/> </asia.ivity.android.marqueeview.MarqueeView>
In Java,
final MarqueeView mv = (MarqueeView) findViewById(R.id.marqueeView100); mv.setPauseBetweenAnimations(500); mv.setSpeed(10); getWindow().getDecorView().post(new Runnable() { @Override public void run() { mv.startMarquee(); } });
Please check this sample project for more help.
I would suggest you to use a single TextView
inside the MarqueeView
and combine both "percentage" and "data" into it.
You can absolutely customize the text size, font style, color, etc attributes of parts of a TextView using Spannable.
Here is a quick little example for you,
Spannable spn = (Spannable) tv3.getText(); spn.setSpan(new BackgroundColorSpan(Color.RED), 0, 7,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); spn.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC),0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
You can obviously customize it the way you want to give the percentage and the data a different look in a single TextView only.
You can also display images inside a TextView any where you want using ImageSpan
,
Here is a quick example for it,
ImageSpan is = new ImageSpan(context, resId);text.setSpan(is, index, index + strLength, 0);
Just ensure that you use correct index positions otherwise you will end up with an StringIndexOutOfBoundsException
.