本文概述:
用gallery是实现图片手动滑动和自动滚动的效果
基本解决方案:重写Gallery,重写里面的方法
1、手动滑动
gallery默认便是可进行手动滑动的,但滑动时会同时滑动多张,重写滑动事件onFling(),保证每次只滑动一张图片
/**
* 一次只滑动一张图片
*/
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// TODO Auto-generated method stub
int kEvent;
if (isScrollingRight(e1, e2)) {
kEvent = KeyEvent.KEYCODE_DPAD_LEFT;
} else {
kEvent = KeyEvent.KEYCODE_DPAD_RIGHT;
}
return onKeyDown(kEvent, null);
}
上面有一个isScrollingRight(),只不过是用来判断是向左还是向右滑动:
/**
* 判断手指是否向右滑动
*/
private boolean isScrollingRight(MotionEvent e1, MotionEvent e2) {
return e2.getX() > e1.getX();
}
构造一个计时器,隔一段时间便通知gallery该触发滑动事件onKeyDown(int keyCode,KeyEvent event);
/**
* 构造计时器
*/
private Timer timer = new Timer();
private TimerTask task = new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
handler.sendEmptyMessage(GUIDE_TIMER);
}
};
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case GUIDE_TIMER:
onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
break;
}
};
};
/**
* 开始计时
*/
public void startTimer() {
timer.schedule(task, periodTime, periodTime);
}
计时器的时间间隔periodTime可由外部传入,启动计时器后,每隔periodTime的时间gallery会自动滑动一张图片
3、图片滑动事件与点击事件的冲突问题
在自定义的gallery中重写onInterceptTouchEvent(MotionEvent ev)方法:
/**
* 解决滑动和点击事件冲突,重写该方法拦截触屏事件,返回false将会上抛该事件到子view上面, 返回true则事件不会上抛,将在
* Gallery内部的OnTouchEvent() 接收做处理
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
boolean b = super.onInterceptTouchEvent(ev);
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
e = MotionEvent.obtain(ev);
super.onTouchEvent(ev);
} else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
if (Math.abs(ev.getX() - e.getX()) > 20 || Math.abs(ev.getY() - e.getY()) > 20) {
b = true;
}
}
return b;
}
4、禁止手动滑动
gallery默认是可以进行手动滑动的,若只想让图片自动滚动,重写里面的 onTouchEvent(MotionEvent event)事件,将返回值返回false即可:
/**
* 重写touch事件,禁止滑动
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
5、无限循环自动滚动
上面的方法在自动滚动完最后一张图片后,gallery的自动滚动便会停止,若想让gallery滚动完最后一张后出现第一张重新滚动,可重新定义adapter,处理getCount()和getView()方法,将个数设置成Integer.MAX_VALUE,显示时对应将相应的图片展示出来即可:
@Override
public int getCount() {
// TODO Auto-generated method stub
return Integer.MAX_VALUE;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
// TODO Auto-generated method stub
if (view == null) {
view = LayoutInflater.from(context).inflate(R.layout.gallery_item, null);
}
ImageView imageView = (ImageView) view.findViewById(R.id.item_iv);
imageView.setImageResource(icon[position % icon.length]);
return view;
}
同时,为了让用户感觉可以左右无限循环,可将gallery默认选中最大值的中间部分,即使是刚开始也能左右都能滑动:
int centerNum = Integer.MAX_VALUE / 2;
centerNum -= centerNum % size;//size图片个数,显示的是第一张图片
myGallery.setSelection(centerNum);// 设置默认选中
6、左右自动滚动(顺序滚动完最后一张,然后逆序滚动,逆序滚动到第一张,再顺序滚动)
此种实现不需要类似5那样处理adapter,像常规处理即可,处理类似上边的handler回调:
//position当前页,num图片数量
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case GUIDE_TIMER:
if (flag) {// 向右
onScroll(null, null, 1, 0);
onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
if (position == num - 2) {//滑动到最后一张
flag = false;
}
} else if (!flag) {// 向左
onScroll(null, null, -1, 0);
onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, null);
if (position == 1) {//滑动到第一张
flag = true;
}
}
break;
}
};
};
当前页的position可由设置监听 OnItemSelectedListener获得
7、自动滚动抖动问题
当gallery放在RelativeLayout中时,在滚动过程中会出现左右抖动,解决方法,将gallery的外面套的父RelativeLayout统统去掉(同级不影响),可选用Framelayout代替。
8、边框模糊问题
xml添加属性 android:fadingEdgeLength=”0dp”
9、设置setSpacing()后自动滚动失效
gallery设置setSpacing()之后会导致onKeyDown()失效,从而不能自动滚动,调用onScroll()方法可解决问题
/**
* gallery设置setSpacing()后,onKeyDown()会失效,添加onScroll方法可解决,
* 后面两个参数分别是自上次调用onScroll方法在X、Y上的距离
**/
onScroll(null, null, 1, 0);
onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
10、gallery每个子元素充满整个屏幕
如果显示的内容比较小,gallery会自动在一个屏幕显示好几个子元素,想要每个屏幕只显示一个元素,关键改变item的layout的最外层,使用RelativeLayout
11、禁止点击声音
setSoundEffectsEnabled(false);
setHapticFeedbackEnabled(false);