自定义gallery,避免选中项总在中间的问题

最近做了一个小功能,实现类似gallery的效果,但需要选中项在第一个,且不希望拉到最前面会有空余空间,在尝试使用android自带的gallery未能达到效果的情况下,自己写了个简单但能满足功能的东东。首先分享一下对于gallery的使用。

首先面对的是不希望拉到最前面有空白,所以参考网上的例子,通过setselection设置选中一个较大的数字,当然,这里要求在adapter中设置getcount方法里返回int的最大值,以下是getview内的代码,cacheView是类里定义的一个缓存itemview的HashMap<Integer,View>对象,然后通过position%list.size()获取已经在缓存内的view,其中list就是数据源数据集合

convertView = cacheView.get(position%list.size());
            if(convertView== null){
                convertView = mInflater.inflate(layoutId, null);
                ImageView iv =(ImageView) convertView.findViewById(R.id.image);
                iv.setBackgroundResource(list.get(position%list.size()));
                cacheView.put(position%list.size(), convertView);
            }
  return convertView;

这样做的效果就是一开始就处于满屏的,且左右拉会有循环显示的效果,但选中项仍然在中间,且拖拉结束时,会自动选中一个

鉴于以上不能满足需求,我尝试了继承gallery重写里面的onTouchEvent,onFling方法,可以通过MotionEvent.ACTION_UP以及onFling 直接return false;达到拖拉时不自动选中,但是项的单击事件也会无法使用,即OnItemClickListener无法触发,在来回纠结并尝试了很久后,还是放弃了

在网上看到有人提出一个使用ScrollView自己实现gallery的思路,于是便写了一个功能简单,但便于使用的代码,在此做一分享,希望给大家一些思路

public class MyGallery extends HorizontalScrollView {
	
	public MyGallery(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public MyGallery(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}
	
	private List<ImageView> imageViews =new ArrayList<ImageView>();//图片view对象,初始化后生成
	private List<TextView> textViews =new ArrayList<TextView>();//文本view对象,初始化后生成
	private Context mContext;//调用本view的activity
	private int mWidth;//宽度onlayout里赋值
	private int selectedItemIndex = -1;//选中的项下标
	private int displayNum = 5;//要显示项的数量
	private int defaultIndex = 0;//默认选中的下标
	private int itemWidth;//每一项的宽度
	private OnClickListener itemClickListener;//点击每项的事件,初始化传入,可以通过onclick中的view内的tag获得postion区分
	private Handler handler;//用来处理选中滚动事件
	private int inoutTime = 200;//放大缩小所耗时间
	private float scale = 1.2f;//放大后的比例
	private LayoutInflater mInflater;
	private List<IWantType> typeList;//类别列表
	private int adjust =-5;//调整移动位置
	public MyGallery(Context context) {
		super(context);
		this.mContext = context;
	}
	/**
	 * 完成布局时根据宽度与显示的数量初始化item布局
	 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if(this.mWidth != this.getWidth()){
			this.mWidth = this.getWidth();
			this.itemWidth = this.mWidth/this.displayNum;
			initImages(itemClickListener);
		}
	}
	/**
	 * 初始化
	 * @param context
	 * @param images
	 * @param itemClickListener
	 */
	public void init(Context context,List<IWantType> typeList,OnClickListener itemClickListener,int defaultIndex) {
		this.typeList = typeList;
		this.mContext = context;
		this.mInflater = LayoutInflater.from(context);
		this.defaultIndex = defaultIndex;
		this.setVerticalScrollBarEnabled(false); //禁用垂直滚动
		this.setHorizontalScrollBarEnabled(false); //禁用水平滚动
		this.itemClickListener = itemClickListener;
		this.handler =new Handler(){
			public void handleMessage(Message msg) {
				if(msg.arg1>msg.arg2){
					int each = (msg.arg1-msg.arg2)/10;
					if(msg.arg2+each<msg.arg1 && each>0){
						scrollTo(msg.arg2+each+adjust, 0);
					}else{
						scrollTo(msg.arg1+adjust, 0);
					}
					Message message = new Message();
					message.arg1 =msg.arg1;
					if(each!=0){
						message.arg2 =msg.arg2+each;
						sendMessageDelayed(message, 1);
					}
				}else{
					int each = (msg.arg2-msg.arg1)/10;
					if(msg.arg2-each>msg.arg1 && each>0){
						scrollTo(msg.arg2-each+adjust, 0);
					}else{
						scrollTo(msg.arg1+adjust, 0);
					}
					Message message = new Message();
					message.arg1 =msg.arg1;
					if(each!=0){
						message.arg2 =msg.arg2-each;
						sendMessageDelayed(message, 1);
					}
				}
			};
		};
	}
	/**
	 * 绑定图片项
	 * @param clickListener
	 */
	private void initImages(OnClickListener clickListener){
		this.removeAllViews();
		LinearLayout ll = new LinearLayout(mContext);
		ll.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
		for(int i=0;i<typeList.size();i++){
			IWantType iWantType = typeList.get(i);
			FrameLayout llitem =(FrameLayout) mInflater.inflate(R.layout.mygallery_item, null);
			llitem.setLayoutParams(new RelativeLayout.LayoutParams(this.itemWidth , LayoutParams.WRAP_CONTENT));
			ImageView image =(ImageView) llitem.findViewById(R.id.image);
			image.setTag(i);
			image.setOnClickListener(clickListener);
			TextView textView = (TextView) llitem.findViewById(R.id.text);
			textView.setText(iWantType.name);
			textView.setTextColor(Color.parseColor(iWantType.color));
			NeighborApplication.getSelf().getPictrueManager().download(iWantType.pic, image);
			ll.addView(llitem);
			imageViews.add(image);
			textViews.add(textView);
		}
		this.addView(ll);
		selectItem(defaultIndex);
	}
	
	
	
	/**
	 * 获取某个imageView
	 * @param postion
	 * @return
	 */
	public ImageView getItemView(int postion){
		return imageViews.get(postion);
	}
	/**
	 * 选中某个item
	 * @param position
	 */
	public void selectItem(Integer position){
		if(position!=selectedItemIndex){
			if(selectedItemIndex!=-1){
				imageViews.get(selectedItemIndex).startAnimation(scaleIn(inoutTime));
				textViews.get(selectedItemIndex).startAnimation(scaleIn(inoutTime));
			}
			imageViews.get(position).startAnimation(scaleOut(inoutTime));
			textViews.get(position).startAnimation(scaleOut(inoutTime));
			selectedItemIndex = position;
			Message msg=new Message();
			msg.arg1 = position*itemWidth;
			msg.arg2 = getScrollX();
			this.handler.sendMessage(msg);
		}
	}
	
	
	
	/**
	 * 选择下一个
	 * @return 选中的index
	 */
	public int selectNext(){
		if(selectedItemIndex+1<imageViews.size()){
			selectItem(selectedItemIndex+1);
		}
		return selectedItemIndex;
	}
	/**
	 * 选择上一个
	 * @return 选中的index
	 */
	public int selectPrev(){
		if(selectedItemIndex>0){
			selectItem(selectedItemIndex-1);
		}
		return selectedItemIndex;
	}
	
	/**
	 * 以自身中心为圆心扩放
	 * @param 持续时间
	 * @return
	 */
	private Animation scaleOut(long time){
		Animation animation =new ScaleAnimation(1,scale,1,scale,Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF,0.5f);
		animation.setDuration(time);
		animation.setFillAfter(true);
		return animation;
	}
	/**
	 * 以自身中心为圆心收缩
	 * @param 持续时间
	 * @return
	 */
	private Animation scaleIn(long time){
		Animation animation =new ScaleAnimation(scale,1,scale,1,Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF,0.5f);
		animation.setDuration(time);
		return animation;
	}
其中iwanttype类是一个实体类,大家可以根据自己的需求更改,主要用于给项绑定数据

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >
   <ImageView 
   	  android:id="@+id/image"
   	  android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true"
   />
   <TextView 
      android:id="@+id/text"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="center_horizontal"
      android:layout_marginTop="60dip"
   />
</FrameLayout>

以上是item项布局文件,就一个图片和下面的文字,因为我这里要文字覆盖一部分图片,所以使用的framelayout,大家可以按需使用

总体思路是,根据数据源,在一个LinearLayout里循环插入imageview以及textview,并根据外部传入的click事件绑定点击事件,这里需要注意的是,在自己写onclick方法时,需要根据view的getTag来区分每项= =没有itemclick那么方便了。。不过还是可以使用的,我这里选中项是在最前面的,大家也可以根据需求修改handler里的控制滚动代码,这样一个简单实用的gallery就完工了~~~

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值