欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

基于andoird的计步器(全代码)

程序员文章站 2022-03-14 20:00:33
收集了一些资料整理了一个简单计步器,带简单界面,作课程设计的。网上很多都不能用,或者是项目太大,分享一下自己弄的,帮助一下像我这样的苦孩子。最后贴上了运行结果和目录结构。怎么进行改进就看自己了。权限:

收集了一些资料整理了一个简单计步器,带简单界面,作课程设计的。网上很多都不能用,或者是项目太大,分享一下自己弄的,帮助一下像我这样的苦孩子。最后贴上了运行结果和目录结构。

怎么进行改进就看自己了。

权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.step">
    <!-- 计歩需要的权限 -->
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />

    <uses-feature android:name="android.hardware.sensor.accelerometer" />

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

    <uses-feature
        android:name="android.hardware.sensor.stepcounter"
        android:required="true" />
    <uses-feature
        android:name="android.hardware.sensor.stepdetector"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".WelcomeShow">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".StepView" />
        <activity android:name=".MainActivity"></activity>

        <service
            android:name=".BindService"
            android:enabled="true"
            android:exported="true" />
    </application>

</manifest>

 

创建服务,创建的时候注意是服务,别创成类了!!!

BindService

package com.example.step;

import android.app.Service;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;

public class BindService extends Service implements SensorEventListener {
    /**
     * binder服务与activity交互桥梁
     */
    private LcBinder lcBinder = new LcBinder();
    /**
     * 当前步数
     */
    private int nowBuSu = 0;
    /**
     * 传感器管理对象
     */
    private SensorManager sensorManager;
    /**
     * 加速度传感器中获取的步数
     */
    private StepCount mStepCount;

    /**
     * 数据回调接口,通知上层调用者数据刷新
     */
    private UpdateUiCallBack mCallback;

    /**
     * 计步传感器类型  Sensor.TYPE_STEP_COUNTER或者Sensor.TYPE_STEP_DETECTOR
     */
    private static int stepSensorType = -1;
    /**
     * 每次第一次启动记步服务时是否从系统中获取了已有的步数记录
     */
    private boolean hasRecord = false;
    /**
     * 系统中获取到的已有的步数
     */
    private int hasStepCount = 0;
    /**
     * 上一次的步数
     */
    private int previousStepCount = 0;
    /**
     * 构造函数
     */
    public BindService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("BindService—onCreate", "开启计步");
        new Thread(new Runnable() {
            @Override
            public void run() {
                startStepDetector();
                Log.i("BindService—子线程", "startStepDetector()");
            }
        }).start();
    }

    /**
     * 选择计步数据采集的传感器
     * SDK大于等于19,开启计步传感器,小于开启加速度传感器
     */
    private void startStepDetector() {
        if (sensorManager != null) {
            sensorManager = null;
        }
        //获取传感器管理类
        sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
        int versionCodes = Build.VERSION.SDK_INT;//取得SDK版本
        if (versionCodes >= 19) {
            //SDK版本大于等于19开启计步传感器
            addCountStepListener();
        } else {        //小于就使用加速度传感器
            addBasePedometerListener();
        }
    }

    /**
     * 启动计步传感器计步
     */
    private void addCountStepListener() {
        Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
        Sensor detectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
        if (countSensor != null) {
            stepSensorType = Sensor.TYPE_STEP_COUNTER;
            sensorManager.registerListener(BindService.this, countSensor, SensorManager.SENSOR_DELAY_NORMAL);
            Log.i("计步传感器类型", "Sensor.TYPE_STEP_COUNTER");
        } else if (detectorSensor != null) {
            stepSensorType = Sensor.TYPE_STEP_DETECTOR;
            sensorManager.registerListener(BindService.this, detectorSensor, SensorManager.SENSOR_DELAY_NORMAL);
        } else {
            addBasePedometerListener();
        }
    }

    /**
     * 启动加速度传感器计步
     */
    private void addBasePedometerListener() {
        Log.i("BindService", "加速度传感器");
        mStepCount = new StepCount();
        mStepCount.setSteps(nowBuSu);
        //获取传感器类型 获得加速度传感器
        Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        //此方法用来注册,只有注册过才会生效,参数:SensorEventListener的实例,Sensor的实例,更新速率
        boolean isAvailable = sensorManager.registerListener(mStepCount.getStepDetector(), sensor, SensorManager.SENSOR_DELAY_UI);
        mStepCount.initListener(new StepValuePassListener() {
            @Override
            public void stepChanged(int steps) {
                nowBuSu = steps;//通过接口回调获得当前步数
                updateNotification();    //更新步数通知
            }
        });
    }

    /**
     * 通知调用者步数更新 数据交互
     */
    private void updateNotification() {
        if (mCallback != null) {
            Log.i("BindService", "数据更新");
            mCallback.updateUi(nowBuSu);
        }
    }

    @Override
    public IBinder onBind(Intent intent) {

        return lcBinder;
    }

    /**
     * 计步传感器数据变化回调接口
     */
    @Override
    public void onSensorChanged(SensorEvent event) {
        //这种类型的传感器返回步骤的数量由用户自上次重新启动时激活。返回的值是作为浮动(小数部分设置为0),
        // 只在系统重启复位为0。事件的时间戳将该事件的第一步的时候。这个传感器是在硬件中实现,预计低功率。
        if (stepSensorType == Sensor.TYPE_STEP_COUNTER) {
            //获取当前传感器返回的临时步数
            int tempStep = (int) event.values[0];
            //首次如果没有获取手机系统中已有的步数则获取一次系统中APP还未开始记步的步数
            if (!hasRecord) {
                hasRecord = true;
                hasStepCount = tempStep;
            } else {
                //获取APP打开到现在的总步数=本次系统回调的总步数-APP打开之前已有的步数
                int thisStepCount = tempStep - hasStepCount;
                //本次有效步数=(APP打开后所记录的总步数-上一次APP打开后所记录的总步数)
                int thisStep = thisStepCount - previousStepCount;
                //总步数=现有的步数+本次有效步数
                nowBuSu += (thisStep);
                //记录最后一次APP打开到现在的总步数
                previousStepCount = thisStepCount;
            }
        }
        //这种类型的传感器触发一个事件每次采取的步骤是用户。只允许返回值是1.0,为每个步骤生成一个事件。
        // 像任何其他事件,时间戳表明当事件发生(这一步),这对应于脚撞到地面时,生成一个高加速度的变化。
        else if (stepSensorType == Sensor.TYPE_STEP_DETECTOR) {
            if (event.values[0] == 1.0) {
                nowBuSu++;
            }
        }
        updateNotification();

    }

    /**
     * 计步传感器精度变化回调接口
     */
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    /**
     * 绑定回调接口
     */
    public class LcBinder extends Binder {
        BindService getService() {
            return BindService.this;
        }
    }

    /**
     * 数据传递接口
     */
    public void registerCallback(UpdateUiCallBack paramICallback) {
        this.mCallback = paramICallback;
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        //取消前台进程
        stopForeground(true);

    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
}

 

MainActivity

package com.example.step;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;

import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {
    private BindService bindService;
    private TextView textView;
    private boolean isBind;
    private StepView mStepView;
    private  float ProgressAni;

    private int ST = 0;
    private String AIM ;
    private int mAIM;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {  //创建线程更新view
            if (msg.what == 1) {
              //  STEPVIEW.setText(STEP);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                       // while (true){
                            //mStepView.sleep(1000);
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    ProgressAni = (float)STEP*365/mAIM; //改变蓝条
                                    mStepView.setText(STEP, ProgressAni,AIM);
                                   // mStepView.startCustomAnimation();
                                }
                            });
                      //  }
                    }
                }).start();
            }
        }
    };

    public int STEP;
    private Button start;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Intent intent2 =getIntent();
            Bundle bun = intent2.getExtras();
            AIM = bun.getString("aim");
            mStepView = (StepView) findViewById(R.id.shapeView);
            //Intent intent = new Intent(MainActivity.this, BindService.class);
            //mAIM = Integer.parseInt(AIM);

           // isBind = bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
            //startService(intent);
            Button start =(Button)findViewById(R.id.start);
            start.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(MainActivity.this, R.string.ST, Toast.LENGTH_LONG).show();
                    ST = 1;
                }

            });
    }

    //和绷定服务数据交换的桥梁,可以通过IBinder service获取服务的实例来调用服务的方法或者数据
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            BindService.LcBinder lcBinder = (BindService.LcBinder) service;
                bindService = lcBinder.getService();
                bindService.registerCallback(new UpdateUiCallBack() {
                @Override
                public void updateUi(int stepCount) {
                    //当前接收到stepCount数据,就是最新的步数
                    Message message = Message.obtain();
                    message.what = 1;
                    if(ST == 1) {
                        message.arg1 = stepCount;
                        STEP = stepCount;
                        handler.sendMessage(message);
                        Log.i("MainActivity—updateUi", "当前步数" + stepCount);
                    }
                }
            });

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onStart() {
        super.onStart();
    }
    @Override
    public void onDestroy() {  //app被关闭之前,service先解除绑定
        super.onDestroy();
        if (isBind) {
            this.unbindService(serviceConnection);
        }
    }
}

StepCount

package com.example.step;

import android.util.Log;

/**
 *计步逻辑
 */
public class StepCount implements StepCountListener {
    private int mCount; //当前步数
    private int count;  //缓存步数,步数3秒内小于10步则不计数
    private long timeOfLastPeak = 0;//计时  开始时间 步数3秒内小于10步则不计数
    private long timeOfThisPeak = 0;//计时  现在时间 步数3秒内小于10步则不计数
    private StepValuePassListener stepValuePassListener;//接口用来传递步数变化
    private StepDetector stepDetector;//传感器SensorEventListener子类实例

    public StepCount() {
        stepDetector = new StepDetector();
        stepDetector.initListener(this);
    }



    @Override
    public void countStep() {
        this.timeOfLastPeak = this.timeOfThisPeak;
        this.timeOfThisPeak = System.currentTimeMillis();
        Log.i("countStep","传感器数据刷新回调");
        if (this.timeOfThisPeak - this.timeOfLastPeak <= 3000L) {
            if (this.count < 9) {
                this.count++;
            } else if (this.count == 9) {
                this.count++;
                this.mCount += this.count;
                notifyListener();
            } else {
                this.mCount++;
                notifyListener();
            }
        } else {//超时
            this.count = 1;
        }

    }
    public void setSteps(int initNowBusu){
        this.mCount = initNowBusu;//接收上层调用传递过来的当前步数
        this.count = 0;
        timeOfLastPeak = 0;
        timeOfThisPeak = 0;
        notifyListener();
    }

    /**
     * 用来给调用者获取SensorEventListener实例
     * return 返回SensorEventListener实例
     */
    public StepDetector getStepDetector(){
        return stepDetector;
    }
    /**
     * 更新步数,通过接口函数通知上层调用者
     */
    public void notifyListener(){
        if(this.stepValuePassListener != null){
            Log.i("countStep","数据更新");
            this.stepValuePassListener.stepChanged(this.mCount);  //当前步数通过接口传递给调用者
        }
    }
    public  void initListener(StepValuePassListener listener){
        this.stepValuePassListener = listener;
    }
}

StepCountListener(接口)

package com.example.step;

public interface StepCountListener {
    void countStep();
}

StepDetector

package com.example.step;



import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
/*
 * 算法的主要部分,检测是否是步点
 * */

public class StepDetector implements SensorEventListener {

    //存放三轴数据
    float[] oriValues = new float[3];
    final int ValueNum = 4;
    //用于存放计算阈值的波峰波谷差值
    float[] tempValue = new float[ValueNum];
    int tempCount = 0;
    //是否上升的标志位
    boolean isDirectionUp = false;
    //持续上升次数
    int continueUpCount = 0;
    //上一点的持续上升的次数,为了记录波峰的上升次数
    int continueUpFormerCount = 0;
    //上一点的状态,上升还是下降
    boolean lastStatus = false;
    //波峰值
    float peakOfWave = 0;
    //波谷值
    float valleyOfWave = 0;
    //此次波峰的时间
    long timeOfThisPeak = 0;
    //上次波峰的时间
    long timeOfLastPeak = 0;
    //当前的时间
    long timeOfNow = 0;
    //当前传感器的值
    float gravityNew = 0;
    //上次传感器的值
    float gravityOld = 0;
    //动态阈值需要动态的数据,这个值用于这些动态数据的阈值
    final float InitialValue = (float) 1.3;
    //初始阈值
    float ThreadValue = (float) 2.0;
    //波峰波谷时间差
    int TimeInterval = 250;
    private StepCountListener mStepListeners;

    @Override
    public void onSensorChanged(SensorEvent event) {//当传感器值改变回调此方法
        for (int i = 0; i < 3; i++) {
            oriValues[i] = event.values[i];
        }
        gravityNew = (float) Math.sqrt(oriValues[0] * oriValues[0]
                + oriValues[1] * oriValues[1] + oriValues[2] * oriValues[2]);
        detectorNewStep(gravityNew);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        //
    }

    public void initListener(StepCountListener listener) {
        this.mStepListeners = listener;
    }

    /*
     * 检测步子,并开始计步
     * */
    public void detectorNewStep(float values) {
        if (gravityOld == 0) {
            gravityOld = values;
        } else {
            if (detectorPeak(values, gravityOld)) {
                timeOfLastPeak = timeOfThisPeak;
                timeOfNow = System.currentTimeMillis();
                if (timeOfNow - timeOfLastPeak >= TimeInterval
                        && (peakOfWave - valleyOfWave >= ThreadValue)) {
                    timeOfThisPeak = timeOfNow;
                    mStepListeners.countStep();
                }
                if (timeOfNow - timeOfLastPeak >= TimeInterval
                        && (peakOfWave - valleyOfWave >= InitialValue)) {
                    timeOfThisPeak = timeOfNow;
                    ThreadValue = peakValleyThread(peakOfWave - valleyOfWave);
                }
            }
        }
        gravityOld = values;
    }

    /*
     * 检测波峰
     * 以下四个条件判断为波峰:
     * 1.目前点为下降的趋势:isDirectionUp为false
     * 2.之前的点为上升的趋势:lastStatus为true
     * 3.到波峰为止,持续上升大于等于2次
     * 4.波峰值大于20
     * 记录波谷值
     * 1.观察波形图,可以发现在出现步子的地方,波谷的下一个就是波峰,有比较明显的特征以及差值
     * 2.所以要记录每次的波谷值,为了和下次的波峰做对比
     * */
    public boolean detectorPeak(float newValue, float oldValue) {
        lastStatus = isDirectionUp;
        if (newValue >= oldValue) {
            isDirectionUp = true;
            continueUpCount++;
        } else {
            continueUpFormerCount = continueUpCount;
            continueUpCount = 0;
            isDirectionUp = false;
        }

        if (!isDirectionUp && lastStatus
                && (continueUpFormerCount >= 2 || oldValue >= 20)) {
            peakOfWave = oldValue;
            return true;
        } else if (!lastStatus && isDirectionUp) {
            valleyOfWave = oldValue;
            return false;
        } else {
            return false;
        }
    }

    /*
     * 阈值的计算
     * 1.通过波峰波谷的差值计算阈值
     * 2.记录4个值,存入tempValue[]数组中
     * 3.在将数组传入函数averageValue中计算阈值
     * */
    public float peakValleyThread(float value) {
        float tempThread = ThreadValue;
        if (tempCount < ValueNum) {
            tempValue[tempCount] = value;
            tempCount++;
        } else {
            tempThread = averageValue(tempValue, ValueNum);
            for (int i = 1; i < ValueNum; i++) {
                tempValue[i - 1] = tempValue[i];
            }
            tempValue[ValueNum - 1] = value;
        }
        return tempThread;

    }

    /*
     * 梯度化阈值
     * 1.计算数组的均值
     * 2.通过均值将阈值梯度化在一个范围里
     * */
    public float averageValue(float value[], int n) {
        float ave = 0;
        for (int i = 0; i < n; i++) {
            ave += value[i];
        }
        ave = ave / ValueNum;
        if (ave >= 8)
            ave = (float) 4.3;
        else if (ave >= 7 && ave < 8)
            ave = (float) 3.3;
        else if (ave >= 4 && ave < 7)
            ave = (float) 2.3;
        else if (ave >= 3 && ave < 4)
            ave = (float) 2.0;
        else {
            ave = (float) 1.3;
        }
        return ave;
    }

}

StepValuePassListener

package com.example.step;

public interface StepValuePassListener {
    void stepChanged(int steps);
}

StepView

package com.example.step;

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;


/**
 * 重新绘图的圆圈
 */
public class StepView extends View {

    private static int mText;
    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;// 上下文字的距离
    private int STEP;
    private float flag;
    private String AIM;
    BarAnimation anim;// 动画类

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

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

    public StepView(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("#000000"));
        textPaint1.setStyle(Style.FILL_AND_STROKE);
        textPaint1.setTextAlign(Align.LEFT);
        textPaint1.setTextSize(mTextSize1);


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

    }

    @SuppressLint("DrawAllocation")
    @Override
    //onDraw()方法来将自定义View绘制在布局中
    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);

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



        upText = "步数";
        downText = "目标:"+AIM;
        middleText = String.valueOf(mText);  //数字接口


        // 中间文字的画笔
        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);
    }

    // 进行测量出自定义控件的宽和高并且调用setMeasureDimension(width,height)方法,将宽高配置好
    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,float ProgressAni,String aim) {
        mText = text;
        flag = ProgressAni;
        AIM = aim;
        this.postInvalidate();// 可以用子线程更新视图的方法调用。view会执行onDraw()方法
        //invalidate();
    }



    /**
     * 继承animation的一个动画类
     *
     */
    public class BarAnimation extends Animation {
        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);
    }


}

 UpdateUiCallBack

package com.example.step;

public interface UpdateUiCallBack {
    /**
     * 更新UI步数
     */
    void updateUi(int stepCount);
}

WelcomeShow

package com.example.step;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

/**
 * 欢迎界面
 */

public class WelcomeShow extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_welcome_show);
        Button TRUE =(Button)findViewById(R.id.TRUE);
        TRUE.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(WelcomeShow.this,MainActivity.class);
                String str1=((EditText)findViewById(R.id.AIM)).getText().toString();
                Bundle bundle=new Bundle();
                bundle.putCharSequence("aim",str1);
                intent.putExtras(bundle) ;
                startActivity(intent);
            }

        });
    }
}

基于andoird的计步器(全代码)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/darker_gray"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.example.step.StepView
        android:id="@+id/shapeView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/busu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="33dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </LinearLayout>


    <Button
        android:id="@+id/start"
        android:layout_width="match_parent"
        android:layout_height="37dp"
        android:layout_below="@+id/shapeView"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="104dp"
        android:background="#FFFFFF"
        android:text="@string/butt1" />


</RelativeLayout>

基于andoird的计步器(全代码)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".WelcomeShow">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="369dp"
        android:orientation="horizontal">

    </LinearLayout>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginEnd="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginBottom="371dp"
        android:layout_toStartOf="@+id/AIM"
        android:layout_toLeftOf="@+id/AIM"
        android:padding="10dp"
        android:text="@string/TE"
        android:textSize="20dp" />

    <EditText
        android:id="@+id/AIM"
        android:layout_width="136dp"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_marginEnd="52dp"
        android:layout_marginRight="52dp"
        android:layout_marginBottom="376dp"
        android:hint="                    "
        android:inputType="number"
        android:padding="10dp" />

    <Button
        android:id="@+id/TRUE"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_marginEnd="141dp"
        android:layout_marginRight="141dp"
        android:layout_marginBottom="141dp"
        android:text="@string/TRUE" />
</RelativeLayout>

基于andoird的计步器(全代码)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".StepView">

</androidx.constraintlayout.widget.ConstraintLayout>

 

目录结构:基于andoird的计步器(全代码)

 

运行结果:

基于andoird的计步器(全代码)

 

本文地址:https://blog.csdn.net/qq_42018521/article/details/107180214