欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android多個(gè)TAB選項(xiàng)卡切換效果

 更新時(shí)間:2020年04月15日 17:31:36   作者:xueshanhaizi  
這篇文章主要介紹了Android多個(gè)TAB選項(xiàng)卡切換效果的實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

在前一期中,我們做了懸浮頭部的兩個(gè)tab切換和下拉刷新效果,后來(lái)項(xiàng)目中要求改成三個(gè)tab,當(dāng)時(shí)就能估量了一下,如果從之前的改,也不是不可以,但是要互相記住的狀態(tài)就太多了,很容易出現(xiàn)錯(cuò)誤。就決定重新實(shí)現(xiàn)一下這個(gè)效果,為此先寫(xiě)了一個(gè)demo,這期間項(xiàng)目都已經(jīng)又更新了兩個(gè)版本了。demo還木有變成文章。

之前的版本中是采用了一個(gè)可以下拉刷新的listview,之后在listview中添加了兩個(gè)頭部,并且在該布局上的上面用了一個(gè)一模一樣的切換tab,如果沒(méi)有看過(guò)前面版本的,可以看看前一個(gè)版本,Listview多Tab上滑懸浮。

基于上述思路我們先來(lái)看看頁(yè)面布局:main_activity

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

 <android.support.v4.view.ViewPager
 android:id="@+id/pager"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />

 <LinearLayout
 android:id="@+id/header"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="@color/white"
 android:orientation="vertical" >

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

 <TextView
  android:id="@+id/show_event_detail_desc"
  android:layout_width="wrap_content"
  android:layout_height="104dip"
  android:paddingBottom="24dip"
  android:layout_marginLeft="15dip"
  android:layout_marginRight="15dip"
  android:paddingTop="25dip"
  android:text="@string/head_title_desc"
  android:textColor="@color/color_black_333333"
  android:textSize="14sp" />

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

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

 <com.example.refreashtabview.sliding.PagerSlidingTabStrip
  android:id="@+id/show_tabs"
  android:layout_width="match_parent"
  android:layout_height="44dip"
  android:background="@color/white" />
 </LinearLayout>

</RelativeLayout>

頁(yè)面采用了兩層,后面一層為Viewpager,前面為懸浮頭與tab切換,在這大家應(yīng)該都想到了會(huì)怎么樣實(shí)現(xiàn),Viewpager中添加已經(jīng)fragment,每個(gè)fragment里面加入一個(gè)可下拉刷新的Listview,根據(jù)ListView的滑動(dòng)來(lái)控制前一幀頁(yè)面的位置。

來(lái)看看頁(yè)面代碼吧,MainAcitivity.java

public class MainActivity extends ActionBarActivity implements OnPageChangeListener, ScrollTabHolder {

 private PagerSlidingTabStrip tabs;

 private ViewPager viewPager;

 private SlidingPagerAdapter adapter;

 private LinearLayout header;

 private int headerHeight;
 private int headerTranslationDis;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main_activity);
 getHeaderHeight();
 findViews();
 setupPager();
 setupTabs();
 }

 private void findViews() {
 tabs = (PagerSlidingTabStrip) findViewById(R.id.show_tabs);
 viewPager = (ViewPager) findViewById(R.id.pager);
 header = (LinearLayout) findViewById(R.id.header);
 }

 private void getHeaderHeight() {
 headerHeight = getResources().getDimensionPixelSize(R.dimen.max_header_height);
 headerTranslationDis = -getResources().getDimensionPixelSize(R.dimen.header_offset_dis);
 }

 private void setupPager() {
 adapter = new SlidingPagerAdapter(getSupportFragmentManager(), this, viewPager);
 adapter.setTabHolderScrollingListener(this);//控制頁(yè)面上滑
 viewPager.setOffscreenPageLimit(adapter.getCacheCount());
 viewPager.setAdapter(adapter);
 viewPager.setOnPageChangeListener(this);
 }

 private void setupTabs() {
 tabs.setShouldExpand(true);
 tabs.setIndicatorColorResource(R.color.color_purple_bd6aff);
 tabs.setUnderlineColorResource(R.color.color_purple_bd6aff);
 tabs.setCheckedTextColorResource(R.color.color_purple_bd6aff);
 tabs.setViewPager(viewPager);
 }

 @Override
 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
 tabs.onPageScrolled(position, positionOffset, positionOffsetPixels);
 }

 @Override
 public void onPageSelected(int position) {
 tabs.onPageSelected(position);
 reLocation = true;
 SparseArrayCompat<ScrollTabHolder> scrollTabHolders = adapter.getScrollTabHolders();
 ScrollTabHolder currentHolder = scrollTabHolders.valueAt(position);
 if (NEED_RELAYOUT) {
  currentHolder.adjustScroll((int) (header.getHeight() + headerTop));// 修正滾出去的偏移量
 } else {
  currentHolder.adjustScroll((int) (header.getHeight() + ViewHelper.getTranslationY(header)));// 修正滾出去的偏移量
 }
 }

 @Override
 public void onPageScrollStateChanged(int state) {
 tabs.onPageScrollStateChanged(state);
 }

 @Override
 public void adjustScroll(int scrollHeight) {

 }

 private boolean reLocation = false;

 private int headerScrollSize = 0;

 public static final boolean NEED_RELAYOUT = Integer.valueOf(Build.VERSION.SDK).intValue() < Build.VERSION_CODES.HONEYCOMB;

 private int headerTop = 0;

 // 刷新頭部顯示時(shí),沒(méi)有onScroll回調(diào),只有當(dāng)刷新時(shí)會(huì)有
 @Override
 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount,
  int pagePosition) {
 if (viewPager.getCurrentItem() != pagePosition) {
  return;
 }
 if (headerScrollSize == 0 && reLocation) {
  reLocation = false;
  return;
 }
 reLocation = false;
 int scrollY = Math.max(-getScrollY(view), headerTranslationDis);
 if (NEED_RELAYOUT) {
  headerTop = scrollY;
  header.post(new Runnable() {

  @Override
  public void run() {
   Log.e("Main", "scorry1="+ headerTop);
   header.layout(0, headerTop, header.getWidth(), headerTop + header.getHeight());
  }
  });
 } else {
  ViewHelper.setTranslationY(header, scrollY);
 }
 }

 /**
 * 主要算這玩意,PullToRefreshListView插入了一個(gè)刷新頭部,因此要根據(jù)不同的情況計(jì)算當(dāng)前的偏移量</br>
 * 
 * 當(dāng)刷新時(shí): 刷新頭部顯示,因此偏移量要加上刷新頭的數(shù)值 未刷新時(shí): 偏移量不計(jì)算頭部。
 * 
 * firstVisiblePosition >1時(shí),listview中的項(xiàng)開(kāi)始顯示,姑且認(rèn)為每一項(xiàng)等高來(lái)計(jì)算偏移量(其實(shí)只要顯示一個(gè)項(xiàng),向上偏移
 * 量已經(jīng)大于頭部的最大偏移量,因此不準(zhǔn)確也沒(méi)有關(guān)系)
 * 
 * @param view
 * @return
 */
 public int getScrollY(AbsListView view) {
 View c = view.getChildAt(0);
 if (c == null) {
  return 0;
 }
 int top = c.getTop();
 int firstVisiblePosition = view.getFirstVisiblePosition();
 if (firstVisiblePosition == 0) {
  return -top + headerScrollSize;
 } else if (firstVisiblePosition == 1) {
  return -top;
 } else {
  return -top + (firstVisiblePosition - 2) * c.getHeight() + headerHeight;
 }
 }

 // 與onHeadScroll互斥,不能同時(shí)執(zhí)行
 @Override
 public void onHeaderScroll(boolean isRefreashing, int value, int pagePosition) {
 if (viewPager.getCurrentItem() != pagePosition) {
  return;
 }
 headerScrollSize = value;
 if (NEED_RELAYOUT) {
  header.post(new Runnable() {

  @Override
  public void run() {
   Log.e("Main", "scorry="+ (-headerScrollSize));
   header.layout(0, -headerScrollSize, header.getWidth(), -headerScrollSize + header.getHeight());
  }
  });
 }else{
  ViewHelper.setTranslationY(header, -value);
 }
 }

}

解釋一下上面的代碼,界面中后一層為Viewpager,里面加入了多個(gè)fragment,每個(gè)fragment里面占用一個(gè)Listivew,Listview中添加一個(gè)與懸浮頭高度完全一樣的header,這樣可顯示區(qū)域就為能看到的區(qū)域,之后監(jiān)聽(tīng)Listview的onScorll,根據(jù)當(dāng)前顯示的listview的item的高度來(lái)控制前一層的懸浮的位置,這個(gè)地方要注意的時(shí),每次切換tab時(shí),要將當(dāng)前已經(jīng)偏移的位置通知到當(dāng)前切換的tab,比如tab1,向上滑動(dòng),影藏了懸浮頭,當(dāng)從tab1切換到tab2時(shí),這是tab2的位置要向上修正,修正距離為懸浮頭滑出去的距離。其他的部分代碼頁(yè)比較簡(jiǎn)單,看看就可以了,其次開(kāi)源控件PullToRefreshListView中我修改了當(dāng)在刷新時(shí)偏移的距離,當(dāng)改距離通知到界面,這樣在下拉刷新時(shí),將整個(gè)頭部向下偏移

ps:上面的代碼中也看到了,我們針對(duì)了不同的版本采用了不同的動(dòng)畫(huà),這是由于在3.0以前,位移動(dòng)畫(huà)看起來(lái)移動(dòng)了位置,可是實(shí)際上控件還在初始位置,為此要針對(duì)不同的版本處理不同的動(dòng)畫(huà),否則tab上的點(diǎn)擊事件在2.X版本上還是在初始位置。上面的動(dòng)畫(huà)采用了nineold控件,也可以自己寫(xiě),這個(gè)部分動(dòng)畫(huà)還是比較簡(jiǎn)單的。

上面的Viewpager中添加了Fragment,我們來(lái)看看Tab1ListFragment.java

public class Tab1ListFragment extends ScrollTabHolderFragment {

 private PullToRefreshListView listView;

 private View placeHolderView;

 private ArrayAdapter<String> adapter;

 private ArrayList<String> listItems;

 private Handler handler;

 public Tab1ListFragment() {
 this.setFragmentId(PageAdapterTab.PAGE_TAB1.fragmentId);
 }

 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 }

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 return inflater.inflate(R.layout.page_tab_fragment_layout, container, false);
 }

 @Override
 public void onActivityCreated(Bundle savedInstanceState) {
 super.onActivityCreated(savedInstanceState);
 findViews();
 initListView();
 }

 @SuppressLint("InflateParams")
 private void findViews() {
 handler = new Handler(Looper.getMainLooper());
 listView = (PullToRefreshListView) getView().findViewById(R.id.page_tab_listview);
 }

 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 (scrollTabHolder != null) {
   scrollTabHolder.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount, getFragmentId());
  }
  }
 });
 listView.setOnHeaderScrollListener(new OnHeaderScrollListener() {

  @Override
  public void onHeaderScroll(boolean isRefreashing, boolean istop, int value) {
  if (scrollTabHolder != null && istop) {
   scrollTabHolder.onHeaderScroll(isRefreashing, value, getFragmentId());
  }
  }
 });
 }

 private void listViewAddHeader() {
 placeHolderView = new LinearLayout(getActivity());
 AbsListView.LayoutParams params = new LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, getResources()
  .getDimensionPixelSize(R.dimen.max_header_height));
 placeHolderView.setLayoutParams(params);
 listView.getRefreshableView().addHeaderView(placeHolderView);
 }

 protected void listViewLoadData() {
 listItems = new ArrayList<String>();
 for (int i = 1; i <= 50; i++) {
  listItems.add("currnet page: " + (getFragmentId() + 1) + " item --" + i);
 }
 adapter = new ArrayAdapter<String>(getActivity(), R.layout.list_item, android.R.id.text1, listItems);
 listView.setAdapter(adapter);
 loadNews();
 }

 /**
 * 下拉清空舊的數(shù)據(jù)
 */
 private void loadNews() {
 handler.postDelayed(new Runnable() {// 模擬遠(yuǎn)程獲取數(shù)據(jù)

   @Override
   public void run() {
   stopRefresh();
   // listItems.clear();
   // for (int i = 1; i <= 50; i++) {
   // listItems.add("currnet page: " + (getFragmentId() +
   // 1) + " item --" + i);
   // }
   // notifyAdpterdataChanged();
   }
  }, 300);
 }

 private void notifyAdpterdataChanged() {
 if (adapter != null) {
  adapter.notifyDataSetChanged();
 }
 }

 protected void loadOlds() {
 handler.postDelayed(new Runnable() {// 模擬遠(yuǎn)程獲取數(shù)據(jù)

   @Override
   public void run() {
   stopRefresh();
   int size = listItems.size() + 1;
   for (int i = size; i < size + 50; ++i) {
    listItems.add("currnet page: " + (getFragmentId() + 1) + " item --" + i);
   }
   notifyAdpterdataChanged();
   }
  }, 300);
 }

 // PullToRefreshListView 自動(dòng)添加了一個(gè)頭部
 @Override
 public void adjustScroll(int scrollHeight) {
 if (scrollHeight == 0 && listView.getRefreshableView().getFirstVisiblePosition() >= 2) {
  return;
 }
 //Log.d(getTag(), "scrollHeight:" + scrollHeight);
 listView.getRefreshableView().setSelectionFromTop(2, scrollHeight);
// Log.d(getTag(), "getScrollY:" + getScrollY(listView.getRefreshableView()));
// handler.postDelayed(new Runnable() {
//  
//  @Override
//  public void run() {
//  Log.d(getTag(), "getScrollY:" + getScrollY(listView.getRefreshableView()));  
//  }
// }, 5000);
 }

 public int getScrollY(AbsListView view) {
 View c = view.getChildAt(0);
 if (c == null) {
  return 0;
 }
 int top = c.getTop();
 int firstVisiblePosition = view.getFirstVisiblePosition();
 if (firstVisiblePosition == 0) {
  return -top;
 } else if (firstVisiblePosition == 1) {
  return top;
 } else {
  return -top + (firstVisiblePosition - 2) * c.getHeight() + 683;
 }
 }

 protected void updateListView() {
 if (adapter != null) {
  adapter.notifyDataSetChanged();
 }
 }

 protected void stopRefresh() {
 listView.onRefreshComplete();
 }

}

上面代碼中的界面就是xml中包含了一個(gè)PullToRefreshListView,比較簡(jiǎn)單這個(gè)地方就不貼出來(lái)了,我們看到在listViewAddHeader中,這個(gè)地方添加了一個(gè)與懸浮頭等高的頭部,這樣就可以將內(nèi)容區(qū)域給呈現(xiàn)出來(lái),不會(huì)被懸浮頭遮擋,其次在list的listener中我們將onScorll傳到了主界面,這樣Listview滾動(dòng),就可以將當(dāng)前滾動(dòng)的距離計(jì)算出來(lái),修正懸浮頭的距離。

我們?cè)儋N出上面剩下的代碼ScrollTabHolderFragment.java與ScrollTabHolder.java

public abstract class ScrollTabHolderFragment extends Fragment implements ScrollTabHolder {

 private int fragmentId;

 protected ScrollTabHolder scrollTabHolder;

 public void setScrollTabHolder(ScrollTabHolder scrollTabHolder) {
 this.scrollTabHolder = scrollTabHolder;
 }

 @Override
 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount,
  int pagePosition) {
 // nothing
 }

 @Override
 public void onHeaderScroll(boolean isRefreashing, int value, int pagePosition) {

 }

 public int getFragmentId() {
 return fragmentId;
 }

 public void setFragmentId(int fragmentId) {
 this.fragmentId = fragmentId;
 }
}


public interface ScrollTabHolder {

 void adjustScroll(int scrollHeight);

 void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount, int pagePosition);

 void onHeaderScroll(boolean isRefreashing, int value, int pagePosition);
}

最后我們來(lái)看看adaper

public class SlidingPagerAdapter extends FragmentPagerAdapter {

 protected final ScrollTabHolderFragment[] fragments;

 protected final Context context;

 private SparseArrayCompat<ScrollTabHolder> mScrollTabHolders;
 private ScrollTabHolder mListener;

 public int getCacheCount() {
 return PageAdapterTab.values().length;
 }

 public SlidingPagerAdapter(FragmentManager fm, Context context, ViewPager pager) {
 super(fm);
 fragments = new ScrollTabHolderFragment[PageAdapterTab.values().length];
 this.context = context;
 mScrollTabHolders = new SparseArrayCompat<ScrollTabHolder>();
 init(fm);
 }

 private void init(FragmentManager fm) {
 for (PageAdapterTab tab : PageAdapterTab.values()) {
  try {
  ScrollTabHolderFragment fragment = null;

  List<Fragment> fs = fm.getFragments();
  if (fs != null) {
   for (Fragment f : fs) {
   if (f.getClass() == tab.clazz) {
    fragment = (ScrollTabHolderFragment) f;
    break;
   }
   }
  }

  if (fragment == null) {
   fragment = (ScrollTabHolderFragment) tab.clazz.newInstance();
  }

  fragments[tab.tabIndex] = fragment;
  } catch (InstantiationException e) {
  e.printStackTrace();
  } catch (IllegalAccessException e) {
  e.printStackTrace();
  }
 }
 }

 public void setTabHolderScrollingListener(ScrollTabHolder listener) {
 mListener = listener;
 }

 @Override
 public ScrollTabHolderFragment getItem(int pos) {
 ScrollTabHolderFragment fragment = fragments[pos];
 mScrollTabHolders.put(pos, fragment);
 if (mListener != null) {
  fragment.setScrollTabHolder(mListener);
 }
 return fragment;
 }

 public SparseArrayCompat<ScrollTabHolder> getScrollTabHolders() {
 return mScrollTabHolders;
 }

 @Override
 public int getCount() {
 return PageAdapterTab.values().length;
 }

 @Override
 public CharSequence getPageTitle(int position) {
 PageAdapterTab tab = PageAdapterTab.fromTabIndex(position);
 int resId = tab != null ? tab.resId : 0;
 return resId != 0 ? context.getText(resId) : "";
 }

}

SlidingPagerAdapter 繼承自FragmentPagerAdapter,從主界面?zhèn)鬟f了一個(gè)callback,將在callback傳遞給每個(gè)fragment,這樣就將fragment與activity聯(lián)系起來(lái)了。其實(shí)還有很多種方式,比如在fragment的attach中獲取activity中的回調(diào)。上面代碼中還有一個(gè)PageAdapterTab,它又是干什么的吶?來(lái)看看代碼

public enum PageAdapterTab {
 PAGE_TAB1(0, Tab1ListFragment.class, R.string.page_tab1),

 PAGE_TAB2(1, Tab2ListFragment.class, R.string.page_tab2),

 PAGE_TAB3(2, Tab3ListFragment.class, R.string.page_tab3),
 ;

 public final int tabIndex;

 public final Class<? extends Fragment> clazz;

 public final int resId;

 public final int fragmentId;

 private PageAdapterTab(int index, Class<? extends Fragment> clazz, int resId) {
 this.tabIndex = index;
 this.clazz = clazz;
 this.resId = resId;
 this.fragmentId = index;
 }

 public static final PageAdapterTab fromTabIndex(int tabIndex) {
 for (PageAdapterTab value : PageAdapterTab.values()) {
  if (value.tabIndex == tabIndex) {
  return value;
  }
 }

 return null;
 }
}

就是一個(gè)枚舉類(lèi),配置了當(dāng)前要顯示的fragment,這樣以后就要增加就可以只修改改枚舉就ok了

到此整個(gè)工程就結(jié)束了,我們截幾張圖看看效果:

最后在回顧一下,布局為兩層,厚一層為一個(gè)Viewpager,里面包含了多個(gè)fragment,前一層為一個(gè)懸浮頭與切換tab,當(dāng)滑動(dòng)listview時(shí)將當(dāng)前顯示的位置傳遞到主界面,同時(shí)更改主界面的位置。

代碼地址如下:https://github.com/FreeSunny/RefreashTabView

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。

相關(guān)文章

最新評(píng)論