第一次发博客,心里有点小激动。
废话不多说,先看效果;
代码结构:
ui:IndicatorFragmentActivity.java
TitleIndicator.java
ViewPagerCompat.java
fragment: BaseFragment.java
FragmentOne.java
FragmentTwo.java
FragmentThree.java
MainActivity.java
别的多的也不一一贴出来,把核心贴出来
/*
* @这个是核心函数,选项卡是用canvas画出来的。所有的invalidate方法均会触发onDraw
* 大意是这样的:当页面滚动的时候,会有一个滚动距离,然后onDraw被触发后,
* 就会在新位置重新画上滚动条(其实就是画线)
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//下面是计算本次滑动的距离
float scroll_x = 0;
if (mTotal != 0) {
mPerItemWidth = getWidth() / mTotal;
int tabID = mSelectedTab;
scroll_x = (mCurrentScroll - ((tabID) * (getWidth() + mViewPager.getPageMargin()))) / mTotal;
} else {
mPerItemWidth = getWidth();
scroll_x = mCurrentScroll;
}
//下面就是如何画线了
Path path = mPath;
path.rewind();
float offset = 0;
float left_x = mSelectedTab * mPerItemWidth + offset + scroll_x;
float right_x = (mSelectedTab + 1) * mPerItemWidth - offset + scroll_x;
float top_y = getHeight() - mFooterLineHeight - mFooterTriangleHeight;
float bottom_y = getHeight() - mFooterLineHeight;
path.moveTo(left_x, top_y + 1f);
path.lineTo(right_x, top_y + 1f);
path.lineTo(right_x, bottom_y + 1f);
path.lineTo(left_x, bottom_y + 1f);
path.close();
canvas.drawPath(path, mPaintFooterTriangle);
}
说完精髓,再说说IndicatorFragmentActivity,包名太占地方了
我就删了
@SuppressWarnings("static-access")
public abstract class IndicatorFragmentActivity extends FragmentActivity implements OnPageChangeListener {
private static final String TAG = "DxFragmentActivity";
public static final String EXTRA_TAB = "tab";
public static final String EXTRA_QUIT = "extra.quit";
protected int mCurrentTab = 0;
protected int mLastTab = -1;
//存放选项卡信息的列表
protected ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
//viewpager adapter
protected MyAdapter myAdapter = null;
//viewpager
protected ViewPager mPager;
//选项卡控件
protected TitleIndicator mIndicator;
public TitleIndicator getIndicator() {
return mIndicator;
}
public class MyAdapter extends FragmentPagerAdapter {
ArrayList<TabInfo> tabs = null;
Context context = null;
public MyAdapter(Context context, FragmentManager fm, ArrayList<TabInfo> tabs) {
super(fm);
this.tabs = tabs;
this.context = context;
}
@Override
public Fragment getItem(int pos) {
Fragment fragment = null;
if (tabs != null && pos < tabs.size()) {
TabInfo tab = tabs.get(pos);
if (tab == null)
return null;
fragment = tab.createFragment();
}
return fragment;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public int getCount() {
if (tabs != null && tabs.size() > 0)
return tabs.size();
return 0;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
TabInfo tab = tabs.get(position);
Fragment fragment = (Fragment) super.instantiateItem(container, position);
tab.fragment = fragment;
return fragment;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(getMainViewResId());
initViews();
//设置viewpager内部页面之间的间距
mPager.setPageMargin(getResources().getDimensionPixelSize(R.dimen.page_margin_width));
//设置viewpager内部页面间距的drawable
mPager.setPageMarginDrawable(R.color.page_viewer_margin_color);
}
@Override
protected void onDestroy() {
mTabs.clear();
mTabs = null;
myAdapter.notifyDataSetChanged();
myAdapter = null;
mPager.setAdapter(null);
mPager = null;
mIndicator = null;
super.onDestroy();
}
private final void initViews() {
// 这里初始化界面
mCurrentTab = supplyTabs(mTabs);
Intent intent = getIntent();
if (intent != null) {
mCurrentTab = intent.getIntExtra(EXTRA_TAB, mCurrentTab);
}
Log.d(TAG, "mTabs.size() == " + mTabs.size() + ", cur: " + mCurrentTab);
myAdapter = new MyAdapter(this, getSupportFragmentManager(), mTabs);
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(myAdapter);
mPager.setOnPageChangeListener(this);
mPager.setOffscreenPageLimit(mTabs.size());
mIndicator = (TitleIndicator) findViewById(R.id.pagerindicator);
mIndicator.init(mCurrentTab, mTabs, mPager);
mPager.setCurrentItem(mCurrentTab);
mLastTab = mCurrentTab;
}
添加选项卡
public void addTabInfo(TabInfo tab) {
mTabs.add(tab);
myAdapter.notifyDataSetChanged();
}
/**
* 从列表添加选项卡
* @param tabs
*/
public void addTabInfos(ArrayList<TabInfo> tabs) {
mTabs.addAll(tabs);
myAdapter.notifyDataSetChanged();
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
mIndicator.onScrolled((mPager.getWidth() + mPager.getPageMargin()) * position + positionOffsetPixels);
}
@Override
public void onPageSelected(int position) {
mIndicator.onSwitched(position);
mCurrentTab = position;
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
mLastTab = mCurrentTab;
}
}
protected TabInfo getFragmentById(int tabId) {
if (mTabs == null) return null;
for (int index = 0, count = mTabs.size(); index < count; index++) {
TabInfo tab = mTabs.get(index);
if (tab.getId() == tabId) {
return tab;
}
}
return null;
}
/**
* 跳转到任意选项卡
* @param tabId 选项卡下标
*/
public void navigate(int tabId) {
for (int index = 0, count = mTabs.size(); index < count; index++) {
if (mTabs.get(index).getId() == tabId) {
mPager.setCurrentItem(index);
}
}
}
@Override
public void onBackPressed() {
finish();
}
/**
* 返回layout id
* @return layout id
*/
protected int getMainViewResId() {
return R.layout.titled_fragment_tab_activity;
}
/**
* 在这里提供要显示的选项卡数据
*/
protected abstract int supplyTabs(List<TabInfo> tabs);
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE");
super.onSaveInstanceState(outState);
}
/**
* 单个选项卡类,每个选项卡包含名字,图标以及提示(可选,默认不显示)
*/
public static class TabInfo implements Parcelable {
private int id;
private int icon;
private String name = null;
public boolean hasTips = false;
public Fragment fragment = null;
public boolean notifyChange = false;
@SuppressWarnings("rawtypes")
public Class fragmentClass = null;
@SuppressWarnings("rawtypes")
public TabInfo(int id, String name, Class clazz) {
this(id, name, 0, clazz);
}
@SuppressWarnings("rawtypes")
public TabInfo(int id, String name, boolean hasTips, Class clazz) {
this(id, name, 0, clazz);
this.hasTips = hasTips;
}
@SuppressWarnings("rawtypes")
public TabInfo(int id, String name, int iconid, Class clazz) {
super();
this.name = name;
this.id = id;
icon = iconid;
fragmentClass = clazz;
}
public TabInfo(Parcel p) {
this.id = p.readInt();
this.name = p.readString();
this.icon = p.readInt();
this.notifyChange = p.readInt() == 1;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setIcon(int iconid) {
icon = iconid;
}
public int getIcon() {
return icon;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public Fragment createFragment() {
if (fragment == null) {
Constructor constructor;
try {
constructor = fragmentClass.getConstructor(new Class[0]);
fragment = (Fragment) constructor.newInstance(new Object[0]);
} catch (Exception e) {
e.printStackTrace();
}
}
return fragment;
}
public static final Parcelable.Creator<TabInfo> CREATOR = new Parcelable.Creator<TabInfo>() {
public TabInfo createFromParcel(Parcel p) {
return new TabInfo(p);
}
public TabInfo[] newArray(int size) {
return new TabInfo[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel p, int flags) {
p.writeInt(id);
p.writeString(name);
p.writeInt(icon);
p.writeInt(notifyChange ? 1 : 0);
}
}
}
`
最后在控制器:
public class MainActivity extends IndicatorFragmentActivity {
public static final int FRAGMENT_ONE = 0;
public static final int FRAGMENT_TWO = 1;
public static final int FRAGMENT_THREE = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected int supplyTabs(List<TabInfo> tabs) {
tabs.add(new TabInfo(FRAGMENT_ONE, getString(R.string.fragment_one),
FragmentOne.class));
tabs.add(new TabInfo(FRAGMENT_TWO, getString(R.string.fragment_two),
FragmentTwo.class));
tabs.add(new TabInfo(FRAGMENT_THREE, getString(R.string.fragment_three),
FragmentThree.class));
return FRAGMENT_ONE;
}
}