软件编程
位置:首页>> 软件编程>> Android编程>> Android Listview多tab上滑悬浮效果

Android Listview多tab上滑悬浮效果

作者:freeCodeSunny  发布时间:2021-07-27 22:06:23 

标签:Android,Listview,tab

样例

       近期要做一个含有两个tab切换页面,两个页面有公共的描述信息区域,两个tab都是listview,可以向上或向下拉动刷新,在页面中部有一个tab切换区域,向上滑动的时候tab区域到顶部后就不在移动,向下拉又重新回到初始位置,先看一样样式图吧!

Android Listview多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 style="@style/horizontal_gray_divider" />

<View style="@style/horizontal_gray_divider" />

</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的代码地址,不要错过。

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com