ViewPager+Fragment添加一行若干小红球滚动指示器指示当前ViewPager翻阅位置(可供第三方使用的类)

简介: 效果图如下:ViewPager+Fragment添加一行若干小红球滚动指示器指示当前ViewPager翻阅位置(可供第三方使用的类)。

效果图如下:


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);
        }
    } 
}  



相关文章
|
存储 Rust 并行计算
【密码学】一文读懂XTS模式
这篇文章的灵感来源于我偶然翻到的一个某U盘有关磁盘加密的一个介绍(这一篇不是广告蛤), 然后发现这个模式我之前还真没遇到过,因此呢,就学习了一下,就出来了这一篇文章。
6833 0
【密码学】一文读懂XTS模式
|
11月前
|
缓存 算法 关系型数据库
Mysql(3)—数据库相关概念及工作原理
数据库是一个以某种有组织的方式存储的数据集合。它通常包括一个或多个不同的主题领域或用途的数据表。
402 5
Mysql(3)—数据库相关概念及工作原理
|
存储 Kubernetes 容器
Kubernetes 存储选项:持久化卷与存储类
【8月更文第29天】随着容器化的普及,越来越多的应用程序需要持久化数据以保持状态信息。Kubernetes 提供了一套完整的解决方案来管理和配置持久化存储,包括持久卷 (Persistent Volume, PV)、持久卷声明 (Persistent Volume Claim, PVC) 和存储类 (StorageClass)。本文将详细介绍这些概念,并通过实际示例来演示如何在 Kubernetes 中配置存储。
821 2
|
10月前
|
机器学习/深度学习 人工智能 安全
TPAMI:安全强化学习方法、理论与应用综述,慕工大、同济、伯克利等深度解析
【10月更文挑战第27天】强化学习(RL)在实际应用中展现出巨大潜力,但其安全性问题日益凸显。为此,安全强化学习(SRL)应运而生。近日,来自慕尼黑工业大学、同济大学和加州大学伯克利分校的研究人员在《IEEE模式分析与机器智能汇刊》上发表了一篇综述论文,系统介绍了SRL的方法、理论和应用。SRL主要面临安全性定义模糊、探索与利用平衡以及鲁棒性与可靠性等挑战。研究人员提出了基于约束、基于风险和基于监督学习等多种方法来应对这些挑战。
280 2
|
10月前
|
存储 NoSQL PHP
PHP与Redis结合使用,提升数据存储性能
随着互联网应用的发展,PHP与Redis的结合成为提升数据存储性能的重要手段。PHP作为流行的服务器端语言,常用于网站开发;Redis作为高性能内存数据库,以其快速读写能力,有效优化数据访问速度,减轻数据库压力。两者结合通过缓存机制显著提升应用响应速度,支持高并发场景下的稳定性和可扩展性。
|
机器学习/深度学习 数据采集 数据可视化
机器学习 —— 分类预测与集成学习(上)
机器学习 —— 分类预测与集成学习
257 2
|
人工智能 达摩院 计算机视觉
《阿里云AI产品必知必会系列电子书》——阿里云视觉智能开放平台——人脸识别QuickStart使用教程(上)
《阿里云AI产品必知必会系列电子书》——阿里云视觉智能开放平台——人脸识别QuickStart使用教程(上)
1117 0
|
机器学习/深度学习 存储 人工智能
长时序建模问题新解,斩获ACM MM
ACMMM(ACM International Conference on Multimedia, 国际多媒体会议)是ACM多媒体领域的顶级会议,也是中国计算机学会推荐的A类国际学术会议,每年举办一次。其接收的论文覆盖了多媒体、多媒体检索、机器学习、人工智能、视觉、数据科学、HCI、多媒体信号处理以及医疗保健、教育、娱乐等多个领域的众多研究方向。
635 0
|
域名解析 存储 缓存
2020-2021 IETF DNS技术热点分析
域名系统(DNS)是互联网基础服务和协议,为互联网服务及资源名称(域名)和IP地址两种标识符体系之间的衔接转换,为互联网可扩展性,应用部署的灵活性,和业务安全稳定提供了基础能力。进入移动互联网和云平台时代,DNS作为核心网络基础设施的地位也正在得到愈发广泛的认同。IETF是互联网技术权威标准组织,也是DNS技术定制标准的主要阵地。本文将概述过去两年(2020-2021)在IETF DNS技术热点,包括当前DNS技术社群讨论的技术问题,创新想法,话题趋势和方向。
2663 3
2020-2021 IETF DNS技术热点分析
|
数据库 Windows
Axure实战01:快速了解Axure9.0
Axure实战01:快速了解Axure9.0
724 0
Axure实战01:快速了解Axure9.0