简单的说,代码要实现的是类似于现在通用新闻客户端头部的新闻图片展示。现在的新闻客户端顶部一般放有图片展示区,假设有5张图片,用户可以左右侧滑翻阅,同时提供一行5个红色小圆球(红色小圆球的个数等于图片数目),假设当用户翻到第3张图片时候,红色小圆球也相应的指示到第3位置。自然,图片标题也要设置成相对应于图片的内容。
代码功能简要说明:
(1)一个ViewPager,每个page加载不同的Fragment,整个ViewPager中的Fragment可以动态删除和添加。
(2)当ViewPager在左右侧滑时候,下方的提示和红色小圆球也相应的滑动指示当前的Page在所有Page中位置和标题。
MainActivity.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Fragment newFragment =new ViewPagerWithCircleIndicatorView();
FragmentTransaction transaction =getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment,newFragment);
transaction.commit();
}
}
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>
ViewPagerWithCircleIndicatorView.java 该类是重点。实现ViewPager和红色小圆球指示器。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import zhangphil.libs.view.CircleIndicatorView;
import com.example.viewpager_fragment.R;
import android.graphics.Color;
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.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* @author Phil
*
*/
public class ViewPagerWithCircleIndicatorView extends Fragment {
private MyFragmentPagerAdapter mPagerAdapter;
private ViewPager mViewPager;
private Handler handler;
private final int MESSAGE_WHAT_CHANGED = 100;
private ArrayList<HashMap<String, Object>> mArrayList = null;
private final String FRAGMENT = "fragment_tag";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mArrayList = new ArrayList<HashMap<String, Object>>();
}
@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) {
}
});
final TextView circleIndicatorView_TextView=(TextView)mView.findViewById(R.id.circleIndicatorView_TextView);
final CircleIndicatorView mCircleIndicatorView = (CircleIndicatorView) mView
.findViewById(R.id.circleIndicatorView);
handler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MESSAGE_WHAT_CHANGED:
mCircleIndicatorView.setCircleCount(mPagerAdapter
.getCount());
mCircleIndicatorView.setCircleSelectedPosition(mViewPager
.getCurrentItem());
mCircleIndicatorView.setSelectedCircleRadius(7);
mCircleIndicatorView.setCircleUnSelectedColor(Color.BLUE);
mCircleIndicatorView.drawCircleView();
TestFragment tf=(TestFragment) mArrayList.get(mViewPager.getCurrentItem()).get(FRAGMENT);
String title=tf.getTitle();
circleIndicatorView_TextView.setText(title);
break;
}
};
};
// 初始化,在此,可选
initialization();
// 初始化选择第一项
if (mPagerAdapter.getCount() > 0) {
set(0);
}
return mView;
}
private void initialization() {
// 在这里做初始化工作,如果有指定的Fragment,在此预装载
// Fragment fragment;//创建一个Fragment
// View view;//一个下方选项卡的View
// add(fragment, view);
}
private void add(Fragment fragment) {
HashMap<String, Object> map = new HashMap<String, Object>();
Bundle args = new Bundle();
fragment.setArguments(args);
map.put(FRAGMENT, fragment);
mArrayList.add(map);
}
private final void delete(int pos) {
mArrayList.remove(pos);
mPagerAdapter.notifyDataSetChanged();
}
private void set(int pos) {
mViewPager.setCurrentItem(pos, true);
handler.sendEmptyMessage(MESSAGE_WHAT_CHANGED);
}
private class MyFragmentPagerAdapter extends FragmentStatePagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int pos) {
return (Fragment) mArrayList.get(pos).get(FRAGMENT);
}
@Override
public int getItemPosition(Object object) {
return FragmentPagerAdapter.POSITION_NONE;
}
@Override
public int getCount() {
return mArrayList.size();
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
handler.sendEmptyMessage(MESSAGE_WHAT_CHANGED);
}
}
private Fragment loadFragment() {
return new TestFragment();
}
protected void onActionAdd() {
add(loadFragment());
mPagerAdapter.notifyDataSetChanged();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_add:
onActionAdd();
break;
case R.id.action_dele:
delete(mViewPager.getCurrentItem());
set(mViewPager.getCurrentItem());
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
}
//
// 仅仅用于测试的Fragment,在ViewPager中加载
//
public static class TestFragment extends Fragment {
private final String title = new Random().nextInt(20)+"";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TextView tv = new TextView(getActivity());
String str = "Fragment : "+title+"\n";
for (int i = 0; i < 500; i++)
str = str + i + "--";
tv.setTextColor(Color.LTGRAY);
tv.setText(str);
return tv;
}
public String getTitle(){
return title;
}
}
}
红色小圆球的绘制类:CircleIndicatorView.java
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=padding;
}
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=5; //被选择的小球半径
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();
}
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);
}
}
}
ViewPagerWithCircleIndicatorView.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="0.618"
android:singleLine="true"
android:text="abcdefghijklmnopqrstuvwxyz01234567890123456789" />
<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>
系统的添加、删除菜单需要。res\menu目录下,main.xml,菜单布局文件:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_add"
android:orderInCategory="100"
android:showAsAction="never"
android:title="添加"/>
<item
android:id="@+id/action_dele"
android:orderInCategory="100"
android:showAsAction="never"
android:title="删除"/>
</menu>
效果图: