计步器转载



 

先给出ExpandableListView的一些效果图

\\

先给出ExpandableListViewAdapter的代码:

 

package com.bit.expandablelistview;

import java.util.HashMap;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.TextView;

public class ExpandableListViewAdapter extends BaseExpandableListAdapter {
	private List group;//这是组视图
	private HashMap> child;//这是子视图
	private ExpandableListView listView;//当选择另一个组视图时关闭当前打开的组视图
	private LayoutInflater inflater;//加载布局文件
	private int last;//判断是否打开当前的页面

	public ExpandableListViewAdapter(Context context, List group,
			HashMap> child, ExpandableListView listView) {
		this.group = group;
		this.child = child;
		this.listView = listView;
		this.inflater = LayoutInflater.from(context);
	}

	/**
	 * 对外提供一个借口,当数据改变时调用这个函数
	 * @param group
	 * @param child
	 */
	public void setOnDataChanged(List group,
			HashMap> child) {
		this.group = group;
		this.child = child;
		this.notifyDataSetChanged();

	}

	@Override
	public int getGroupCount() {
		// TODO Auto-generated method stub
		return group.size();
	}

	@Override
	public int getChildrenCount(int groupPosition) {
		List tempList = child.get(group.get(groupPosition));
		if (tempList != null) {
			return tempList.size();
		} else {
			return 0;
		}

	}

	@Override
	public Object getGroup(int groupPosition) {
		// TODO Auto-generated method stub
		return group.get(groupPosition);
	}

	@Override
	public Object getChild(int groupPosition, int childPosition) {
		// TODO Auto-generated method stub
		return child.get(group.get(groupPosition)).get(childPosition);
	}

	@Override
	public long getGroupId(int groupPosition) {
		// TODO Auto-generated method stub
		return groupPosition;
	}

	@Override
	public long getChildId(int groupPosition, int childPosition) {
		// TODO Auto-generated method stub
		return childPosition;
	}

	@Override
	public boolean hasStableIds() {
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * 得到组视图布局文件,对这个进行了优化,可以看到converView是一个Android提供的缓存的对象,如果第一次没有这个布局文件
	 * 就创建一个,如果有的话,直接从convertView得到,不用进行创建,减少内存开销
	 */
	public View getGroupView(int groupPosition, boolean isExpanded,
			View convertView, ViewGroup parent) {
		String groupName = group.get(groupPosition);
		View view;
		TextView name;
		if (convertView == null) {
			view = inflater.inflate(R.layout.group_item, null);
			name = (TextView) view.findViewById(R.id.group_number);
			view.setTag(name);
		} else {
			view = convertView;
			name = (TextView) view.getTag();
		}

		name.setText(groupName);
		return view;
	}

	private class ViewHolder {
		ImageView picture;
		TextView name;
	}

	/**
	 * 得到子视图的布局文件,类似于组视图
	 */
	@Override
	public View getChildView(int groupPosition, int childPosition,
			boolean isLastChild, View convertView, ViewGroup parent) {
		User user = child.get(group.get(groupPosition)).get(childPosition);
		View view;
		ViewHolder viewHolder;

		if (convertView == null) {
			view = inflater.inflate(R.layout.child_item, null);
			viewHolder = new ViewHolder();
			viewHolder.picture = (ImageView) view.findViewById(R.id.pic);
			viewHolder.name = (TextView) view.findViewById(R.id.child_name);
			view.setTag(viewHolder);
		} else {
			view = convertView;
			viewHolder = (ViewHolder) view.getTag();
		}

		viewHolder.name.setText(user.getName());
		viewHolder.picture.setImageResource(user.getPicture());
		return view;
	}

	/**
	 * 设置可以点击子视图
	 */
	@Override
	public boolean isChildSelectable(int groupPosition, int childPosition) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public void onGroupExpanded(int groupPosition) {
		super.onGroupExpanded(groupPosition);
		if (groupPosition != last) {
			listView.collapseGroup(last);
		}
		last = groupPosition;
	}

}

然后给出MainActivity类的代码

 

 

package com.bit.expandablelistview;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.Toast;

public class MainActivity extends Activity implements OnChildClickListener {
	private List group;//这是组视图
	private HashMap> child;//这是子视图
	private ExpandableListView listView;//这是可以扩展的listview
	private ExpandableListViewAdapter adapter;
	//这是子视图要加载的所有图片
	private int pic[] = new int[] { R.drawable.head1, R.drawable.head2,
			R.drawable.head3, R.drawable.head4, R.drawable.head5,
			R.drawable.head6, R.drawable.head7, R.drawable.head8,
			R.drawable.head9, R.drawable.head10 };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		init();
		prepareData();
		showData();
	}

	/**
	 * 显示数据
	 */
	private void showData() {
		if (adapter == null) {
			adapter = new ExpandableListViewAdapter(this, group, child,
					listView);
			listView.setAdapter(adapter);
		} else {
			adapter.setOnDataChanged(group, child);
		}

	}

	/**
	 * 初始化一些参数,设置监听事件
	 */
	private void init() {
		group = new ArrayList();
		child = new HashMap>();
		listView = (ExpandableListView) findViewById(R.id.expandlistview);
		listView.setOnChildClickListener(this);
	}

	/**
	 * 准备测试数据
	 */
	private void prepareData() {
		group.add(第一组);
		group.add(第二组);
		group.add(第三组);
		List users = new ArrayList();
		for (int i = 0; i < 4; i++) {
			User user = new User();
			user.setName(张全蛋 + i);
			user.setPicture(pic[i]);
			users.add(user);
		}
		child.put(group.get(0), users);
		users = new ArrayList();
		for (int i = 4; i < 7; i++) {
			User user = new User();
			user.setName(李铁柱 + i);
			user.setPicture(pic[i]);
			users.add(user);
		}
		child.put(group.get(1), users);
		users = new ArrayList();
		for (int i = 7; i < 10; i++) {
			User user = new User();
			user.setName(唐马儒 + i);
			user.setPicture(pic[i]);
			users.add(user);
		}
		child.put(group.get(2), users);
	

	}

	@Override
	public boolean onChildClick(ExpandableListView parent, View v,
			int groupPosition, int childPosition, long id) {
		//点击显示当前子视图的位置
		Toast.makeText(
				MainActivity.this,
				你点击的是
						+ child.get(group.get(groupPosition))
								.get(childPosition).getName(),
				Toast.LENGTH_SHORT).show();
		return false;
	}
}

大家注意,其中的User类是自己定义的一个类。

 

 

 

 

首先,这是两张今天要实现的效果图:

height=300 height=300

最主要的实现自己写的一个HistogramView的类(柱状图类)

HistogramView的代码如下:

 

package com.example.histogram.widet;



import com.example.changepage1.R;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;


/**
 * 这是重新写的一个柱状图的view
 * Author: 李垭超   email:296777513@qq.com
 * Date: 2015-1-3
 * Time: 下午6:15
 */
public class HistogramView extends View {
	private boolean Text = false;//判断是否在柱状图上显示数字
	private int Height;//控件高度
	private int Width;//控件宽度
	private Bitmap bitmap;//柱状图的样子
	private int mHeight;//柱状图高度
	private int AnimValue;//实现的动画
	private double Progress;

	private Canvas canvas;//画出柱状图的各个属性
	private HistogramAnimation ani;

	public void setText(boolean mText) {
		this.Text = mText;
		invalidate();

	}

	public HistogramView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		ani = new HistogramAnimation();//初始化自定义的动画类
		ani.setDuration(1000);//设置整个动画在1秒内完成
	}

	public HistogramView(Context context, AttributeSet attrs) {
		super(context, attrs);
		ani = new HistogramAnimation();
		ani.setDuration(1000);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		//初始化控件和进度的条相关参数
		Width = w;
		Height = h;
		mHeight = (int) (h * Progress * 0.9);

	}

	@SuppressLint(DrawAllocation)
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		this.canvas = canvas;
		
		Paint paint = new Paint();//设置矩形画笔,设置柱状图的信息
		paint.setAntiAlias(true);
		paint.setStyle(Paint.Style.FILL);
		paint.setTextSize(sp2px(getContext(),12));
		paint.setColor(Color.parseColor(#6DCAEC));


		// 绘制 柱状图的形状 :left,top,right,bottom
		RectF dst = new RectF(0, Height - AnimValue, Width, Height);
		//取出图片,并且转换为bitmap类型
		bitmap = BitmapFactory
				.decodeResource(getResources(), R.drawable.column);

		this.canvas.drawBitmap(bitmap, null, dst, paint);//画出柱状图
		if (Text) {
			if (Progress != 0) {
				this.canvas.drawText((int) (Progress * 10000) + , 0,
						(Height - AnimValue) - 10, paint);
			} else {
				this.canvas.drawText((int) (Progress * 10000) + , 0,
						(Height - AnimValue) - 10, paint);
			}

		}
	}

	/**
	 * 对外提供接口来传进数值
	 * @param Progress
	 */
	public void setProgress(double Progress) {
		if (Progress < 0.03 && Progress != 0) {
			this.Progress = Progress;
			Progress = 0.03;
		}
		this.Progress = Progress;
		this.startAnimation(ani);
	}

	/**
	 * 集成animation的一个动画类
	 * @author 李垭超
	 *
	 */
	private class HistogramAnimation extends Animation {
		@Override
		protected void applyTransformation(float interpolatedTime,
				Transformation t) {
			super.applyTransformation(interpolatedTime, t);
			if (interpolatedTime < 1.0f) {
				AnimValue = (int) (mHeight * interpolatedTime);
			} else {
				AnimValue = mHeight;
			}
			postInvalidate();
		}
	}
	

    public static int sp2px(Context context, float spValue) { 
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 
        return (int) (spValue * fontScale + 0.5f); 
    } 

}

重写FragmentAnalysis类

 

 

package com.example.histogram;

import java.text.SimpleDateFormat;
import java.util.Calendar;

import com.example.changepage1.R;
import com.example.histogram.widet.HistogramView;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import android.annotation.SuppressLint;

import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.Transformation;

import android.widget.TextView;

/**
 * 这是分析七天步数的碎片 Author: 李垭超 email:296777513@qq.com Date: 2015-1-2 Time: 下午2:39
 */
public class FragmentAnalysis extends Fragment implements OnClickListener {
	private HistogramView hv1, hv2, hv3, hv4, hv5, hv6, hv7;// 这是7个条形柱状图

	private TextView day1, day2, day3, day4, day5, day6, day7;// 这是底部显示的一周7天

	private TextView average_step;// 平均步数
	private TextView sum_step;// 总共步数

	private int average = 0;
	private int sum = 0;
	private int average1 = 0;
	private int sum1 = 0;

	private Calendar calendar;// 日期的操作
	private String day;

	private View view;

	private AllAnimation ani;// 设置的动画

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		view = inflater.inflate(R.layout.analysis, container, false);
		return view;
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		init();
		setWeek();
		setProgress();
		view.startAnimation(ani);

	}

	/**
	 * 初始化一些对象
	 */
	private void init() {
		average_step = (TextView) view.findViewById(R.id.average_step);
		sum_step = (TextView) view.findViewById(R.id.sum_step);
		ani = new AllAnimation();// 创建自定义的动画对象
		ani.setDuration(1000);// 设置完成动画的时间为1秒

		calendar = Calendar.getInstance();// 对日期进行实例化,显示当天的日期

		hv1 = (HistogramView) view.findViewById(R.id.map1);
		hv2 = (HistogramView) view.findViewById(R.id.map2);
		hv3 = (HistogramView) view.findViewById(R.id.map3);
		hv4 = (HistogramView) view.findViewById(R.id.map4);
		hv5 = (HistogramView) view.findViewById(R.id.map5);
		hv6 = (HistogramView) view.findViewById(R.id.map6);
		hv7 = (HistogramView) view.findViewById(R.id.map7);

		// 对7个柱状图设置点击时间,可以显示具体的数值
		hv1.setOnClickListener(this);
		hv2.setOnClickListener(this);
		hv3.setOnClickListener(this);
		hv4.setOnClickListener(this);
		hv5.setOnClickListener(this);
		hv6.setOnClickListener(this);
		hv7.setOnClickListener(this);

		// 显示对应的周数
		day1 = (TextView) view.findViewById(R.id.Monday);
		day2 = (TextView) view.findViewById(R.id.Tuesday);
		day3 = (TextView) view.findViewById(R.id.Wednesday);
		day4 = (TextView) view.findViewById(R.id.Thursday);
		day5 = (TextView) view.findViewById(R.id.Friday);
		day6 = (TextView) view.findViewById(R.id.Saturday);
		day7 = (TextView) view.findViewById(R.id.Sunday);

	}

	@SuppressLint(SimpleDateFormat)
	private void setProgress() {
		SimpleDateFormat sdf = new SimpleDateFormat(yyyyMMdd);
		day = sdf.format(calendar.getTime());
		// Toast.makeText(getActivity(), day + , Toast.LENGTH_LONG).show();
		hv1.setProgress((5000 / 10000.0));
		sum += 5000;

		calendar.add(Calendar.DAY_OF_MONTH, -1);//把日期设置成为
		day = sdf.format(calendar.getTime());
		hv2.setProgress((3000 / 10000.0));
		sum += 3000;
		// Toast.makeText(getActivity(), day+, Toast.LENGTH_LONG).show();

		calendar.add(Calendar.DAY_OF_MONTH, -1);
		day = sdf.format(calendar.getTime());
		hv3.setProgress((2000 / 10000.0));
		sum += 2000;

		calendar.add(Calendar.DAY_OF_MONTH, -1);
		day = sdf.format(calendar.getTime());
		hv4.setProgress((7631 / 10000.0));
		sum += 7631;

		calendar.add(Calendar.DAY_OF_MONTH, -1);
		day = sdf.format(calendar.getTime());
		hv5.setProgress((4213 / 10000.0));
		sum += 4213;

		calendar.add(Calendar.DAY_OF_MONTH, -1);
		day = sdf.format(calendar.getTime());
		hv6.setProgress((8431/ 10000.0));
		sum += 8431;

		calendar.add(Calendar.DAY_OF_MONTH, -1);
		day = sdf.format(calendar.getTime());
		hv7.setProgress((9999 / 10000.0));
		sum += 9999;

	}

	/**
	 * 设置星期
	 */
	private void setWeek() {

		int day = calendar.get(Calendar.DAY_OF_WEEK);//当天的周数
		// Toast.makeText(getActivity(), day + , Toast.LENGTH_LONG).show();
		day -= 1;
		day1.setText(week(day));
		day2.setText(week(day - 1));
		day3.setText(week(day - 2));
		day4.setText(week(day - 3));
		day5.setText(week(day - 4));
		day6.setText(week(day - 5));
		day7.setText(week(day - 6));
	}

	@Override
	public void onClick(View arg0) {
		switch (arg0.getId()) {
		case R.id.map1:
			hv1.setText(true);
			hv2.setText(false);
			hv3.setText(false);
			hv4.setText(false);
			hv5.setText(false);
			hv6.setText(false);
			hv7.setText(false);
			view.invalidate();
			break;
		case R.id.map2:
			hv1.setText(false);
			hv2.setText(true);
			hv3.setText(false);
			hv4.setText(false);
			hv5.setText(false);
			hv6.setText(false);
			hv7.setText(false);
			view.invalidate();
			break;
		case R.id.map3:
			hv1.setText(false);
			hv2.setText(false);
			hv3.setText(true);
			hv4.setText(false);
			hv5.setText(false);
			hv6.setText(false);
			hv7.setText(false);
			view.invalidate();
			break;
		case R.id.map4:
			hv1.setText(false);
			hv2.setText(false);
			hv3.setText(false);
			hv4.setText(true);
			hv5.setText(false);
			hv6.setText(false);
			hv7.setText(false);
			view.invalidate();
			break;
		case R.id.map5:
			hv1.setText(false);
			hv2.setText(false);
			hv3.setText(false);
			hv4.setText(false);
			hv5.setText(true);
			hv6.setText(false);
			hv7.setText(false);
			view.invalidate();
			break;
		case R.id.map6:
			hv1.setText(false);
			hv2.setText(false);
			hv3.setText(false);
			hv4.setText(false);
			hv5.setText(false);
			hv6.setText(true);
			hv7.setText(false);
			view.invalidate();
			break;
		case R.id.map7:
			hv1.setText(false);
			hv2.setText(false);
			hv3.setText(false);
			hv4.setText(false);
			hv5.setText(false);
			hv6.setText(false);
			hv7.setText(true);
			view.invalidate();
			break;

		default:
			break;
		}

	}

	/**
	 * 将星期由阿拉伯数字变为汉字
	 * @param day
	 * @return
	 */
	private String week(int day) {
		if (day < 1) {
			day += 7;
		}
		switch (day) {
		case 1:
			return 周一;
		case 2:
			return 周二;
		case 3:
			return 周三;
		case 4:
			return 周四;
		case 5:
			return 周五;
		case 6:
			return 周六;
		case 7:
			return 周日;
		default:
			return ;
		}
	}

	/**
	 * 自定义的一个动画类
	 * @author 李垭超
	 *
	 */
	private class AllAnimation extends Animation {
		@Override
		protected void applyTransformation(float interpolatedTime,
				Transformation t) {
			super.applyTransformation(interpolatedTime, t);
			if (interpolatedTime < 1.0f) {
				sum1 = (int) (sum * interpolatedTime);
				average1 = (int) (average * interpolatedTime);
			} else {
				sum1 = sum;
				average1 = average;
			}
			view.postInvalidate();
			sum_step.setText(sum1 + );
			average = sum / 7;
			average_step.setText(average1 + );

		}
	}

}

先给几张效果图:

基于Android的计步器(Pedometer)的讲解(三)--CircleBar(圆形进度条)0基于Android的计步器(Pedometer)的讲解(三)--CircleBar(圆形进度条)1基于Android的计步器(Pedometer)的讲解(三)--CircleBar(圆形进度条)2

如上图所示,点击中间的圆圈会依次显示3个不同的页面(信息),而且圆形的进度条是动态增加的,效果还是可以的。然后给出源代码,供大家参考

CircleBar的主要代码





package com.example.histogram.widet;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
/**
 * 这是继承view的一个重新绘图的圆圈的一个类 Author: liyachao email:296777513@qq.com Date: 2015-1-5
 * Time: 下午2:39
 */
public class CircleBar extends View {

	private RectF mColorWheelRectangle = new RectF();// 圆圈的矩形范围
	private Paint mDefaultWheelPaint;// 绘制底部灰色圆圈的画笔
	private Paint mColorWheelPaint;// 绘制蓝色扇形的画笔
	private Paint textPaint;// 中间文字的画笔
	private Paint textPaint1;// 上下文字的画笔
	private float mColorWheelRadius;// 圆圈普通状态下的半径
	private float circleStrokeWidth;// 圆圈的线条粗细
	private float pressExtraStrokeWidth;// 按下状态下增加的圆圈线条增加的粗细
	private int mText;// 中间文字内容
	private int mCount;// 为了达到数字增加效果而添加的变量,他和mText其实代表一个意思
	private float mProgressAni;// 为了达到蓝色扇形增加效果而添加的变量,他和mProgress其实代表一个意思
	private float mProgress;// 扇形弧度
	private int mTextSize;// 中间文字大小
	private int mTextSize1;// 上下文字大小
	private int mDistance;// 上下文字的距离
	BarAnimation anim;// 动画类
	private int mType;// 根据传入的数值判断应该显示的页面

	public CircleBar(Context context) {
		super(context);
		init();
	}

	public CircleBar(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public CircleBar(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	private void init() {

		circleStrokeWidth = dip2px(getContext(), 20);// 圆圈的线条粗细
		pressExtraStrokeWidth = dip2px(getContext(), 2);// 按下状态下增加的圆圈线条增加的粗细
		mTextSize = dip2px(getContext(), 80);// 中间文字大小
		mTextSize1 = dip2px(getContext(), 30);// 上下文字大小
		mDistance = dip2px(getContext(), 70);//文字间的距离

		// 绘制蓝色扇形的画笔
		mColorWheelPaint = new Paint();
		mColorWheelPaint.setAntiAlias(true);// 抗锯齿
		mColorWheelPaint.setColor(0xFF29a6f6);// 设置颜色
		mColorWheelPaint.setStyle(Paint.Style.STROKE);// 设置空心
		mColorWheelPaint.setStrokeWidth(circleStrokeWidth);// 设置圆圈粗细

		// 绘制底部灰色圆圈的画笔
		mDefaultWheelPaint = new Paint();
		mDefaultWheelPaint.setAntiAlias(true);
		mDefaultWheelPaint.setColor(Color.parseColor("#d9d6c3"));
		mDefaultWheelPaint.setStyle(Paint.Style.STROKE);
		mDefaultWheelPaint.setStrokeWidth(circleStrokeWidth);

		// 中间文字的画笔
		textPaint = new Paint(Paint.LINEAR_TEXT_FLAG);
		textPaint.setAntiAlias(true);
		textPaint.setColor(Color.parseColor("#6DCAEC"));
		textPaint.setStyle(Style.FILL_AND_STROKE);
		textPaint.setTextAlign(Align.LEFT);
		textPaint.setTextSize(mTextSize);

		// 上下文字的画笔
		textPaint1 = new Paint(Paint.LINEAR_TEXT_FLAG);
		textPaint1.setAntiAlias(true);
		textPaint1.setColor(Color.parseColor("#a1a3a6"));
		textPaint1.setStyle(Style.FILL_AND_STROKE);
		textPaint1.setTextAlign(Align.LEFT);
		textPaint1.setTextSize(mTextSize1);

		// 中间文字内容
		mText = 0;
		// 扇形弧度
		mProgress = 0;

		// 动画类
		anim = new BarAnimation();
		anim.setDuration(1000);

	}

	@SuppressLint("DrawAllocation")
	@Override
	protected void onDraw(Canvas canvas) {
		int halfHeight = getHeight() / 2;
		int halfWidth = getWidth() / 2;
		int radius = halfHeight < halfWidth ? halfHeight : halfWidth;
		// 圆圈的矩形范围 绘制底部灰色圆圈的画笔
		canvas.drawCircle(halfWidth, halfHeight, radius - 20f,
				mDefaultWheelPaint);

		// canvas.drawArc(mColorWheelRectangle, -90, 360, false,
		// mDefaultWheelPaint);
		// 为了达到蓝色扇形增加效果而添加的变量,他和mSweepAngle其实代表一个意思

		// mColorWheelRectangle是绘制蓝色扇形的画笔
		mColorWheelRectangle.top = halfHeight - radius + 20f;
		mColorWheelRectangle.bottom = halfHeight + radius - 20f;
		mColorWheelRectangle.left = halfWidth - radius + 20f;
		mColorWheelRectangle.right = halfWidth + radius - 20f;
		// 根据mProgressAni(角度)画扇形
		canvas.drawArc(mColorWheelRectangle, -90, mProgressAni, false,
				mColorWheelPaint);
		Rect bounds = new Rect();
		String middleText = null;// 中间的文字
		String upText = null;// 上面文字
		String downText = null;// 底部文字

		if (this.mType == 1) {// 第一个页面
			upText = "步数";
			downText = "目标:10000";
			middleText = String.valueOf(mCount);
		} else if (this.mType == 2) {// 第二个页面
			upText = "卡路里";
			downText = "目标:10000";
			middleText = String.valueOf(mCount);
		} else if (this.mType == 3) {// 第三个页面
			upText = "根据自己的需要填写";
			downText = "3";
			middleText = "天气";
		}
		// 中间文字的画笔
		textPaint.getTextBounds(middleText, 0, middleText.length(), bounds);
		// drawText各个属性的意思(文字,x坐标,y坐标,画笔)
		canvas.drawText(middleText, (mColorWheelRectangle.centerX())
				- (textPaint.measureText(middleText) / 2),
				mColorWheelRectangle.centerY() + bounds.height() / 2, textPaint);
		textPaint1.getTextBounds(upText, 0, upText.length(), bounds);
		canvas.drawText(
				upText,
				(mColorWheelRectangle.centerX())
						- (textPaint1.measureText(upText) / 2),
				mColorWheelRectangle.centerY() + bounds.height() / 2
						- mDistance, textPaint1);
		textPaint1.getTextBounds(downText, 0, downText.length(), bounds);
		canvas.drawText(downText, (mColorWheelRectangle.centerX())
				- (textPaint1.measureText(downText) / 2),
				mColorWheelRectangle.centerY() + bounds.height() / 2
						+ mDistance, textPaint1);
	}

	// 测量父布局的大小
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int height = getDefaultSize(getSuggestedMinimumHeight(),
				heightMeasureSpec);
		int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
		int min = Math.min(width, height);
		setMeasuredDimension(min, min);
		mColorWheelRadius = min - circleStrokeWidth - pressExtraStrokeWidth;

		// set方法的参数意思:left,top,right,bottom
		mColorWheelRectangle.set(circleStrokeWidth + pressExtraStrokeWidth,
				circleStrokeWidth + pressExtraStrokeWidth, mColorWheelRadius,
				mColorWheelRadius);
	}

	// 对外的一个接口,用来开启动画
	public void startCustomAnimation() {
		this.startAnimation(anim);
	}

	// 中间的数值
	public void setText(int text) {
		mText = text;
		this.postInvalidate();// 可以用子线程更新视图的方法调用。
	}

	// 设置圆圈的进度和圆圈所显示的第几个页面
	public void setProgress(float progress, int mType) {
		mProgress = progress;
		this.mType = mType;
		this.postInvalidate();// 可以用子线程更新视图的方法调用。
	}

	/**
	 * 继承animation的一个动画类
	 * 
	 * @author liyachao
	 *
	 */
	public class BarAnimation extends Animation {
		/**
		 * Initializes expand collapse animation, has two types, collapse (1)
		 * and expand (0).
		 * 
		 * @param view
		 *            The view to animate
		 * @param type
		 *            The type of animation: 0 will expand from gone and 0 size
		 *            to visible and layout size defined in xml. 1 will collapse
		 *            view and set to gone
		 */
		@Override
		protected void applyTransformation(float interpolatedTime,
				Transformation t) {
			super.applyTransformation(interpolatedTime, t);
			if (interpolatedTime < 1.0f) {
				mProgressAni = interpolatedTime * mProgress;
				mCount = (int) (interpolatedTime * mText);
			} else {
				mProgressAni = mProgress;
				mCount = mText;
			}
			postInvalidate();

		}
	}

	public static int dip2px(Context context, float dipValue) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (dipValue * scale + 0.5f);
	}

}

FragmentPedometer 的代码如下

package com.example.histogram;

import com.example.changepage1.R;
import com.example.histogram.widet.CircleBar;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;

/**
 * 这是记步的碎片
 * Author: 李垭超   email:296777513@qq.com
 * Date: 2015-1-2
 * Time: 下午2:39
 */
public class FragmentPedometer extends Fragment{
	private View view;
	private CircleBar circleBar;
	private int type = 1;//页面类型
	//需要在handler里修改UI
	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			if (type == 1) {
				circleBar.setProgress(270, 1);
				circleBar.setText(1000);
				circleBar.startCustomAnimation();
			} else if (type == 2) {
				circleBar.setProgress(180, 2);
				circleBar.setText(1500);
				circleBar.startCustomAnimation();
			} else if (type == 3) {
				circleBar.setProgress(360, 3);
				circleBar.startCustomAnimation();
			}
		};
	};

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		view = inflater.inflate(R.layout.pedometer, container, false);
		circleBar = (CircleBar) view.findViewById(R.id.circle);

		circleBar.setProgress(270, 1);
		circleBar.setText(1000);
		circleBar.startCustomAnimation();//开启动画
		circleBar.setOnClickListener(new OnClickListener() {
			public void onClick(View view) {
				if (type == 1) {
					type = 2;
				} else if (type == 2) {
					type = 3;
				} else if (type == 3) {
					type = 1;
				}
				Message msg = new Message();
				handler.sendMessage(msg);
			}
		});
		return view;
	}

}

先上几张效果图:(效果和上一篇讲到的CircleBar非常的相似,因为记步功能在后台)

\\

如图所示,能根据你的一些基本参数,来记步。有一个缺点,因为这个是根据感应加速度来计算是否走一步,所以你在原地晃手机,也会记步,不过正常的走路还是挺准确的。

首先给出StepDetector类的代码:

package com.example.histogram.widet;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

/**
 * 这是一个实现了信号监听的记步的类
 * 这是从谷歌找来的一个记步的算法,看不太懂
 * @author Liyachao Date:2015-1-6
 *
 */
public class StepDetector implements SensorEventListener {

	public static int CURRENT_SETP = 0;
	public static float SENSITIVITY = 10; // SENSITIVITY灵敏度
	private float mLastValues[] = new float[3 * 2];
	private float mScale[] = new float[2];
	private float mYOffset;
	private static long end = 0;
	private static long start = 0;
	/**
	 * 最后加速度方向
	 */
	private float mLastDirections[] = new float[3 * 2];
	private float mLastExtremes[][] = { new float[3 * 2], new float[3 * 2] };
	private float mLastDiff[] = new float[3 * 2];
	private int mLastMatch = -1;

	/**
	 * 传入上下文的构造函数
	 * 
	 * @param context
	 */
	public StepDetector(Context context) {
		super();
		int h = 480;
		mYOffset = h * 0.5f;
		mScale[0] = -(h * 0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY * 2)));
		mScale[1] = -(h * 0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));
	}

	//当传感器检测到的数值发生变化时就会调用这个方法
	public void onSensorChanged(SensorEvent event) {
		Sensor sensor = event.sensor;
		synchronized (this) {
			if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

				float vSum = 0;
				for (int i = 0; i < 3; i++) {
					final float v = mYOffset + event.values[i] * mScale[1];
					vSum += v;
				}
				int k = 0;
				float v = vSum / 3;

				float direction = (v > mLastValues[k] ? 1
						: (v < mLastValues[k] ? -1 : 0));
				if (direction == -mLastDirections[k]) {
					// Direction changed
					int extType = (direction > 0 ? 0 : 1); // minumum or
															// maximum?
					mLastExtremes[extType][k] = mLastValues[k];
					float diff = Math.abs(mLastExtremes[extType][k]
							- mLastExtremes[1 - extType][k]);

					if (diff > SENSITIVITY) {
						boolean isAlmostAsLargeAsPrevious = diff > (mLastDiff[k] * 2 / 3);
						boolean isPreviousLargeEnough = mLastDiff[k] > (diff / 3);
						boolean isNotContra = (mLastMatch != 1 - extType);

						if (isAlmostAsLargeAsPrevious && isPreviousLargeEnough
								&& isNotContra) {
							end = System.currentTimeMillis();
							if (end - start > 500) {// 此时判断为走了一步

								CURRENT_SETP++;
								mLastMatch = extType;
								start = end;
							}
						} else {
							mLastMatch = -1;
						}
					}
					mLastDiff[k] = diff;
				}
				mLastDirections[k] = direction;
				mLastValues[k] = v;
			}

		}
	}
	//当传感器的经度发生变化时就会调用这个方法,在这里没有用
	public void onAccuracyChanged(Sensor arg0, int arg1) {

	}

}

下来是后台服务StepService的代码:
package com.example.histogram.widet;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.IBinder;

public class StepService extends Service {
	public static Boolean flag = false;
	private SensorManager sensorManager;
	private StepDetector stepDetector;

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		//这里开启了一个线程,因为后台服务也是在主线程中进行,这样可以安全点,防止主线程阻塞
		new Thread(new Runnable() {
			public void run() {
				startStepDetector();
			}
		}).start();

	}

	private void startStepDetector() {
		flag = true;
		stepDetector = new StepDetector(this);
		sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);//获取传感器管理器的实例
		Sensor sensor = sensorManager
				.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//获得传感器的类型,这里获得的类型是加速度传感器
		//此方法用来注册,只有注册过才会生效,参数:SensorEventListener的实例,Sensor的实例,更新速率
		sensorManager.registerListener(stepDetector, sensor,
				SensorManager.SENSOR_DELAY_FASTEST);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		flag = false;
		if (stepDetector != null) {
			sensorManager.unregisterListener(stepDetector);
		}

	}
}
最后把FragmentPedometer测试页面的代码也给大家,如果大家看过之前的博客,应该知道这是一个碎片。如果没看过,看兴趣的朋友可以看看之前的博文:
package com.example.histogram;

import java.text.SimpleDateFormat;
import java.util.Date;
import com.example.changepage1.R;
import com.example.histogram.widet.CircleBar;
import com.example.histogram.widet.StepDetector;
import com.example.histogram.widet.StepService;
import com.example.histogram.widet.Weather;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;

/**
 * 这是记步的碎片
 * Author: 李垭超   email:296777513@qq.com
 * Date: 2015-1-6
 * Time: 下午8:39
 */
public class FragmentPedometer extends Fragment implements OnClickListener{
	private View view;
	private CircleBar circleBar;
	private int total_step = 0;
	private Thread thread;
	private int Type = 1;
	private int calories = 0;
	private int step_length = 50;
	private int weight = 70;
	private Weather weather;
	private String test;
	private boolean flag = true;// 来判断第三个页面是否开启动画

	@SuppressLint(HandlerLeak)
	Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			total_step = StepDetector.CURRENT_SETP;
			if (Type == 1) {
				circleBar.setProgress(total_step, Type);
			} else if (Type == 2) {
				calories = (int) (weight * total_step * step_length * 0.01 * 0.01);
				circleBar.setProgress(calories, Type);
			} else if (Type == 3) {
				if (flag) {
					circleBar.startCustomAnimation();
					flag = false;
				}
				if (test != null || weather.getWeather() == null) {
					weather.setWeather(正在更新中...);
					weather.setPtime();
					weather.setTemp1();
					weather.setTemp2();
					circleBar.startCustomAnimation();
					circleBar.setWeather(weather);
				} else {
					circleBar.setWeather(weather);
				}

			}

		}

	};


	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		view = inflater.inflate(R.layout.pedometer, container, false);
		init();
		mThread();
		return view;
	}
	private void init() {		
		Intent intent = new Intent(getActivity(), StepService.class);
		getActivity().startService(intent);
		weather = new Weather();
		circleBar = (CircleBar) view.findViewById(R.id.progress_pedometer);
		circleBar.setMax(10000);
		circleBar.setProgress(StepDetector.CURRENT_SETP, 1);
		circleBar.startCustomAnimation();
		circleBar.setOnClickListener(this);

	}
	
	private void mThread() {
		if (thread == null) {

			thread = new Thread(new Runnable() {
				public void run() {
					while (true) {
						try {
							Thread.sleep(500);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						if (StepService.flag) {
							Message msg = new Message();
							handler.sendMessage(msg);
						}
					}
				}
			});
			thread.start();
		}
	}
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.progress_pedometer:
			if (Type == 1) {
				Type = 2;
			} else if (Type == 2) {
				flag = true;
				Type = 3;
			} else if (Type == 3) {
				Type = 1;
			}
			Message msg = new Message();
			handler.sendMessage(msg);
			break;
		default:
			break;
		}
		
	}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值