處理好item點選事件的gallery(畫廊)效果(無bug)

BigSweetee發表於2017-04-24

前言

首先看下需要實現的效果圖
這裡寫圖片描述
螢幕是橫屏的,每個item點選後滑到中間,再次點選之後就跳轉,同時滑動也會有選中的狀態

首先看到這個效果,很多人會說,這還不簡單,不就是一個畫廊效果嗎,用viewpager簡單實現。
加個父佈局,設定一下android:clipChildren=”false”不就搞定了嗎,是的,這樣可以實現這樣的效果,但是功能卻滿足不了,這個功能指的是item的點選事件
首先看下viewpager實現這個關鍵的程式碼

   class ViewpagerAdapter extends PagerAdapter {
        ImageView ivPortrait;
        @Override
        public Object instantiateItem(ViewGroup container, final int position) {
            final UserInfo info = mDatas.get(position);
            View view = LayoutInflater.from(LeiDaActivity.this).inflate(R.layout.viewpager_layout, null);
            ivPortrait = (ImageView) view.findViewById(R.id.iv);
            ImageView ivSex = (ImageView) view.findViewById(R.id.iv_sex);
            TextView tvName = (TextView) view.findViewById(R.id.tv_name);
            TextView tvDistance = (TextView) view.findViewById(R.id.tv_distance);
            tvName.setText(info.getName());
            tvDistance.setText(info.getDistance() + "km");
            ivPortrait.setImageResource(info.getPortraitId());
            if (info.getSex()) {
                ivSex.setImageResource(R.drawable.girl);
            } else {
                ivSex.setImageResource(R.drawable.boy);
            }

            ivPortrait.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(LeiDaActivity.this, "這是 " + info.getName() + " >.<", Toast.LENGTH_SHORT).show();
                    Log.d("swt", position+"");
                }
            });
            container.addView(view);
            return view;
        }

這是viewpager的adapter,網上很多人都會把點選事件寫在這裡,其實這是錯誤的,
首先這裡的position是當前例項化view的position
也就是說
這裡寫圖片描述

然後還有一個問題就是,如果你把點選事件寫在這裡,會出現這樣的一個問題

這裡寫圖片描述
圖中紅圈標記的位置也會響應點選事件,不信的同學可以試試,
而且我覺得使用viewpager實現這個效果點選事件是不好處理的,所以我換個思路
接下來我考慮使用recyclerview實現這個效果,item的點選事件是很好處理了,
但是坑的是 我發現

如果當前position是可見的,那麼你點選的話不會有滑動效果(recyclerview)

也就是scroll不會執行,
呵呵呵呵,那麼這個我也放棄了。最後我決定用最原始的控制元件
gallery來實現,至於效果,那就自己寫

xml 佈局

xml佈局很簡單直接上程式碼了,上面之所以要保留一個LinearLayout是專案需要,我還需要放置一些控制元件在頂部,大家可以忽略

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="cn.primedu.m.hualang.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipChildren="false"
        android:layout_weight="3">

        <Gallery
            android:id="@+id/gallery"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:spacing="50dp"
            />

    </LinearLayout>
</RelativeLayout>

解釋一下android:spacing=”50dp”,這個是控制每個item的邊距,因為我是橫屏的介面,所以我設定的比較大

ps:橫屏設定  <activity android:name=".MainActivity" android:screenOrientation="landscape">

java檔案

   mGallery = (Gallery) findViewById(R.id.gallery);
        BaseAdapter adapter = new BaseAdapter() {
            @Override
            public int getCount() {
                return mImgs.length;
            }

            @Override
            public Object getItem(int position) {
                return position;
            }

            @Override
            public long getItemId(int position) {
                return mImgs[position];
            }

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                // 建立一個ImageView
                ImageView imageView = new ImageView(MainActivity.this);
                imageView.setImageResource(mImgs[position % mImgs.length]);
                // 設定ImageView的縮放型別
                imageView.setLayoutParams(new Gallery.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                imageView.setScaleType(ImageView.ScaleType.CENTER);
                          /*  TypedArray typedArray = obtainStyledAttributes(R.styleable.Gallery);
                            imageView.setBackgroundResource(typedArray.getResourceId(android.R.style.theme_#Theme_galleryItemBackground, 0));*/

                return imageView;
            }
        };
        mGallery.setAdapter(adapter);

首先設定一個adapter,那麼介面就出來了,接下來實現效果,
首先選中的view是高亮的,我在原始碼裡發現了這個

  public void setUnselectedAlpha(float unselectedAlpha) {
        mUnselectedAlpha = unselectedAlpha;
    }

設定沒有被選中的view的透明度
mGallery.setUnselectedAlpha(0.5f);
所以我設定他為半透明
接下來設定點選事件,gallery幫我們已經做好了點選事件

    mGallery.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (position == defaultpostion) {
                    Toast.makeText(MainActivity.this, "跳轉", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(MainActivity.this, "當前點選的是" + position, Toast.LENGTH_SHORT).show();
                }
                defaultpostion = position;

            }
        });

設定一個預設的position
當點選之後,進行覆蓋賦值
進行判斷如果點選的position和當前的defaultpostion 一致,那麼就可以跳轉了
mGallery.setSelection(3);
設定初始化的時候選中第三個view
接下來實現選中的效果,縮放和放大
從效果圖可以看到,選中的是放大,沒選中的是不變
當item被滑動或者被點選的時候都會呼叫這個方法
mGallery.setOnItemSelectedListener(this);//設定好監聽,mainactiivity implements AdapterView.OnItemSelectedListener

  @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

        Log.d("swt", parent.getCount() + "");

        for (int i = 0; i < parent.getChildCount(); i++) {
            parent.getChildAt(i).setScaleX(1);
            parent.getChildAt(i).setScaleY(1);

        }
        view.setScaleX(1.5f);
        view.setScaleY(1.5f);

    }

在監聽中我們做了倆件事
1,首先初始化所有的item的放大,縮小比例為1
2,設定選中的view方法1.5倍

好了,到這裡就結束了,功能看起來很簡單,程式碼也不多,但是關於gallery網上的資料比較少,而且為了實現這個功能,踩得坑實現在太多,所以寫下來,給以後要實現類似功能的人一點啟發,如果你有更好的方法實現,歡迎指教

程式碼下載地址http://download.csdn.net/detail/qq_15527709/9823633

相關文章