近期在弄个项目。要求有跑马灯效果的图片展示。
网上搜了一堆,都没有完美实现的算了还是自己写吧!
实现原理利用 ViewPager 控件,这个控件本身就支持滑动翻页非常好非常强大好多功能都能用上它。利用mViewPager.setCurrentItem(currentIndex); 来实现切换当前显示的view
在加一个定时器不断设置setCurrentItem 来实现跑马灯效果。
一。主要实现类 凝视非常具体了 一看就知道了
package com.example.marqueeimage;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import com.example.marqueeimage.adapter.MarqueeAdapter;
import com.example.marqueeimage.transforms.ABaseTransformer;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class MarqueeImage extends LinearLayout{
private ViewPager mViewPager;
private ArrayList<View> mPageViewList=new ArrayList<View>();//数据�?
private ImageView mImageView;
private ImageView[] mImageViews;
//主布�?��部指示当前页面的小圆点视图,LinearLayout
private ViewGroup indicatorViewGroup;
private LayoutInflater mInflater;//定义LayoutInflater
private MarqueeAdapter marqueeAdapter;//适配�?
private Timer mTimer=null;//定时�?
public int currentIndex=0;//当前显示View页面的序号
private Handler mHandler;//处理更换图片消息
private FixedSpeedScroller scroller=null;
private Context mContext;
public MarqueeImage(Context context) {
super(context);
init(context);
}
public MarqueeImage(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context){
mContext=context;
LayoutInflater.from(mContext).inflate(R.layout.marquee_image, this);
mViewPager = (ViewPager) findViewById(R.id.marquee_image_viewpager);
indicatorViewGroup = (ViewGroup) findViewById(R.id.marquee_image_bottomviewgroup);
mViewPager.setOnPageChangeListener(new pageChangeListener());
mViewPager.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
stopAutoScroller();
setScrollerTime(100);
}else if(event.getAction()==MotionEvent.ACTION_UP){
startAutoScroller();
}
return false;
}
});
marqueeAdapter=new MarqueeAdapter();
mViewPager.setAdapter(marqueeAdapter);
initHandle();
}
/**
* 设置滑动动画
* mViewPager.setPageTransformer(true,new CubeOutTransformer());
mViewPager.setPageTransformer(true,new AccordionTransformer());
mViewPager.setPageTransformer(true,new FlipHorizontalTransformer());
mViewPager.setPageTransformer(true,new RotateUpTransformer());
mViewPager.setPageTransformer(true,new ZoomOutTranformer());
mViewPager.setPageTransformer(true,new ZoomOutSlideTransformer());
mViewPager.setPageTransformer(true,new TabletTransformer());
*/
public void setScrollerAnimation(ABaseTransformer animation){
mViewPager.setPageTransformer(true,animation);
}
/**
* 開始自己主动滚动
*/
public boolean startAutoScroller(){
return startTime();
}
/**
* 停止自己主动滚动
*/
public boolean stopAutoScroller(){
if(mTimer!=null){
mTimer.cancel();
mTimer=null;
return true;
}else{
return false;
}
}
/**
* 初始化Handle
*/
public void initHandle(){
mHandler = new Handler() {
@SuppressLint("NewApi") public void handleMessage(Message msg) {
if(msg.what==1){
setScrollerTime(700);
mViewPager.setCurrentItem(currentIndex);
if(mPageViewList.size()-1==currentIndex){
currentIndex=0;
}else{
currentIndex++;
}
}
};
};
}
/**
* 设置滑动时间
*/
public void setScrollerTime(int scrollerTime){
try {
if(scroller!=null){
scroller.setTime(scrollerTime);
}else{
Field mScroller;
mScroller = ViewPager.class.getDeclaredField("mScroller");
mScroller.setAccessible(true);
scroller= new FixedSpeedScroller(mViewPager.getContext(),new AccelerateInterpolator());
scroller.setTime(scrollerTime);
mScroller.set(mViewPager, scroller);
}
} catch (Exception e) {
}
}
/**
* 创建底部的导航条
*/
public void createNavBar(){
mImageViews = new ImageView[mPageViewList.size()];
for (int i = 0; i < mImageViews.length; i++) {
mImageView = new ImageView(mContext);
mImageView.setLayoutParams(new LayoutParams(20,20));
mImageView.setPadding(20, 0, 20, 0);
if (i == 0) {
mImageView.setBackgroundResource(R.drawable.page_indicator_focused);
} else {
mImageView.setBackgroundResource(R.drawable.page_indicator);
}
mImageViews[i] = mImageView;
//把指示作用的远点图片加入底部的视图中
indicatorViewGroup.addView(mImageViews[i]);
}
}
class pageChangeListener implements OnPageChangeListener{
@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
for (int i = 0; i < mImageViews.length; i++) {
if(i == arg0) {
mImageViews[i].setBackgroundResource(R.drawable.page_indicator_focused);
} else {
mImageViews[i].setBackgroundResource(R.drawable.page_indicator);
}
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
}
/**
* 启动计时
*/
private boolean startTime(){
if(mTimer==null){
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
@Override
public void run() {
Message msg=new Message();
msg.what=1;
mHandler.sendMessage(msg);
}
},2000,2000); //每2秒运行一次
return true;
}else{
return false;
}
}
/**
* 设置数据
* @param mPageViews
*/
public void setData(ArrayList<View> pageViewList){
if(pageViewList!=null){
this.mPageViewList=pageViewList;
marqueeAdapter.setData(mPageViewList);//加入数据
marqueeAdapter.notifyDataSetChanged();//通知数据发生改变�?
createNavBar();//依据数据。创建导航条
}
}
/**
* 清理所有数据
*/
public void clearData(){
if(this.mPageViewList!=null){
this.mPageViewList.clear();
}
mViewPager.removeAllViews();
indicatorViewGroup.removeAllViews();
}
}
二。
ViewPager的适配器也非常easy
package com.example.marqueeimage.adapter;
import java.util.ArrayList;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
/**
* @author fcm
* @Create at 2013-8-27 下午2:48:34
* @Version 1.0
* <p>
Features draft description.
主要功能介绍
</p>
*/
public class MarqueeAdapter extends PagerAdapter{
private ArrayList<View> mPageViews=new ArrayList<View>();
/**
* 加入数据
* @param mPageViews
*/
public void setData(ArrayList<View> mPageViews){
this.mPageViews=mPageViews;
}
@Override
public int getCount() {
return mPageViews.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public int getItemPosition(Object object) {
// TODO Auto-generated method stub
return super.getItemPosition(object);
}
@Override
public void destroyItem(View arg0, int arg1, Object arg2) {
// TODO Auto-generated method stub
((ViewPager) arg0).removeView(mPageViews.get(arg1));
}
@Override
public Object instantiateItem(View arg0, int arg1) {
// TODO Auto-generated method stub
((ViewPager) arg0).addView(mPageViews.get(arg1));
return mPageViews.get(arg1);
}
@Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
// TODO Auto-generated method stub
}
@Override
public Parcelable saveState() {
// TODO Auto-generated method stub
return null;
}
@Override
public void startUpdate(View arg0) {
// TODO Auto-generated method stub
}
@Override
public void finishUpdate(View arg0) {
// TODO Auto-generated method stub
}
}
三。
控制滑动速度 这个非常重要 设置自己主动滚动默认的速度的非常快 效果非常差,用FixedSpeedScroller继承Scroller来实现控制viewpaper滑动速度 这部分来自网络
package com.example.marqueeimage;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.animation.Interpolator;
import android.widget.Scroller;
public class FixedSpeedScroller extends Scroller {
private int mDuration =500;
public void setTime(int scrollerTime){
mDuration=scrollerTime;
}
public FixedSpeedScroller(Context context) {
super(context);
}
public FixedSpeedScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
@SuppressLint("NewApi") public FixedSpeedScroller(Context context, Interpolator interpolator, boolean flywheel) {
super(context, interpolator, flywheel);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
}
四。
布局文件:
<?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:id="@+id/marquee_image_layout"
android:orientation="vertical">
<!--拖动 -->
<android.support.v4.view.ViewPager
android:id="@+id/marquee_image_viewpager"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
/>
<LinearLayout
android:id="@+id/marquee_image_bottomviewgroup"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal" >
</LinearLayout>
</LinearLayout>
五。
最后一步就是改动默认动画,实现比較绚丽的效果 这部分来自网络 大约有10种左右动画吧