自定义ViewFlipper实现带索引效果的自动播放广告栏

本文介绍了如何模仿淘宝和易迅客户端的广告栏,创建一个带有指引效果的自定义ViewFlipper。通过实现OnGestureListener接口,允许用户手动滑动广告栏,并在用户滑动前暂停自动播放。关键在于通过自定义回调接口监听显示View的变化,以实现索引效果。文章提供了自定义ViewFlipper的源码及部分实现细节。
摘要由CSDN通过智能技术生成

前几天看到淘宝和易迅的客户端的广告栏做的不错,今天就尝试了一下,模仿着写了带指引的ViewFlipper。本文主要介绍指引栏的实现,论坛上关于ViewFlipper的使用和介绍很多,就不过多介绍。

效果图如下:


首先是布局,稍有Android开发经验的人很容易看出来,这是一个Layout里面嵌套了ViewFliper和一个LinearLayout。布局如下:

 <RelativeLayout 
        android:id="@+id/food_recom_viewfliper_rl"
        android:layout_width="fill_parent"
        android:longClickable="true"
        android:layout_height="150dp">
     <com.mobsut.mm.widget.GestureViewFliper
         android:id="@+id/food_recom_viewfliper"
         android:layout_height="150dp"
         android:background="@color/white"
         android:layout_width="fill_parent"/>
     <LinearLayout
         android:id="@+id/food_recom_page_indicator"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
         android:gravity="center"
         android:orientation="horizontal"
         android:padding="@dimen/offset_2dp"></LinearLayout>
     </RelativeLayout >


可以看到这个GestureViewFliper是我自定义的,继承于VIewFlipper,实现OnGestureListener接口用来识别用户手势,让用户可以手动滑动广告栏。在用GestureDetector 识别手势时,会出现一个问题:onFling函数不被触发,这时需要把onDown设置为true。

在用户滑动之前,需要注意:当用户将作出滑动手势时,需要停掉自动播放,然后用户结束滑动时,继续自动播放

然后是重点,要实现带索引的效果,首先需要得到ViewFlipper的当前展示的View的索引值,而这个View当自动播放时是实时变化的,但是ViewFlipper并没有提供一个接口,在可以监听自动播放时view的变化。所以,需要自定义一个回调接口,监听displayView的变化,并把相应的索引值传递出去。这样才可以实现索引效果。

自定义的ViewFlipper源码如下:

package com.mobsut.mm.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.animation.AnimationUtils;
import android.widget.ViewFlipper;
/*
 * 自定义的ViewFliper,监听滑动手势,以及自动指引
 * @author jiakang
 */
import com.mobsut.mm.R;

public class GestureViewFliper extends ViewFlipper implements OnGestureListener {

	GestureDetector gestureDetector = null;
	private Context mContext = null;
	FlipperFacousChangedListener flipperFacousChangedListener=null;

	public GestureViewFliper(Context mContext) {
		super(mContext);

	}

	public GestureViewFliper(Context mContext, AttributeSet attrs) {
		super(mContext, attrs);
		this.mContext = mContext;
		gestureDetector = new GestureDetector(mContext, this);
		setLongClickable(true);
		setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				return gestureDetector.onTouchEvent(event);
			}
		});
	}

	@Override
	public void startFlipping() {
		// TODO Auto-generated method stub
		super.startFlipping();
		setInAnimation(AnimationUtils.loadAnimation(mContext,
				R.anim.m_push_up_in));   
		setOutAnimation(AnimationUtils.loadAnimation(mContext,
				R.anim.m_push_up_out));
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		stopFlipping();       //用户点击屏幕时,停止滑动
		setAutoStart(false);   //取消自动滑动
		return this.gestureDetector.onTouchEvent(event);   //把touch事件交给gesture处理
	}

	@Override
	public boolean onDown(MotionEvent e) {
		// TODO Auto-generated method stub
		return true; // 缺省值是false,在onTouchEvent后触发,如果为false,onFling将得不到down的事件即不触发
	}

	/*
	 * 重写了onFling,为了判断手势,让手势滑动
	 * 
	 * @see android.view.GestureDetector.OnGestureListener#onFling(android.view.
	 * MotionEvent, android.view.MotionEvent, float, float)
	 */

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		// TODO Auto-generated method stub
		if (e2.getX() - e1.getX() > 120) {    // 从左侧滑进
			setInAnimation(AnimationUtils.loadAnimation(mContext,
					R.anim.m_push_up_in));     //设置进出动画
			setOutAnimation(AnimationUtils.loadAnimation(mContext,
					R.anim.m_push_up_out));
			//用户手势滑动结束,再次开始自动播放
			showPrevious();
			setAutoStart(true);
			startFlipping();

			return true;
		} else if (e2.getX() - e1.getX() < -120) {   //从右侧画出
			setOutAnimation(AnimationUtils.loadAnimation(mContext,
					R.anim.m_push_up_out));         //设置进出动画
			setInAnimation(AnimationUtils.loadAnimation(mContext,
					R.anim.m_push_up_in));			
			//滑动结束,再次自动播放
			showNext();
			setAutoStart(true);
			startFlipping();

			return true;
		}
		return false;
	}
	
	

	@Override
	public void showNext() {
		// TODO Auto-generated method stub
		super.showNext();
		//监听向下向下翻页
		flipperFacousChangedListener.onFliperChanged(getDisplayedChild());
	}

	@Override
	public void showPrevious() {
		// TODO Auto-generated method stub
		super.showPrevious();
		//监听向上翻页
		flipperFacousChangedListener.onFliperChanged(getDisplayedChild());
	}

	@Override
	public void onLongPress(MotionEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public void onShowPress(MotionEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}
	/*
	 * 回调接口,用于监听viewflipper切花事件
	 */
	
	public interface FlipperFacousChangedListener{
		public void onFliperChanged(int index);
	}
	
	public void setOnFacousChangedListener(FlipperFacousChangedListener flipperFacousChangedListener){
		this.flipperFacousChangedListener=flipperFacousChangedListener;
	}

}


接着是实现部分,指引条是由两张图片构成,选中项目一个颜色,未选中时一个颜色。实现比较简单,部分代码如下:

package com.mobsut.mm.foods;

public class FoodRecomFragment extends Fragment {

	private Context mContext=null;
	private LinearLayout mainLayout=null;
	private LinearLayout indicatorLayout=null;
	private ImageView[] mImageView;
	
	private int[] fliperImage={R.drawable.fliper1,R.drawable.fliper2,R.drawable.fliper3};
	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		mContext=getActivity();
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		mainLayout=(LinearLayout)inflater.inflate(R.layout.food_recom_fragment_main,container,false);
		indicatorLayout=(LinearLayout)mainLayout.findViewById(R.id.food_recom_page_indicator);
		GestureViewFliper viewFilper=(GestureViewFliper)mainLayout.findViewById(R.id.food_recom_viewfliper);
		mImageView=new ImageView[fliperImage.length];
		for(int i=0;i<fliperImage.length;i++){
			
			ImageView iv=new ImageView(mContext);
			ImageView indicatorView=new ImageView(mContext);
			if(i==0){
				indicatorView.setImageResource(R.drawable.page_selected);//初始默认选中第一张为当前指引
			}else{
				indicatorView.setImageResource(R.drawable.page_normal);
			}
			iv.setImageResource(fliperImage[i]);
			//把指引条的图片添加到LinearLayout里面
			LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);
			lp.setMargins(6, 0, 0, 0);
			indicatorView.setLayoutParams(lp);
			iv.setScaleType(ScaleType.FIT_XY);
			viewFilper.addView(iv, new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
			mImageView[i]=indicatorView;
			indicatorLayout.addView(mImageView[i]);
		}
		viewFilper.setAutoStart(true);    //让viewFlipper自动播放
		viewFilper.setFlipInterval(4000); //间隔为4S
		if(viewFilper.isAutoStart()&&viewFilper.isFlipping()){
			viewFilper.startFlipping();
		}
		if(viewFilper.getDisplayedChild()!=0){
			viewFilper.setInAnimation(AnimationUtils.loadAnimation(
                    mContext, R.anim.m_push_up_in));   //进出动画
			viewFilper.setOutAnimation(AnimationUtils.loadAnimation(
                    mContext, R.anim.m_push_up_out));
		}
		viewFilper.setOnFacousChangedListener(new FlipperFacousChangedListener() {
			
			@Override  //实现监听接口
			public void onFliperChanged(int index) {
				// TODO Auto-generated method stub
				for(int i=0;i<mImageView.length;i++){
					if(i==index){					
					mImageView[i].setImageResource(R.drawable.page_selected);
					}else{
						mImageView[i].setImageResource(R.drawable.page_normal);
					}
					
				}
			}
		});
		return mainLayout;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值