Android Listview上下拉動(dòng)刷新tab滑動(dòng)切換功能
近期要做一個(gè)含有兩個(gè)tab切換頁(yè)面,兩個(gè)頁(yè)面有公共的描述信息區(qū)域,兩個(gè)tab都是listview,可以向上或向下拉動(dòng)刷新,在頁(yè)面中部有一個(gè)tab切換區(qū)域,向上滑動(dòng)的時(shí)候tab區(qū)域到頂部后就不在移動(dòng),向下拉又重新回到初始位置,先看一樣樣式圖吧!
整個(gè)需求大致如上圖所示,其中上拉刷新和下拉刷新沒(méi)有截圖,采用了開(kāi)源控件PullToRefreshListView來(lái)實(shí)現(xiàn)這個(gè)效果。
1、總體思路,為了簡(jiǎn)單不想監(jiān)控很多手勢(shì)問(wèn)題,因此投機(jī)取巧的采用下面的方式來(lái)實(shí)現(xiàn),
a. 整個(gè)頁(yè)面是一個(gè)listview,公共的區(qū)域作為listview的header添加進(jìn)來(lái),兩個(gè)切換的tab也作為一個(gè)header加入,
b. 在頁(yè)面布局的時(shí)候在listview上面添加一層,里面放tab的布局,這個(gè)tab的布局與listview的header中的是同一個(gè)布局,
c. 之后當(dāng)listview滑動(dòng)時(shí)候在onScroll函數(shù)中處理頁(yè)面tab布局的顯示與隱藏,當(dāng)listview的tab布局到達(dá)屏幕頂部時(shí),顯示頁(yè)面中的tab布局,向下滑動(dòng)當(dāng)整個(gè)tab都出現(xiàn)是影藏界面中的tab布局
d. tab切換,由于tab1,tab2的數(shù)據(jù)不同,因此采用了三個(gè)數(shù)據(jù)源,在tab切換的時(shí)候,數(shù)據(jù)來(lái)回切換,當(dāng)點(diǎn)擊tab時(shí),記住當(dāng)前顯示的tab的pos和偏移量(只記住pos重定位的時(shí)候會(huì)有偏差)
demo的大致流程就是這樣了,沒(méi)有添加刷新的處理,雖然實(shí)際項(xiàng)目中時(shí)處理了更多的邏輯,但是demo不想寫(xiě)太復(fù)雜(主要是沒(méi)有人看,就自己看,稍稍寫(xiě)寫(xiě))。
2、說(shuō)了這么多,可能看的人的還是不怎么明白,下面就來(lái)看代碼吧
a. 首先是界面布局,保護(hù)兩層,底層一個(gè)listview,頂部一個(gè)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>
b. tab布局,up_float_tab_layout.xml,text都采用了selector,這樣在選中時(shí)可以高亮顯示
<?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>
c .公共部分布局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 style="@style/horizontal_gray_divider" /> <View style="@style/horizontal_gray_divider" /> </LinearLayout>
d.接下來(lái)就是主頁(yè)面的代碼了
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欄選中狀態(tài) */ 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出現(xiàn)時(shí)機(jī),listview含有三個(gè)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;// 說(shuō)明點(diǎn)擊的是相同的活動(dòng)列表,不用改變 } 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); } }); } } }
總結(jié):
a 上面的demo只是實(shí)現(xiàn)了向上滑動(dòng)的效果,其實(shí)有很大的局限性,兩個(gè)tab的item布局要一致,才能自由切換,其次是兩個(gè)tab不能左右滑動(dòng)
b 上面的只適合兩個(gè)或者一個(gè)tab,再多要控制的變量狀態(tài)就更多,很容易出錯(cuò),并且上面還沒(méi)有包含刷新的效果,數(shù)據(jù)返回時(shí)不能僅僅是添加到item,而要判斷刷新tab與當(dāng)前顯示tab的關(guān)系。
c 看了其他的開(kāi)源項(xiàng)目,之后如果有時(shí)間會(huì)寫(xiě)一個(gè)demo,做真正的多個(gè)tab,并且能左右切換的效果。
ps: 鑒于還是有很多人要源代碼,我就在下一篇重新實(shí)現(xiàn)了現(xiàn)有的方式,并且附上了代碼地址。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家學(xué)習(xí)Android軟件編程有所幫助。
- Android實(shí)現(xiàn)界面左右滑動(dòng)切換功能
- Android App中使用ViewPager+Fragment實(shí)現(xiàn)滑動(dòng)切換效果
- Android開(kāi)發(fā)之使用ViewPager實(shí)現(xiàn)圖片左右滑動(dòng)切換效果
- Android實(shí)現(xiàn)簡(jiǎn)單底部導(dǎo)航欄 Android仿微信滑動(dòng)切換效果
- Android實(shí)現(xiàn)滑動(dòng)屏幕切換圖片
- Android編程實(shí)現(xiàn)ViewPager多頁(yè)面滑動(dòng)切換及動(dòng)畫(huà)效果的方法
- Android實(shí)現(xiàn)微信首頁(yè)左右滑動(dòng)切換效果
- android實(shí)現(xiàn)切換日期左右無(wú)限滑動(dòng)效果
- Android使用TabLayou+fragment+viewpager實(shí)現(xiàn)滑動(dòng)切換頁(yè)面效果
- android?viewflipper實(shí)現(xiàn)左右滑動(dòng)切換顯示圖片
相關(guān)文章
Android編程之界面跳動(dòng)提示動(dòng)畫(huà)效果實(shí)現(xiàn)方法
這篇文章主要介紹了Android編程之界面跳動(dòng)提示動(dòng)畫(huà)效果實(shí)現(xiàn)方法,實(shí)例分析了Android動(dòng)畫(huà)效果的布局及功能相關(guān)實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11Android判斷屏幕是橫屏或是豎屏的簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要介紹了Android判斷屏幕是橫屏或是豎屏的簡(jiǎn)單實(shí)現(xiàn)方法,是Android應(yīng)用開(kāi)發(fā)中常用的功能,需要的朋友可以參考下2014-07-07Android DrawerLayout帶有側(cè)滑功能的布局類(lèi)(2)
這篇文章主要為大家詳細(xì)介紹了Android DrawerLayout帶有側(cè)滑功能的布局類(lèi),感興趣的小伙伴們可以參考一下2016-07-07詳解Android?Flutter如何使用相機(jī)實(shí)現(xiàn)拍攝照片
在app中使用相機(jī)肯定是再平常不過(guò)的一項(xiàng)事情了,相機(jī)肯定涉及到了底層原生代碼的調(diào)用,那么在flutter中如何快速簡(jiǎn)單的使用上相機(jī)的功能呢?一起來(lái)看看吧2023-04-04Android實(shí)現(xiàn)微信右側(cè)頂部下拉對(duì)話框
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)微信右側(cè)頂部下拉對(duì)話框,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12android-使用環(huán)信SDK開(kāi)發(fā)即時(shí)通信功能(附源碼下載)
本篇文章主要介紹了android-使用環(huán)信SDK開(kāi)發(fā)即時(shí)通信功能,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。2016-12-12