[Android]豎直滑動選擇器WheelView的實現


以下內容為原創,轉載請注明:

來自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3819304.html 

 

公司項目中有這么一個需求,所以需要自己實現下。效果類似android4.0以上原生的DatePicker這種。

這個WheelView控件我已經放在github上了,大家有興趣可以看看,地址:https://github.com/wangjiegulu/WheelView,歡迎Star或者Fork哦!(建庫的時候忘了選ignore了--,所以有些gen什么的直接無視掉,我也懶得改了--)

 

先貼上效果圖:

  

 

講下思路吧,因為這是一個滾動選擇器,所以首先想到的是可以基於ListView或者ScrollView自定義。

剛開始我用的是繼承ListView來實現,把滑動選擇的每個item作為listview中的一個item,然后根據FirstVisiblePosition、LastVisiblePosition來判斷某個item是否在選中的區域,但是后來發現偶爾有時候調用getFirstVisiblePosition和getLastVisiblePosition的結果跟我看到的界面顯示的item並不一致(我是在Adapter中調用的這兩個方法),后來分析可能是因為我調用了scrollTo后沒有刷新adapter的原因吧。

再后來,就打算使用ScrollView來實現了,其中的每個item都是一個View(我這里使用了TextView)。因為這個選中框是在中間的位置,所以剛啟動時第一個item應該需要在中間選中框顯示,所以前面應該使用空白補全。最后一個也是如此,后面也需要空白補全。

在滑動過程中需要實現這種場景:滑動結束后,必須且只有一個item完整顯示在選擇框中。所以我們必須要監聽滾動停止的事件,然后在滾動停止后判斷是不是滿足前面的場景,如果沒有,則需要代碼中實現滾動到正確位置。但是,蛋疼的是,sdk中竟然沒有提供原生的監聽滾動停止的api,然后在網上找了很久,得到的結果是只能另辟蹊徑,使用了stackoverflow一個網友的做法通過主動檢測是否停止滾動的方法去實現(總覺得方法有點坑,額 好吧 但是暫時先用了這個方法)。

思路就講到這里了。

 

使用方式:

/**
 * Author: wangjie
 * Email: tiantian.china.2@gmail.com
 * Date: 7/1/14.
 */
@AILayout(R.layout.main)
public class MainActivity extends AIActivity {
    public static final String TAG = MainActivity.class.getSimpleName();

    private static final String[] PLANETS = new String[]{"Mercury", "Venus", "Earth", "Mars", "Jupiter", "Uranus", "Neptune", "Pluto"};

    @AIView(R.id.main_wv)
    private WheelView wva;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        wva.setOffset(1);
        wva.setItems(Arrays.asList(PLANETS));
        wva.setOnWheelViewListener(new WheelView.OnWheelViewListener() {
            @Override
            public void onSelected(int selectedIndex, String item) {
                Logger.d(TAG, "selectedIndex: " + selectedIndex + ", item: " + item);
            }
        });


    }

    @AIClick({R.id.main_show_dialog_btn})
    public void onClickCallbackSample(View view) {
        switch (view.getId()) {
            case R.id.main_show_dialog_btn:
                View outerView = LayoutInflater.from(context).inflate(R.layout.wheel_view, null);
                WheelView wv = (WheelView) outerView.findViewById(R.id.wheel_view_wv);
                wv.setOffset(2);
                wv.setItems(Arrays.asList(PLANETS));
                wv.setSeletion(3);
                wv.setOnWheelViewListener(new WheelView.OnWheelViewListener() {
                    @Override
                    public void onSelected(int selectedIndex, String item) {
                        Logger.d(TAG, "[Dialog]selectedIndex: " + selectedIndex + ", item: " + item);
                    }
                });

                new AlertDialog.Builder(context)
                        .setTitle("WheelView in Dialog")
                        .setView(outerView)
                        .setPositiveButton("OK", null)
                        .show();

                break;
        }
    }

}

 

注意:這個Demo只是一個臨時解決方案,比較適合選項較少的時候使用,比如選擇性別、星期等。因為里面的買個item都是一個單獨的View,並沒有去實現View的緩存和重用,所以大家這點需要注意下。如果有時間我會完善優化這個代碼,實現View的復用。關於View的復用,大家可以fork后自己嘗試改寫,我講下主要的思路(我的思路,當然不能代表是最優的方案)是:假設,每頁顯示5個item以供選擇,那么剛開始加載時,先生成6個item,其中6個是正常的6個選項所new出來的item,注意!因為每頁顯示5個item,所以第6個item不可見,但是卻已經new出來了,其實可以正常顯示。然后往下滾動時,監聽滾動事件,第6個完全顯示時,這個時候第一個item已經不可見了,所以可以重用該item的view。所以如果往下滾要顯示第7個item時,重用第一個item的view,作為第7個item的view顯示數據。再往下也是一樣。總之,重用當前不可見的item的view給即將顯示的item。

 

注意:項目使用到了一部分注解、日志方面的東西,跟實現WheelView沒關系,但是可以簡化代碼,提高編碼效率

AndroidInject:https://github.com/wangjiegulu/androidInject

AndroidBucket:https://github.com/wangjiegulu/AndroidBucket

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM