自定義gallery,避免選中項總在中間的問題 – Android移動開發技術文章_手機開發 Android移動開發教學課程

最近做瞭一個小功能,實現類似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就完工瞭~~~

摘自 chenghaoorange的專欄
 

發佈留言