滑動ListView自動隱藏頁面頭部和底部元素的例子-創(chuàng)新互聯(lián)

完整工程代碼在這:https://github.com/NashLegend/Auto-Hide-ListView

創(chuàng)新互聯(lián)專注于白云鄂企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站建設(shè),商城網(wǎng)站建設(shè)。白云鄂網(wǎng)站建設(shè)公司,為白云鄂等地區(qū)提供建站服務(wù)。全流程定制網(wǎng)站制作,專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

現(xiàn)在很多軟件都有這種滑動列表的時候自動隱藏頁面頭部和底部元素的功能,比如Google+。在剛剛進入Activity的時候,頁面是一個列表,底部有一個view,頭部一個view,當列表向上滑動的時候,隱藏頭尾元素,以顯示更多內(nèi)容,當列表向下滑動的時候,再將頭尾元素拉出來。比如Google+。

剛剛進入時是這個樣子:

滑動ListView自動隱藏頁面頭部和底部元素的例子

再把列表身上一拉,頭尾隱藏,成了這個樣子:

 滑動ListView自動隱藏頁面頭部和底部元素的例子

再往下拉,就會再變回第一張圖的樣子。

這個例子實現(xiàn)的就是這個功能

這個例子里面,MainActivity的布局如下,ToolBar是頂部元素,Button為底部元素。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:headerDividersEnabled="false" />

    <android.support.v7.widget.Toolbar
        android:id="@+id/action_bar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@android:color/holo_blue_light" />

    <Button
        android:id="@+id/footer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="@string/ScrollDown" />
</RelativeLayout>

public class MainActivity extends ActionBarActivity {

    ListView listView;
    Toolbar toolbar;
    View header;
    View footer;
    int touchSlop = 10;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        touchSlop = (int) (ViewConfiguration.get(MainActivity.this).getScaledTouchSlop() * 0.9);//滾動過多少距離后才開始計算是否隱藏/顯示頭尾元素。這里用了默認touchslop的0.9倍。
        listView = (ListView) findViewById(R.id.list_view);
        footer = findViewById(R.id.footer);
        toolbar = (Toolbar) findViewById(R.id.action_bar);
        // 下面這句將這個ToolBar設(shè)置為ActionBar,在這個例子里面,這句其實用不著,但是如果用了這句,就得把Theme設(shè)置為NoActionBar了,無關(guān)這里要說的,具體見上面的鏈接中的Style
        setSupportActionBar(toolbar);
        
        //為這個ListView填充元素。
        String[] str = new String[64];
        for (int i = 0; i < str.length; i++) {
            str[i] = "Android " + i;
        }
        //R.layout.simple_layout是一個TextView,詳見上面的鏈接……
        ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, R.layout.simple_layout, str);
        listView.setAdapter(adapter);
        
        //為ListView添加一個Header,這個Header與ToolBar一樣高。這樣我們可以正確的看到列表中的第一個元素而不被遮住。
        header = new View(MainActivity.this);
        header.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) getResources().getDimension(R.dimen.abc_action_bar_default_height_material)));
        header.setBackgroundColor(Color.parseColor("#00000000"));
        listView.addHeaderView(header);
        
        //為ListView設(shè)置觸摸事件和滾動事件,這是核心
        listView.setOnTouchListener(onTouchListener);
        listView.setOnScrollListener(onScrollListener);
        footer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //為button設(shè)置點擊事件,點擊一次滾動10個item
                listView.smoothScrollByOffset(10);
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    AnimatorSet backAnimatorSet;//這是顯示頭尾元素使用的動畫

    private void animateBack() {
        //先清除其他動畫
        if (hideAnimatorSet != null && hideAnimatorSet.isRunning()) {
            hideAnimatorSet.cancel();
        }
        if (backAnimatorSet != null && backAnimatorSet.isRunning()) {
            //如果這個動畫已經(jīng)在運行了,就不管它
        } else {
            backAnimatorSet = new AnimatorSet();
            //下面兩句是將頭尾元素放回初始位置。
            ObjectAnimator headerAnimator = ObjectAnimator.ofFloat(toolbar, "translationY", toolbar.getTranslationY(), 0f);
            ObjectAnimator footerAnimator = ObjectAnimator.ofFloat(footer, "translationY", footer.getTranslationY(), 0f);
            ArrayList<Animator> animators = new ArrayList<>();
            animators.add(headerAnimator);
            animators.add(footerAnimator);
            backAnimatorSet.setDuration(300);
            backAnimatorSet.playTogether(animators);
            backAnimatorSet.start();
        }
    }

    AnimatorSet hideAnimatorSet;//這是隱藏頭尾元素使用的動畫

    private void animateHide() {
        //先清除其他動畫
        if (backAnimatorSet != null && backAnimatorSet.isRunning()) {
            backAnimatorSet.cancel();
        }
        if (hideAnimatorSet != null && hideAnimatorSet.isRunning()) {
            //如果這個動畫已經(jīng)在運行了,就不管它
        } else {
            hideAnimatorSet = new AnimatorSet();
            ObjectAnimator headerAnimator = ObjectAnimator.ofFloat(toolbar, "translationY", toolbar.getTranslationY(), -toolbar.getHeight());//將ToolBar隱藏到上面
            ObjectAnimator footerAnimator = ObjectAnimator.ofFloat(footer, "translationY", footer.getTranslationY(), footer.getHeight());//將Button隱藏到下面
            ArrayList<Animator> animators = new ArrayList<>();
            animators.add(headerAnimator);
            animators.add(footerAnimator);
            hideAnimatorSet.setDuration(200);
            hideAnimatorSet.playTogether(animators);
            hideAnimatorSet.start();
        }
    }

    View.OnTouchListener onTouchListener = new View.OnTouchListener() {


        float lastY = 0f;
        float currentY = 0f;
        //下面兩個表示滑動的方向,大于0表示向下滑動,小于0表示向上滑動,等于0表示未滑動
        int lastDirection = 0;
        int currentDirection = 0;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    lastY = event.getY();
                    currentY = event.getY();
                    currentDirection = 0;
                    lastDirection = 0;
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (listView.getFirstVisiblePosition() > 0) {
                        //只有在listView.getFirstVisiblePosition()>0的時候才判斷是否進行顯隱動畫。因為listView.getFirstVisiblePosition()==0時,
                        //ToolBar——也就是頭部元素必須是可見的,如果這時候隱藏了起來,那么占位置用了headerview就被用戶發(fā)現(xiàn)了
                        //但是當用戶將列表向下拉露出列表的headerview的時候,應(yīng)該要讓頭尾元素再次出現(xiàn)才對——這個判斷寫在了后面onScrollListener里面……
                        float tmpCurrentY = event.getY();
                        if (Math.abs(tmpCurrentY - lastY) > touchSlop) {//滑動距離大于touchslop時才進行判斷
                            currentY = tmpCurrentY;
                            currentDirection = (int) (currentY - lastY);
                            if (lastDirection != currentDirection) {
                                //如果與上次方向不同,則執(zhí)行顯/隱動畫
                                if (currentDirection < 0) {
                                    animateHide();
                                } else {
                                    animateBack();
                                }
                            }
                            lastY = currentY;
                        }
                    }
                    break;
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP:
                    //手指抬起的時候要把currentDirection設(shè)置為0,這樣下次不管向哪拉,都與當前的不同(其實在ACTION_DOWN里寫了之后這里就用不著了……)
                    currentDirection = 0;
                    lastDirection = 0;
                    break;
            }
            return false;
        }
    };

    

    AbsListView.OnScrollListener onScrollListener = new AbsListView.OnScrollListener() {
    
        //這個Listener其實是用來對付當用戶的手離開列表后列表仍然在滑動的情況,也就是SCROLL_STATE_FLING
        
        int lastPosition = 0;//上次滾動到的第一個可見元素在listview里的位置——firstVisibleItem
        int state = SCROLL_STATE_IDLE;
        
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            //記錄當前列表狀態(tài)
            state = scrollState;
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            if (firstVisibleItem == 0) {
                animateBack();
            }
            if (firstVisibleItem > 0) {
                if (firstVisibleItem > lastPosition && state == SCROLL_STATE_FLING) {
                    //如果上次的位置小于當前位置,那么隱藏頭尾元素
                    animateHide();
                }
                
                //================================
                if (firstVisibleItem < lastPosition && state == SCROLL_STATE_FLING) {
                    //如果上次的位置大于當前位置,那么顯示頭尾元素,其實本例中,這個if沒用
                    //如果是滑動ListView觸發(fā)的,那么,animateBack()肯定已經(jīng)執(zhí)行過了,所以沒有必要
                    //如果是點擊按鈕啥的觸發(fā)滾動,那么根據(jù)設(shè)計原則,按鈕肯定是頭尾元素之一,所以也不需要animateBack()
                    //所以這個if塊是不需要的
                    animateBack();
                }
                //這里沒有判斷(firstVisibleItem == lastPosition && state == SCROLL_STATE_FLING)的情況,
                //但是如果列表中的單個item如果很長的話還是要判斷的,只不過代碼又要多幾行
                //但是可以取巧一下,在觸發(fā)滑動的時候拖動執(zhí)行一下animateHide()或者animateBack()——本例中的話就寫在那個點擊事件里就可以了)
                //BTW,如果列表的滑動純是靠手滑動列表,而沒有類似于點擊一個按鈕滾到某個位置的話,只要第一個if就夠了…
                
            }
            lastPosition = firstVisibleItem;
        }
    };
}

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

當前文章:滑動ListView自動隱藏頁面頭部和底部元素的例子-創(chuàng)新互聯(lián)
當前網(wǎng)址:http://muchs.cn/article42/dhicec.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、做網(wǎng)站、域名注冊Google、電子商務(wù)網(wǎng)站排名

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)