ViewGroup可实现上下、各地跑马灯效果滚动

先上效果图:

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

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

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

代码:

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吧!

源代码

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

时间: 2024-07-31 11:30:08

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

ListView 中的TextView实现跑马灯效果

案例:怎么样在一个ListView中含有TextView的item中实现字母滚动呢.这个在一些特定的场合经常用得到.如下图,当焦点位于某个item的时候其内容就自动滚动显示 要实现这样的效果,废话不多说直接上代码: adapter对应的layout 对应的listView的layout 切记千万不要在TextView中加上android:focusable="true" view plain <LinearLayout android:orientation="vert

练习:WinForm 跑马灯效果+Timer

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace Timer { public partial class Form1 : Form { public Form1

Android TextView跑马灯效果

TextView跑马灯简单效果 <!--简单示例--> <TextView android:text="@string/longWord" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView1" android:ellipsize="marquee&quo

android 怎么实现跑马灯效果

自定义控件 FocusedTextView, 使android系统误以为它拥有焦点 1 public class FocusedTextView extends TextView { 2 public FocusedTextView(Context context, AttributeSet attrs, int defStyle) { 3 super(context, attrs, defStyle); 4 // TODO Auto-generated constructor stub 5 }

框架,锚点,背景音乐,嵌入视频和跑马灯效果

框架,iframe有点过时,会在部分浏览器出现一些奇怪的问题:设置三个属性: 1.src,框架默认的显示路径 2.name,让超链接的target属性与name值相等,就可以将超链接网页在框架中打开 3.框架的宽度和高度 站点:实际上就是一个文件夹,单独起了一个名字.统一来管理所有页面,就是一个站点,称之为网站 锚点: 书写格式:<a href="#锚点位置对应的名称">内容</a> --#是在本页面中 <a name="锚点位置的名称"

jCarousel Lite 实现图片跑马灯效果

官方网站:http://www.gmarwaha.com/jquery/jcarousellite/ demo: <!DOCTYPE> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <script src="http://libs.baidu.com/jquery/1.9.0/jquer

Android界面(1) 使用TextView实现跑马灯效果

方法一:(只能实现单个TextView的跑马灯效果)在TextView添加以下控件 android:singleLine="true"只能单行,超出的文字显示为"..." android:ellipsize="marquee"省略号没有,但没有跑马灯效果 android:focusable="true" android:focusableInTouchMode="true" 方法二:(可以实现多行TextV

安卓TextView的跑马灯效果

跑马灯效果的实现非常简单,可分为两步 1.定义一个View继承TextView,重写isFocused方法 package com.jsako.marquee; import android.content.Context; import android.util.AttributeSet; import android.view.ViewDebug.ExportedProperty; import android.widget.TextView; public class MarqueeTex

2、按下按键S1控制LED1.LED2.LED3实现跑马灯效果(CC2540开发寄存器设置)

按下按键S1控制LED1.LED2.LED3实现跑马灯效果 1 /**************************************************************************** 2 * 文 件 名: main.c 3 * 作 者: Amo [ www.amoMcu.com 阿莫单片机] 4 * 修 订: 2014-04-08 5 * 版 本: 1.0 6 * 描 述: 按下按键S1控制LED1.LED2.LED3实现跑马灯效果 7 ***********