TabLayout + ViewPager + Fragment + SwipeRefreshLayout + RecyclerView
Android開發中,頂欄和底欄的的使用很普遍,處理方法也不少;
本文對主流的 TabLayout + ViewPager + Fragment + SwipeRefreshLayout + RecyclerView方式進行簡要說明;
配置環境
- 首先在gradle中添加依賴(具體版本自行決定):compile ‘com.android.support:design:25.1.0’
自定義TabLayout樣式
- 自定義tab的樣式:
- 在 styles.xml 中添加自定義的style
- 在相應layout中應用到 TabLayout 中
styles.xml
<style name="CustomTabLayout" parent="Widget.Design.TabLayout">
<item name="paddingEnd">dp</item>
<item name="paddingStart">dp</item>
<item name="tabBackground">@color/colorPrimaryDark</item>
<item name="tabContentStart">dp</item>
<item name="tabIndicatorColor">#999900</item>
<item name="tabIndicatorHeight">dp</item>
<item name="tabMode">fixed</item>
<item name="tabPaddingBottom">dp</item>
<item name="tabPaddingEnd">dp</item>
<item name="tabPaddingStart">dp</item>
<item name="tabPaddingTop">dp</item>
<item name="tabSelectedTextColor">#ffcc00</item>
<item name="tabTextAppearance">@style/CustomTabTextAppearance</item>
<item name="tabTextColor">#ffffff</item>
</style>
<!-- 自定義 TabText 的外觀 -->
<style name="CustomTabTextAppearance" parent="TextAppearance.Design.Tab">
<item name="android:textSize">sp</item>
<item name="android:textColor">#006600</item>
<item name="textAllCaps">false</item>
</style>
layout.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.design.widget.TabLayout
android:id="@+id/tl_title"
style="@style/CustomTabLayout" //設定自定義style
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v4.view.ViewPager
android:id="@+id/my_viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v4.view.ViewPager>
</LinearLayout>
具體代碼
- 自定義一個FragmentPagerAdapter:
public class MyViewPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
private String[] titles;
public MyViewPagerAdapter(FragmentManager fm, String[] titles, List<Fragment> fragments) {
super(fm);
this.titles = titles;
this.fragments = fragments;
}
@Override
public Fragment getItem(int arg0) {
return fragments.get(arg0);
}
@Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
@Override
public int getCount() {
return fragments.size();
}
}
- 然後看代碼中的具體使用:
private String[] titles=new String[]{"tab1","tab2"};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
firstPage = new FirstFragment();
secondPage = new SecondFragment();
fragments.add(firstPage);
fragments.add(secondPage);
mViewPager = (ViewPager) findViewById(R.id.my_viewpager);
viewPagerAdapter = new MyViewPagerAdapter(getSupportFragmentManager(), titles, fragments);
mViewPager.setAdapter(viewPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tl_title);
tabLayout.setTabMode(TabLayout.MODE_FIXED);
tabLayout.setupWithViewPager(mViewPager);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
mViewPager.setCurrentItem(tab.getPosition(), true);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
- 再來看看RecyclerView在Fragment中的使用:
- 首先是分割線,官方并沒有封裝分割線,需要自定義(其實也可以不使用分割線,而是使用CardView,效果可能更好):
public class MyDividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
public MyDividerItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable();
a.recycle();
setOrientation(orientation);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
// 繪制間隔
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (mOrientation == VERTICAL_LIST) {
outRect.set(, , , mDivider.getIntrinsicHeight());
} else {
outRect.set(, , mDivider.getIntrinsicWidth(), );
}
}
private void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
/**
* 繪制間隔
*/
private void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = ; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin +
Math.round(ViewCompat.getTranslationY(child));
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
/**
* 繪制間隔
*/
private void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = ; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin +
Math.round(ViewCompat.getTranslationX(child));
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
- 接下來是自定義RecyclerView.Adapter,添加點選事件(因為沒有自帶):
public class SimpleItemAdapter extends RecyclerView.Adapter<SimpleItemAdapter.SimpleItemViewHolder> {
private final Context context;
private List<? extends Map<String, ?>> data;
private OnItemClickListener clickListener;
//Fragment中調用以監聽點選事件,通過RecyclerView.ViewHolder來傳遞
public void setClickListener(OnItemClickListener clickListener) {
this.clickListener = clickListener;
}
//點選事件接口
public static interface OnItemClickListener {
void onClick(View view, int position);
}
public SimpleItemAdapter(Context context, List<? extends Map<String, ?>> data) {
this.context = context;
this.data = data;
}
//友善重新整理資料
public void updateData(List<? extends Map<String, ?>> data) {
this.data = data;
notifyDataSetChanged();
}
@Override
public SimpleItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View itemView = LayoutInflater.from(context).inflate(R.layout.list_first, viewGroup, false);
return new SimpleItemViewHolder(itemView);
}
@Override
public void onBindViewHolder(SimpleItemViewHolder viewHolder, int position) {
viewHolder.status.setBackground(context.getResources().getDrawable((Integer) data.get(position).get("im")));
viewHolder.name.setText((String) data.get(position).get("tv"));
}
@Override
public int getItemCount() {
return (this.data != null) ? this.data.size() : ;
}
final class SimpleItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
//為友善,将layout設為 ImageView + TextView
LinearLayout rootView;
ImageView im;
TextView tv;
SimpleItemViewHolder(View itemView) {
super(itemView);
rootView = (LinearLayout) itemView.findViewById(R.id.root_view);
rootView.setOnClickListener(this);
this.im = (ImageView) itemView.findViewById(R.id.im);
this.tv = (TextView) itemView.findViewById(R.id.tv);
}
//傳遞點選事件
@Override
public void onClick(View view) {
if (clickListener != null) {
clickListener.onClick(itemView, getAdapterPosition());
}
}
}
}
- 在Fragment中處理RecyclerView和SwipeRefreshLayout:
public View initView() {
View view = View.inflate(mActivity, R.layout.fragment_first, null);
//RecyclerView
mRecyclerView = (RecyclerView) view.findViewById(R.id.rv_first);
//添加分割線
mRecyclerView.addItemDecoration(new MyDividerItemDecoration(mActivity, LinearLayoutManager.VERTICAL));
//設定布局
mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
adapter = new SimpleItemAdapter(mActivity, data);
mRecyclerView.setAdapter(adapter);
//監聽點選事件:使用adapter中自定義的點選事件接口
adapter.setClickListener(new SimpleItemAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int position) {
//do something
}
});
//SwipeRefreshLayout
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.sl_first);
//設定樣式
mSwipeRefreshLayout.setColorSchemeResources(R.color.lightblue, R.color.lightpink, R.color.orange, R.color.lightgreen);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
public void onRefresh() {
refreshData();
}
});
}