在很多天气或者新闻的应用中,我们都能看到一些字幕滚动的效果,最简单的实现为跑马灯效果,用系统提供的属性即可实现. 复杂一些的就需要自己去用自定义控件实现. 比如 让TextView 实现垂直滚动. 这里我要讲的是垂直滚动的字幕效果,并且内容并不仅为文字,还可以加入图片或者其他元素. 废话不多说,还是直接上效果图:
首先还是看一下核心的实现:
目前我的做法是重写了ScrollView,对外提供几个重要的方法:
isScrolled()方法判断当前是否为滚动状态
setScrolled(boolean flag)设置滚动的开关
setPeriod(long period)设置从开始滚动到结束的时间
setSpeed(long speed)设置滚动的速度
下面说一些需要注意的地方:
1.由于是定时操作,所以需要在Activity的对应生命周期进行处理: 当界面由不可见到可见时,设置setScrolled(true)打开滚动开关,由可见到不可见时,setScrolled(false)
关闭开关
2. 可根据自己需要调用setPeriod(long period)和setSpeed(long speed)控制滚动的速度
3. 由于是ScrollView实现的,中间放置的内容同ScrollView,不仅仅可以设置文字,还可以添加图片等其他元素,实现复杂的UI
4. 图文混排, 目前这个DEMO我还没做细致处理. 最主要的部分就是文字的处理,需要考虑中英文,全角半角,字体大小,段落处理,计算对应的字符宽高等进行排版
图片等资源处理的部分就相对要简单,主要处理分辨率与计算宽高
关于这些部分,之后我会慢慢做细致讲解.
这个Demo是我临时写的,UI和图文混排包括具体的滚动部分处理都相对简单,大家可以在这个例子的基础上进行扩展,根据需求做出自己想要的效果:
下面是对应的代码:
首先是自定义View:
packagecom.tony.autoscroll;
importandroid.content.Context;
importandroid.os.Handler;
importandroid.util.AttributeSet;
importandroid.util.Log;
importandroid.view.MotionEvent;
importandroid.widget.ScrollView;
/**
* @author Tony
*
*/
publicclassAutoScrollViewextendsScrollView {
privatefinalHandler handler =newHandler();
privatelongduration =50;
privatebooleanisScrolled =false;
privateintcurrentIndex =0;
privatelongperiod =1000;
privateintcurrentY = -1;
privatedoublex;
privatedoubley;
privateinttype = -1;
/**
* @param context
*/
publicAutoScrollView(Context context) {
this(context,null);
}
/**
* @param context
* @param attrs
*/
publicAutoScrollView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
/**
* @param context
* @param attrs
* @param defStyle
*/
publicAutoScrollView(Context context, AttributeSet attrs,intdefStyle) {
super(context, attrs, defStyle);
}
publicbooleanonTouchEvent(MotionEvent event) {
intAction = event.getAction();
switch(Action) {
caseMotionEvent.ACTION_DOWN:
x=event.getX();
y=event.getY();
if(type ==0) {
setScrolled(false);
}
break;
caseMotionEvent.ACTION_MOVE:
doublemoveY = event.getY() - y;
doublemoveX = event.getX() - x;
if((moveY>20||moveY -50) && getParent() !=null) {
getParent().requestDisallowInterceptTouchEvent(true);
}
break;
caseMotionEvent.ACTION_UP:
if(type ==0) {
currentIndex = getScrollY();
setScrolled(true);
}
break;
default:
break;
}
returnsuper.onTouchEvent(event);
}
@Override
publicbooleanonInterceptTouchEvent(MotionEvent p_event)
{
returntrue;
}
/**
* 判断当前是否为滚动状态
*
* @return the isScrolled
*/
publicbooleanisScrolled() {
returnisScrolled;
}
/**
* 开启或者关闭自动滚动功能
*
* @param isScrolled true为开启,false为关闭
*/
publicvoidsetScrolled(booleanisScrolled) {
this.isScrolled = isScrolled;
autoScroll();
}
/**
* 获取当前滚动到结尾时的停顿时间,单位:毫秒
*
* @return the period
*/
publiclonggetPeriod() {
returnperiod;
}
/**
* 设置当前滚动到结尾时的停顿时间,单位:毫秒
*
* @param period
* the period to set
*/
publicvoidsetPeriod(longperiod) {
this.period = period;
}
/**
* 获取当前的滚动速度,单位:毫秒,值越小,速度越快。
*
* @return the speed
*/
publiclonggetSpeed() {
returnduration;
}
/**
* 设置当前的滚动速度,单位:毫秒,值越小,速度越快。
*
* @param speed
* the duration to set
*/
publicvoidsetSpeed(longspeed) {
this.duration = speed;
}
publicvoidsetType(inttype){
this.type = type;
}
privatevoidautoScroll() {
handler.postDelayed(newRunnable() {
@Override
publicvoidrun() {
booleanflag = isScrolled;
if(flag) {
if(currentY == getScrollY()) {
try{
Thread.sleep(period);
} catch(InterruptedException e) {
e.printStackTrace();
}
currentIndex = 0;
scrollTo(0,0);
handler.postDelayed(this, period);
} else{
currentY = getScrollY();
handler.postDelayed(this, duration);
currentIndex++;
scrollTo(0, currentIndex *1);
}
} else{
//currentIndex = 0;
//scrollTo(0, 0);
}
}
}, duration);
}
}
MainActivity:
packagecom.tony.autoscroll;
importcom.example.testautoscroll.R;
importandroid.os.Bundle;
importandroid.app.Activity;
/**
* link: blog.csdn.net/t12x3456
* @author Tony
*
*/
publicclassMainActivityextendsActivity {
privateAutoScrollView scrollView;
@Override
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = (AutoScrollView) findViewById(R.id.auto_scrollview);
}
@Override
protectedvoidonStart() {
// TODO Auto-generated method stub
if(!scrollView.isScrolled()){
scrollView.setScrolled(true);
}
super.onStart();
}
@Override
protectedvoidonStop() {
// TODO Auto-generated method stub
if(scrollView.isScrolled()){
scrollView.setScrolled(false);
}
super.onStop();
}
}