先上效果图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFuZ25lbmd3dQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" height="369" width="199" alt="">

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFuZ25lbmd3dQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" height="369" width="202" alt="">

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFuZ25lbmd3dQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" height="441" width="265" alt="">

代码:

package com.example.scrolltextview;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Scroller;
import android.widget.SpinnerAdapter;
import android.widget.TextView; public class ScrollTextView extends ViewGroup { private static final int SCROLL = 0;
private static final int JUSTIFY = 1;
private static final int ANIMATION_DURATION = 3000; private int mOrientation;
private int mSize;
private int mIndex;
private int mPosition;
private Scroller mScroller;
private Map<View, Integer> mViews;
private SpinnerAdapter mAdapter;
private int mPackedViews;
private int mAnimationDuration; private float measuredWidth = 0;
private float textSize = 0;
private float measuredHeight = 0;
private String text= null;
private String[] data;
private boolean flag = true;
public ScrollTextView(Context context, AttributeSet attrs) {
super(context, attrs); int[] linerarLayoutAttrs = {
android.R.attr.orientation,
};
TypedArray a = context.obtainStyledAttributes(attrs, linerarLayoutAttrs);
mOrientation = a.getInteger(0, LinearLayout.HORIZONTAL);
a.recycle(); mAnimationDuration = ANIMATION_DURATION; mScroller = new Scroller(context);
mIndex = -1;
mPosition = -1;
mPackedViews = -1;
mViews = new HashMap<View, Integer>(); setFocusable(true);
setFocusableInTouchMode(true); } public float getCharacterWidth(String text, float size){
if(null == text || "".equals(text))
return 0;
float width = 0;
Paint paint = new Paint();
paint.setTextSize(size);
float text_width = paint.measureText(text);//得到整体长度
width = text_width/text.length();//字符的长度
return width;
} public void setText(String text)
{
this.text = text;
data = new String[]{this.text};
LayoutInflater inflater= (LayoutInflater) getContext().getSystemService(getContext().LAYOUT_INFLATER_SERVICE);
TextView view = (TextView) inflater.inflate(R.layout.scroll_text_view, null);
textSize = view.getTextSize();
measuredHeight = textSize;
textSize = getCharacterWidth(text,textSize);
} public void beginScroll()
{
thread.start();
}
Thread thread = new Thread(new Runnable() {
boolean enabled = true;
@Override
public void run() {
// TODO Auto-generated method stub
while(enabled)
{
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
setNextView();
enabled = mIndex + 1 < mAdapter.getCount();
}
}
}); @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
measuredWidth = getMeasuredWidth();
mSize = mOrientation == LinearLayout.HORIZONTAL? getMeasuredWidth() : getMeasuredHeight();
if(flag && text!=null)
{
int length = text.length();
Log.i("AAA", "length*textSize:"+length*textSize+" measuredWidth:"+measuredWidth);
if(length*textSize >= measuredWidth)
{
int textCountInOneLine = (int) (measuredWidth/textSize -1);
int lineCount =(int) ((length%textCountInOneLine==0)? (length/textCountInOneLine):(length/textCountInOneLine+1));
Log.i("AAA", "length:"+length+" textCountInOneLine:"+textCountInOneLine+" lineCount:"+lineCount);
data = new String[lineCount];
for(int i=0;i<lineCount;i++)
{
if((i+1)*textCountInOneLine<length)
data[i] = text.substring(i*textCountInOneLine, (i+1)*textCountInOneLine);
else
data[i] = text.substring(i*textCountInOneLine, length);
Log.i("AAA", "data:"+data[i]);
}
}
else
{
data = new String[]{text};
} ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(), R.layout.scroll_text_view, data);
setAdapter(adapter);
flag = false;
}
View view = getChildAt(0);
if(view!=null)
{
measureChild(view, widthMeasureSpec, widthMeasureSpec);
measuredHeight = view.getMeasuredHeight();
} setMeasuredDimension((int)measuredWidth, (int)measuredHeight);
} private int getPackedViews(int offset) {
int size = mSize;
int start = offset / size;
int numViews = offset % size != 0? 1 : 0;
return start << 1 | numViews;
} Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
mScroller.computeScrollOffset();
int currX = mScroller.getCurrX();
int delta = mPosition - currX;
mPosition = currX;
int packed = getPackedViews(mPosition);
manageViews(packed);
scroll(delta);
if (!mScroller.isFinished()) {
handler.sendEmptyMessage(msg.what);
} else {
if (msg.what == SCROLL) {
justify();
} else {
mIndex = mPosition / mSize; }
}
}
}; private void justify() {
int offset = mPosition % mSize;
if (offset != 0) {
int endPosition = mPosition - offset;
if (offset > mSize / 2) {
endPosition += mSize;
}
mScroller.startScroll(mPosition, 0, endPosition - mPosition, 0, mAnimationDuration);
handler.sendEmptyMessage(JUSTIFY);
} else {
mIndex = mPosition / mSize; }
} private void scroll(int offset) {
if (mOrientation == LinearLayout.HORIZONTAL) {
for (View view : mViews.keySet()) {
view.offsetLeftAndRight(offset);
}
} else {
for (View view : mViews.keySet()) {
view.offsetTopAndBottom(offset);
}
}
invalidate();
} public void setSelection(int index, boolean animate) {
if (index == mIndex) {
return;
}
int endPosition = index * mSize;
int diff = Math.abs(index - mIndex);
int sign = index > mIndex? 1 : -1;
mIndex = index;
if (diff > 1) {
mPosition = endPosition - sign * mSize;
}
if (animate) {
mScroller.startScroll(mPosition, 0, endPosition - mPosition, 0, mAnimationDuration);
handler.removeMessages(JUSTIFY);
handler.removeMessages(SCROLL);
handler.sendEmptyMessage(JUSTIFY);
} else {
mPosition = endPosition;
manageViews(index << 1); invalidate();
}
} private void manageViews(int packedViews) {
if (packedViews == mPackedViews) {
return;
} mPackedViews = packedViews;
int startIdx = packedViews >> 1;
int endIdx = startIdx + (packedViews & 1);
int viewIdx = startIdx;
while (viewIdx <= endIdx) {
if (!mViews.containsValue(viewIdx)) {
if (viewIdx >= 0 && viewIdx < mAdapter.getCount()) {
View view = mAdapter.getView(viewIdx, null, this);
mViews.put(view, viewIdx);
addView(view);
}
}
viewIdx++;
} // remove not visible views
Iterator<View> iterator = mViews.keySet().iterator();
while (iterator.hasNext()) {
View view = iterator.next();
int idx = mViews.get(view);
if (idx < startIdx || idx > endIdx) {
iterator.remove();
removeView(view);
}
}
} public int getSelection() {
return mIndex;
} public void setPreviousView() {
if (mAdapter != null && mIndex > 0) {
setSelection(mIndex-1, true); }
} public void setNextView() {
if (mAdapter != null && mIndex + 1 < mAdapter.getCount()) {
setSelection(mIndex+1, true);
}
} public void setAdapter(SpinnerAdapter adapter) {
mAdapter = adapter;
if (mAdapter != null) {
setSelection(0, false);
}
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (View view : mViews.keySet()) {
if (view.getWidth() == 0) {
// new View: not layout()ed
int idx = mViews.get(view);
if (mOrientation == LinearLayout.HORIZONTAL) {
int left = mSize * idx - mPosition;
view.layout(left, 0, left+r-l, b-t);
} else {
int top = mSize * idx - mPosition;
view.layout(0, top, r-l, top+b-t);
}
}
}
} }

使用:

String temp = getResources().getString(R.string.info);
ScrollTextView switcher1 = (ScrollTextView) findViewById(R.id.switcher1);
switcher1.setText(temp);
switcher1.beginScroll();

唉,我认为我真是懒....

还是直接给project吧!

源代码

版权声明:本文博主原创文章。博客,未经同意不得转载。

ViewGroup可实现上下、各地跑马灯效果滚动的更多相关文章

  1. ListView 中的TextView实现跑马灯效果

    案例:怎么样在一个ListView中含有TextView的item中实现字母滚动呢.这个在一些特定的场合经常用得到.如下图,当焦点位于某个item的时候其内容就自动滚动显示 要实现这样的效果,废话不多 ...

  2. Android-TextView跑马灯效果

    要实现跑马灯还是比较简单的. 同时有几个需要注意的点,先上代码: public class MTView extends TextView { public MTView(Context contex ...

  3. TextView跑马灯效果

    转载:http://www.2cto.com/kf/201409/330658.html 一.只想让TextView显示一行,但是文字超过TextView的长度怎么办?在开头显示省略号 android ...

  4. Android_TextView之跑马灯效果

    对于android控件中的TextView,相信大家一定不陌生,在显示文本内容时十分方便.不过我在使用时遇到一个小问题,就是当文字交多时,如何为用户进行展示.今天就为大家介绍一种解决方案--跑马灯效果 ...

  5. android中实现跑马灯效果以及AutoCompleteTestView与MultiAutoCompleteTextView的学习

    跑马灯效果 1.用过属性的方式实现跑马灯效果 属性:                  android:singleLine="true" 这个属性是设置TextView文本中文字 ...

  6. Android 实现多行文本跑马灯效果

    Android TextView 实现跑马灯的效果很简单,只要加三个属性就可以了. android:ellipsize="marquee" android:focusable=&q ...

  7. android:ellipsize实现跑马灯效果总结(转)

      最近无意间看到了涉及到跑马灯效果的代码,于是在网上查阅了很多资料,在这里对自己看的一些文章进行一下总结,顺便加上自己的一些体会. 让我们一步步逐渐向下. 首先我们要实现走马灯这样一个效果,通常来说 ...

  8. flex 简单跑马灯效果(竖着显示)

    <mx:Move id="move_area" target="{VBox_AreaWarning}"/> //move效果,模拟跑马灯 <s ...

  9. Dom操作--跑马灯效果

    这里给园友们演示的是Dom操作实现跑马灯效果,相信我们很多人都用Winform实现过跑马灯效果,其中的关键就是Tirm控件,那么在Dom操作中是用setInterval方法来实现隔一段时间执行一段代码 ...

随机推荐

  1. 染色法判断是否是二分图 hdu2444

    用染色法判断二分图是这样进行的,随便选择一个点, 1.把它染成黑色,然后将它相邻的点染成白色,然后入队列 2.出队列,与这个点相邻的点染成相反的颜色 根据二分图的特性,相同集合内的点颜色是相同的,即 ...

  2. Android 通过系统使用NotificationListenerService 监听各种Notification的用法

    NotificationListenerService是通过系统调起的服务,当有应用发起通知的时候,系统会将通知的动作和信息回调给NotificationListenerService. 在继承Not ...

  3. 怎么样putty打开图形化管理工具,在终端上

    有时需要在putty这种图形终端开放的图形化管理工具将出现以下错误: [root@node2 ~]# Traceback (most recent call last): File "/us ...

  4. kNN(K-Nearest Neighbor)最近的分类规则

    KNN最近的规则,主要的应用领域是未知的鉴定,这一推断未知的哪一类,这样做是为了推断.基于欧几里得定理,已知推断未知什么样的特点和最亲密的事情特性: K最近的邻居(k-Nearest Neighbor ...

  5. ftp的主动模式(port)与被动模式(PASV) (转)

    FTP是仅基于TCP的服务,不支持UDP.与众不同的是FTP使用2个端口,一个数据端口和一个命令端口(也可叫做控制端口).通常来说这两个端口是21(命令端口)和20(数据端口).但FTP工作方式的不同 ...

  6. C# 5.0 Async函数的提示和技巧

    一.创建Async函数 Async是C# 5.0中新增的关键字,通过语法糖的形式简化异步编程,它有如下三种方式: async Task<T> MyReturningMethod { ret ...

  7. linux kernel 结构体赋值方法{转载}

    原文地址: http://www.chineselinuxuniversity.net/articles/48226.shtml 这几天看Linux的内核源码,突然看到init_pid_ns这个结构体 ...

  8. 採訪The Molasses Flood:BioShock Infinite 游戏之后又一大作

    Xsolla有幸与Flame in the Flood游戏的开发人员之中的一个-----Forrest Dowling进行了採訪,Flame in the Flood这款非常棒的游戏在Kickstar ...

  9. mac 下有些工具 app 推荐

    打开推荐报价mac在工具app Evernote的 Evernote的贬值,课堂笔记软件,其主要功能是记录笔记,假设你想,它可用于使todo list, 甚至gtd, 或收集的知识归纳 Doit.im ...

  10. unity简易小地图的实现(NGUI)

    首先,我们在场景中添加一个摄像机叫做minimapCamera, 把上面的Audio Listener组件去掉,调整摄像机位置,将其置于角色正上方,如图 新建一个Texture我们叫做minimapT ...