Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Listview多tab上滑懸浮效果

Android Listview多tab上滑懸浮效果

編輯:關於Android編程

樣例

       近期要做一個含有兩個tab切換頁面,兩個頁面有公共的描述信息區域,兩個tab都是listview,可以向上或向下拉動刷新,在頁面中部有一個tab切換區域,向上滑動的時候tab區域到頂部後就不在移動,向下拉又重新回到初始位置,先看一樣樣式圖吧!

整個需求大致如上圖所示,其中上拉刷新和下拉刷新沒有截圖,采用了開源控件PullToRefreshListView來實現這個效果。

實現方式

總體思路,為了簡單不想監控很多手勢問題,因此投機取巧的采用下面的方式來實現,

a. 整個頁面是一個listview,公共的區域作為listview的header添加進來,兩個切換的tab也作為一個header加入,
b. 在頁面布局的時候在listview上面添加一層,裡面放tab的布局,這個tab的布局與listview的header中的是同一個布局,
c. 之後當listview滑動時候在onScroll函數中處理頁面tab布局的顯示與隱藏,當listview的tab布局到達屏幕頂部時,顯示頁面中的tab布局,向下滑動當整個tab都出現是影藏界面中的tab布局
d. tab切換,由於tab1,tab2的數據不同,因此采用了三個數據源,在tab切換的時候,數據來回切換,當點擊tab時,記住當前顯示的tab的pos和偏移量(只記住pos重定位的時候會有偏差)

demo的大致流程就是這樣了,沒有添加刷新的處理,雖然實際項目中時處理了更多的邏輯,但是demo不想寫太復雜(主要是沒有人看,就自己看,稍稍寫寫)。

說了這麼多,可能看的人的還是不怎麼明白,下面就來看代碼吧

首先是界面布局,底層一個listview,頂部一個tab布局,界面布局up_float_first_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:background="@color/white_color" >

  <com.example.toolbox.upFloat.PullToRefreshListView
    xmlns:ptr="http://schemas.android.com/apk/res-auto"
    android:id="@+id/up_float_listview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:cacheColorHint="@color/white_color"
    android:divider="@color/transpant"
    android:dividerHeight="0dip"
    android:fadingEdge="none"
    android:fastScrollEnabled="false"
    android:listSelector="@color/transpant"
    android:smoothScrollbar="true"
    android:visibility="visible"
    ptr:ptrHeaderTextColor="@color/color_333333"
    ptr:ptrMode="both" />

  <include
    layout="@layout/up_float_tab_layout"
    android:visibility="gone" />

</FrameLayout>

tab布局,up_float_tab_layout.xml,text都采用了selector,這樣在選中時可以高亮顯示

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/up_float_tab_root"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:background="@color/white_color"
  android:minHeight="44dip"
  android:orientation="vertical" >

  <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="44dip"
    android:minHeight="44dip"
    android:orientation="horizontal" >

    <TextView
      android:id="@+id/up_fload_tab1"
      android:layout_width="0dip"
      android:layout_height="match_parent"
      android:layout_weight="1"
      android:background="@drawable/show_event_detail_tab_selector"
      android:gravity="center"
      android:text="@string/up_float_tab1"
      android:textColor="@color/show_event_detail_tab_text_selector"
      android:textSize="17sp" />

    <TextView
      android:id="@+id/up_float_tab2"
      android:layout_width="0dip"
      android:layout_height="match_parent"
      android:layout_weight="1"
      android:background="@drawable/show_event_detail_tab_selector"
      android:gravity="center"
      android:text="@string/up_float_tab2"
      android:textColor="@color/show_event_detail_tab_text_selector"
      android:textSize="17sp" />
  </LinearLayout>

  <View
    android:layout_width="match_parent"
    android:layout_height="@dimen/split_one_pixels"
    android:background="@color/color_purple_bd6aff" />

</LinearLayout>

公共部分布局up_float_common_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:background="@color/white_color"
  android:orientation="vertical" >

  <ImageView
    android:id="@+id/show_event_detail_bg"
    android:layout_width="fill_parent"
    android:layout_height="125dip"
    android:contentDescription="@string/empty"
    android:scaleType="fitXY"
    android:src="@drawable/pic1" />

  <TextView
    android:id="@+id/show_event_detail_desc"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="24dip"
    android:layout_marginLeft="15dip"
    android:layout_marginRight="15dip"
    android:layout_marginTop="24dip"
    android:text="@string/up_float_desc"
    android:textColor="@color/color_black_333333"
    android:textSize="14sp" />

  <View  />

  <View  />

</LinearLayout>

接下來就是主頁面的代碼了

package com.example.toolbox.upFloat.activity;

import java.util.ArrayList;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.example.toolbox.R;
import com.example.toolbox.upFloat.PullToRefreshBase;
import com.example.toolbox.upFloat.PullToRefreshBase.OnRefreshListener2;
import com.example.toolbox.upFloat.PullToRefreshListView;

/**
 * 
 * 
 * @author sunyoujun
 * 
 */
public class UpFloatFirstActivity extends ActionBarActivity implements OnClickListener {

  public static final int TYPE_TAB_1 = 1;

  public static final int TYPE_TBA_2 = 2;

  private int tab2Pos = 0;
  private int tab2OffsetY = 0;

  private int tab1Pos = 0;
  private int tab1OffsetY = 0;

  private ArrayList<String> item = new ArrayList<String>();
  private ArrayList<String> item1 = new ArrayList<String>();
  private ArrayList<String> item2 = new ArrayList<String>();

  protected PullToRefreshListView listView;

  private LinearLayout titleView;

  private LayoutInflater infater;

  private LinearLayout titleTab;
  private LinearLayout titleFloatTab;

  private TextView latestTv;
  private TextView latestFloatTv;

  private TextView hotTv;
  private TextView hotFloatTv;

  private int currentType = TYPE_TAB_1;

  private ArrayAdapter<String> adapter;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.up_float_first_activity);
    findViews();
    setViewsListener();
    updateTabSelectState();
    initData();
    initListView();
  }

  private void findViews() {
    listView = (PullToRefreshListView) findViewById(R.id.up_float_listview);
    titleFloatTab = (LinearLayout) findViewById(R.id.up_float_tab_root);
    latestFloatTv = (TextView) titleFloatTab.findViewById(R.id.up_float_tab2);
    hotFloatTv = (TextView) titleFloatTab.findViewById(R.id.up_fload_tab1);

    infater = LayoutInflater.from(this);
    titleView = (LinearLayout) infater.inflate(R.layout.up_float_common_layout, null);

    titleTab = (LinearLayout) infater.inflate(R.layout.up_float_tab_layout, null);
    latestTv = (TextView) titleTab.findViewById(R.id.up_float_tab2);
    hotTv = (TextView) titleTab.findViewById(R.id.up_fload_tab1);
  }

  private void setViewsListener() {
    latestTv.setOnClickListener(this);
    hotTv.setOnClickListener(this);
    latestFloatTv.setOnClickListener(this);
    hotFloatTv.setOnClickListener(this);
    updateTabSelectState();
  }

  /**
   * 更新tab欄選中狀態
   */
  private void updateTabSelectState() {
    boolean isTab1 = (currentType == TYPE_TAB_1);
    hotTv.setSelected(isTab1);
    hotFloatTv.setSelected(isTab1);
    latestTv.setSelected(!isTab1);
    latestFloatTv.setSelected(!isTab1);
  }

  private void initData() {
    for (int i = 1; i <= 50; i++) {
      item1.add("tab1-- item ---" + i);
      item2.add("tab2-- item ---" + i);
    }
  }

  private void initListView() {
    setListViewListener();
    listViewAddHeader();
    listViewLoadData();
  }

  private void setListViewListener() {
    listView.setOnRefreshListener(new OnRefreshListener2<ListView>() {

      @Override
      public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
        // loadNews();
      }

      @Override
      public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
        // loadOlds();
      }

    });

    listView.setOnScrollListener(new OnScrollListener() {

      @Override
      public void onScrollStateChanged(AbsListView view, int scrollState) {
      }

      @Override
      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if (firstVisibleItem < 2) {// 懸浮tab出現時機,listview含有三個header
          titleFloatTab.setVisibility(View.GONE);
        } else
          titleFloatTab.setVisibility(View.VISIBLE);
        ;
      }
    });
  }

  private void listViewAddHeader() {
    listView.getRefreshableView().addHeaderView(titleView);
    listView.getRefreshableView().addHeaderView(titleTab);
  }

  protected void listViewLoadData() {
    item.clear();
    item.addAll(item1);
    adapter = new ArrayAdapter<String>(this, R.layout.list_item, android.R.id.text1, item);
    listView.setAdapter(adapter);
  }

  @Override
  public void onClick(View v) {
    switch (v.getId()) {
    case R.id.up_fload_tab1:
      switchTabtList(true);
      break;
    case R.id.up_float_tab2:
      switchTabtList(false);
      break;
    default:
      break;
    }
  }

  private void switchTabtList(boolean isTab1) {
    if (isTab1) {
      if (currentType == TYPE_TAB_1) {
        return;// 說明點擊的是相同的活動列表,不用改變
      } else {// tab2 switch tab1
        tab2Pos = listView.getRefreshableView().getFirstVisiblePosition();
        tab2OffsetY = getOffsetY();
        currentType = TYPE_TAB_1;
        item2.clear();
        item2.addAll(item);
        item.clear();
        item.addAll(item1);
      }
    } else {
      if (currentType == TYPE_TBA_2) {
        return;
      } else {// tab1 switch tab2
        tab1Pos = listView.getRefreshableView().getFirstVisiblePosition();
        tab1OffsetY = getOffsetY();
        currentType = TYPE_TBA_2;
        item1.clear();
        item1.addAll(item);
        item.clear();
        item.addAll(item2);
      }
    }
    updateTabSelectState();
    relocationLastPos();
  }

  private int getOffsetY(){
    View view = listView.getRefreshableView().getChildAt(0);
    return view != null ? view.getTop() : 0;
  }

  /**
   * 重新定位到上次的位置
   */
  private void relocationLastPos() {
    if (adapter != null) {
      adapter.notifyDataSetChanged();
    }
    if (currentType == TYPE_TAB_1) {
      listView.post(new Runnable() {

        @Override
        public void run() {
          listView.getRefreshableView().setSelectionFromTop(tab1Pos, tab1OffsetY);
        }
      });
    } else {
      listView.post(new Runnable() {

        @Override
        public void run() {
          listView.getRefreshableView().setSelectionFromTop(tab2Pos, tab2OffsetY);
        }
      });
    }
  }

}

總結:

 a  上面的demo只是實現了向上滑動的效果,其實有很大的局限性,兩個tab的item布局要一致,才能自由切換,其次是兩個tab不能左右滑動
 b  上面的只適合兩個或者一個tab,再多要控制的變量狀態就更多,很容易出錯,並且上面還沒有包含刷新的效果,數據返回時不能僅僅是添加到item,而要判斷刷新tab與當前顯示tab的關系。
 c  看了其他的開源項目,之後如果有時間會寫一個demo,做真正的多個tab,並且能左右切換的效果。

ps: 鑒於還是有很多人要源代碼,我就在下一篇重新實現了現有的方式,並且附上了git的代碼地址,不要錯過。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved