当前位置: 移动技术网 > IT编程>移动开发>Android > Android Listview多tab上滑悬浮效果

Android Listview多tab上滑悬浮效果

2019年07月24日  | 移动技术网IT编程  | 我要评论

儿女传奇之分身,wqmobile,波光粼粼涟漪诊疗所

样例

       近期要做一个含有两个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 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的代码地址,不要错过。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网