效果圖如下:
ViewPager+Fragment添加一行若幹小紅球滾動訓示器訓示目前ViewPager翻閱位置(可供第三方使用的類)。
類似現在通用的新聞用戶端頭部,會放置幾張圖檔供新聞閱讀者翻閱,同時放置一行小圓球根據使用者翻閱的位置相應的滾動,辨別出目前第幾頁。
該項目開放出幾個用以重載的方法函數供第三方使用:
protected Fragment getFragmentAt(int pos) {
return null;
}
protected int getItemsCount() {
return 0;
}
protected String getDescriptionAt(int pos){
return null;
}
測試用的主MainActivity.java (不是重點,僅僅用以測試)
package zhangphil.viewpager_fragment;
import java.util.ArrayList;
import java.util.Random;
import com.example.viewpager_fragment.R;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Fragment newFragment = new HowToUseThisView();
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.fragment, newFragment);
transaction.commit();
}
public static class HowToUseThisView extends
ViewPagerAndFragmentWithCircleIndicator {
private ArrayList<Fragment> mArrayList;
// 主要用以标記Fragment,沒特别意義
private int id = 0;
// ViewPager的元素個數。
private int item_count = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mArrayList = new ArrayList<Fragment>();
// 測試用的。假設生成随機個數的Fragment。
Random rand = new Random();
item_count = rand.nextInt(10);
}
@Override
protected Fragment getFragmentAt(int pos) {
Fragment fragment = null;
try {
fragment = mArrayList.get(pos);
} catch (Exception e) {
Log.d(this.getClass().getName(), "隊列中不存在,建立新Fragment");
}
if (fragment == null) {
fragment = new TestFragment();
((TestFragment) fragment).setID(id++);
mArrayList.add(fragment);
}
return fragment;
}
@Override
protected int getItemsCount() {
return item_count;
}
@Override
protected String getDescriptionAt(int pos) {
//實際使用過程中,可根據每個不同的Fragment傳回不同的描述文本
return pos + "";
}
}
//
// 僅僅用于測試的Fragment,在ViewPager中加載
//
public static class TestFragment extends Fragment {
private int id = 0;
public void setID(int id) {
this.id = id;
}
public int getID() {
return id;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TextView tv = new TextView(getActivity());
String str = "序号: " + getID();
tv.setTextColor(Color.LTGRAY);
tv.setText(str);
tv.setTextSize(60);
tv.setGravity(Gravity.CENTER);
return tv;
}
}
}
MainActivity.java所要的布局檔案 activity_main.xml :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="@+id/fragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
重點是 ViewPagerAndFragmentWithCircleIndicator.java
package zhangphil.viewpager_fragment;
import com.example.viewpager_fragment.R;
import zhangphil.libs.view.CircleIndicatorView;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class ViewPagerAndFragmentWithCircleIndicator extends Fragment {
private MyFragmentPagerAdapter mPagerAdapter;
private ViewPager mViewPager;
private CircleIndicatorView mCircleIndicatorView;
private TextView circleIndicatorView_TextView;
private Handler handler;
private final int MESSAGE_WHAT_DRAW_CIRCLE = 100;
public void notifyDataSetChanged() {
mPagerAdapter.notifyDataSetChanged();
}
protected Fragment getFragmentAt(int pos) {
return null;
}
protected int getItemsCount() {
return 0;
}
protected String getDescriptionAt(int pos){
return null;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View mView = inflater.inflate(R.layout.viewpager_fragment, null);
mViewPager = (ViewPager) mView.findViewById(R.id.viewpager);
mPagerAdapter = new MyFragmentPagerAdapter(getFragmentManager());
mViewPager.setAdapter(mPagerAdapter);
mViewPager
.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int pos) {
set(pos);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
mCircleIndicatorView = (CircleIndicatorView) mView
.findViewById(R.id.circleIndicatorView);
mCircleIndicatorView.drawCircleView(mPagerAdapter.getCount(), 0);
//初始化紅色小圓球的 位置和文本描述
circleIndicatorView_TextView=(TextView) mView.findViewById(R.id.circleIndicatorView_TextView);
circleIndicatorView_TextView.setText(getDescriptionAt(0));
handler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MESSAGE_WHAT_DRAW_CIRCLE:
mCircleIndicatorView.drawCircleView(mPagerAdapter.getCount(),mViewPager.getCurrentItem());
break;
}
};
};
return mView;
}
private void set(int pos) {
mViewPager.setCurrentItem(pos, true);
circleIndicatorView_TextView.setText(getDescriptionAt(pos));
handler.sendEmptyMessage(MESSAGE_WHAT_DRAW_CIRCLE);
}
private class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int pos) {
return getFragmentAt(pos);
}
@Override
public int getCount() {
return getItemsCount();
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
handler.sendEmptyMessage(MESSAGE_WHAT_DRAW_CIRCLE);
}
}
}
ViewPagerAndFragmentWithCircleIndicator.java需要的布局檔案 viewpager_fragment.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="30dip"
android:orientation="horizontal"
android:layout_gravity="bottom" >
<TextView
android:id="@+id/circleIndicatorView_TextView"
android:layout_width="0dip"
android:layout_height="match_parent"
android:gravity="left"
android:textColor="#FF0000"
android:layout_weight="1"
android:singleLine="true"
android:text="" />
<zhangphil.libs.view.CircleIndicatorView
android:id="@+id/circleIndicatorView"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="0.382"/>
</LinearLayout>
</FrameLayout>
</LinearLayout>
以及用以繪制紅色小圓球的 CircleIndicatorView.java
package zhangphil.libs.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class CircleIndicatorView extends View {
public CircleIndicatorView(Context context, AttributeSet attrs){
super(context, attrs);
}
private int gap=20;//各個橫向排列的小球間距
public void setCirlceGap(int gap){
this.gap=gap;
}
public int getCirlceGap(){
return gap;
}
private int padding=20;
public void setPadding(int padding){
this.padding=padding;
}
public int getPadding(){
return padding;
}
private int circle_normal_radius=5; //普通小球半徑
public void setNormalCircleRadius(int radius){
this.circle_normal_radius=radius;
}
public int getNormalCircleRadius(){
return circle_normal_radius;
}
private int circle_selected_radius=7; //被選擇的小球半徑
public void setSelectedCircleRadius(int radius){
this.circle_selected_radius=radius;
}
public int getSelectedCircleRadius(){
return circle_selected_radius;
}
private int count=0;
public void setCircleCount(int count){
this.count=count;
}
public int getCircleCount(){
return count;
}
private int pos=0;
public void setCircleSelectedPosition(int pos){
this.pos=pos;
}
public int getCircleSelectedPosition(){
return pos;
}
public void drawCircleView(){
this.invalidate();
}
public void drawCircleView(int count,int circleSelectedPosition){
setCircleCount(count);
setCircleSelectedPosition(circleSelectedPosition);
this.invalidate();
}
private int circleSelectedColor=Color.RED;
public void setCircleSelectedColor(int color){
circleSelectedColor=color;
}
public int getCircleSelectedColor(){
return circleSelectedColor;
}
private int circleUnSelectedColor=Color.LTGRAY;
public void setCircleUnSelectedColor(int color){
circleUnSelectedColor=color;
}
public int getCircleUnSelectedColor(){
return circleUnSelectedColor;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint p = new Paint();
p.setAntiAlias(true);
int w=this.getWidth();
int h=this.getHeight();
//因為是自右往左繪制小圓圈,需要轉化pos的位置。
int translate_pos=getCircleCount()-getCircleSelectedPosition()-1;
//如果居中繪制則使用start_x,但需要依次遞加x坐标軸位置值。
//int start_x=(w-(CIRCLE_GAP*(getCircleCount()-1)))/2;
for(int i=0;i<getCircleCount();i++){
int r=getNormalCircleRadius();
if(i==translate_pos){
r=getSelectedCircleRadius();
p.setColor(getCircleSelectedColor());
}
else{
r=getNormalCircleRadius();
p.setColor(getCircleUnSelectedColor());
}
//自右向左繪制。從最右邊往左邊繪制小球
//如果從該自定制的View左邊繪制,直接将 x=0即可。
canvas.drawCircle(w-i*getCirlceGap()-getPadding(), h/2, r, p);
}
}
}