This commit is contained in:
zhaolizhi
2018-09-06 09:26:42 +08:00
95 changed files with 5120 additions and 189 deletions

View File

@@ -24,7 +24,7 @@ android {
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support:design:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
@@ -50,5 +50,20 @@ dependencies {
//个人信息的那个条条
compile 'com.akexorcist:RoundCornerProgressBar:2.0.3'
//wave
compile 'com.gelitenight.waveview:waveview:1.0.0'
implementation 'me.itangqi.waveloadingview:library:0.3.5'
//计步
implementation project(':todaystepcounterlib')
//打分ui
compile 'com.github.CB-ysx:CBRatingBar:3.0.1'
// //蛛网
// implementation 'me.panpf:spider-web-score-view:1.0.1'
//折线
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
//searchview
compile 'com.miguelcatalan:materialsearchview:1.4.0'
//floatbuttom
compile 'com.nightonke:boommenu:2.1.1'
//recycler and card
implementation 'com.android.support:recyclerview-v7:26.1.0'
implementation 'com.android.support:cardview-v7:26.1.0'
}

View File

@@ -17,9 +17,13 @@
<!-- 相机权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name="com.example.ninefourone.nutritionmaster.NutritionMaster"
android:name=".NutritionMaster"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
@@ -33,6 +37,12 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".camera.FoodMaterialCamera" />
<receiver
android:name=".step.StepStarter"
android:enabled="true"
android:exported="true"></receiver>
</application>
</manifest>

View File

@@ -1,6 +1,8 @@
package com.example.ninefourone.nutritionmaster;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import com.orhanobut.logger.AndroidLogAdapter;
import com.orhanobut.logger.Logger;
@@ -12,6 +14,7 @@ import com.orhanobut.logger.Logger;
public class NutritionMaster extends Application {
public static NutritionMaster mInstance;
private int appCount = 0;
@Override
public void onCreate() {
@@ -25,10 +28,55 @@ public class NutritionMaster extends Application {
*/
private void init() {
Logger.addLogAdapter(new AndroidLogAdapter());
Logger.d("Logger初始化成功");
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
appCount++;
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
appCount--;
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
}
public static NutritionMaster getInstance() {
return mInstance;
}
/**
* app是否在前台
*
* @return true前台false后台
*/
public boolean isForeground() {
return appCount > 0;
}
}

View File

@@ -0,0 +1,63 @@
package com.example.ninefourone.nutritionmaster.adapter;
import android.content.Context;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.ninefourone.nutritionmaster.R;
import com.example.ninefourone.nutritionmaster.bean.DailyCard;
import com.orhanobut.logger.Logger;
import java.util.ArrayList;
/**
* Created by ScorpioMiku on 2018/9/2.
*/
public class CardAdapter extends RecyclerView.Adapter<CardHolder> {
private Context context;
private ArrayList<DailyCard> mList;
public CardAdapter(Context context, ArrayList<DailyCard> mList) {
this.context = context;
this.mList = mList;
}
@Override
public CardHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.card_item, parent, false);
CardHolder cardHolder = new CardHolder(view);
return cardHolder;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onBindViewHolder(CardHolder holder, int position) {
holder.bindView(mList.get(position).getPictureId(), mList.get(position).getTitle(), context);
}
@Override
public int getItemCount() {
return mList.size();
}
/**
* 右划
*/
public void swipe2Right() {
Logger.d("右划");
}
/**
* 左划
*/
public void swipe2left() {
Logger.d("左划");
}
}

View File

@@ -0,0 +1,44 @@
package com.example.ninefourone.nutritionmaster.adapter;
import android.content.Context;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.ninefourone.nutritionmaster.R;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* Created by ScorpioMiku on 2018/9/2.
*/
public class CardHolder extends RecyclerView.ViewHolder {
@BindView(R.id.iv_photo)
ImageView ivPhoto;
@BindView(R.id.tv_name)
TextView tvName;
@BindView(R.id.tv_sign)
TextView tvSign;
public CardHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void bindView(int picId, String text, Context context) {
tvName.setText(text);
ivPhoto.setImageDrawable(context.getDrawable(picId));
}
}

View File

@@ -6,7 +6,7 @@ import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import com.example.ninefourone.nutritionmaster.R;
import com.example.ninefourone.nutritionmaster.modules.viewpagerfragments.page1.Page1;
import com.example.ninefourone.nutritionmaster.modules.viewpagerfragments.customization.CustomizationFragment;
import com.example.ninefourone.nutritionmaster.modules.viewpagerfragments.bodyinformation.BodyInformationFragment;
import com.example.ninefourone.nutritionmaster.modules.viewpagerfragments.page3.Page3;
@@ -30,7 +30,7 @@ public class HomePagerAdapter extends FragmentPagerAdapter {
if (fragments[position] == null) {
switch (position) {
case 0:
fragments[position] = Page1.getInstance();
fragments[position] = CustomizationFragment.getInstance();
break;
case 1:
fragments[position] = BodyInformationFragment.getInstance();

View File

@@ -23,6 +23,8 @@ public abstract class BaseActivity extends AppCompatActivity {
initToolBar();
}
/**
* 设置布局layout
*

View File

@@ -0,0 +1,44 @@
package com.example.ninefourone.nutritionmaster.bean;
/**
* Created by ScorpioMiku on 2018/9/3.
*/
public class DailyCard {
/***
* 每日卡片bean类
*/
private String title;
private String description;
private int pictureId;
public DailyCard(String title, String description, int pictureId) {
this.title = title;
this.description = description;
this.pictureId = pictureId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getPictureId() {
return pictureId;
}
public void setPictureId(int pictureId) {
this.pictureId = pictureId;
}
}

View File

@@ -0,0 +1,14 @@
package com.example.ninefourone.nutritionmaster.bean;
/**
* Created by ScorpioMiku on 2018/8/30.
*/
public class User {
private float height;
private float weight;
private float BMI;
private String sex;
private int age;
private String job;
}

View File

@@ -0,0 +1,63 @@
package com.example.ninefourone.nutritionmaster.camera;
import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import com.orhanobut.logger.Logger;
import java.io.IOException;
/**
* Created by ScorpioMiku on 2018/9/3.
*/
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera camera;
public CameraPreview(Context context, Camera camera) {
super(context);
this.camera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
// mHolder.setType();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (IOException e) {
Logger.e(e.getMessage());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mHolder.getSurface() == null) {
return;
}
try {
camera.stopPreview();
} catch (Exception e) {
e.printStackTrace();
}
try {
camera.setPreviewDisplay(mHolder);
camera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}

View File

@@ -0,0 +1,197 @@
package com.example.ninefourone.nutritionmaster.camera;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.Surface;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.ninefourone.nutritionmaster.R;
import com.example.ninefourone.nutritionmaster.utils.MessageUtils;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
/**
* Created by ScorpioMiku on 2018/9/3.
*/
public class FoodMaterialCamera extends AppCompatActivity {
@BindView(R.id.camera_preview)
FrameLayout mCameraLayout;
@BindView(R.id.results_text_view)
TextView resultsTextView;
@BindView(R.id.more_take_photo_button_capture)
ImageView moreTakePhotoButtonCapture;
@BindView(R.id.more_takephoto_ok)
ImageView moreTakephotoOk;
@BindView(R.id.more_camera_cover_linearlayout)
FrameLayout moreCameraCoverLinearlayout;
private Camera mCamera;
private CameraPreview mPreview;
private int mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//取消toolbar
requestWindowFeature(Window.FEATURE_NO_TITLE);
//设置全屏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//注意上面两个设置必须写在setContentView前面
setContentView(R.layout.cameras_layout);
ButterKnife.bind(this);
if (!checkCameraHardware(this)) {
MessageUtils.MakeToast("不支持相机");
} else {
openCamera();
}
setCameraDisplayOrientation(this, mCameraId, mCamera);
}
/**
* 检查当前设备是否有相机
*
* @param context
* @return
*/
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
/**
* 打开相机
*/
private void openCamera() {
if (null == mCamera) {
mCamera = getCameraInstance();
mPreview = new CameraPreview(this, mCamera);
// mPreview.setOnTouchListener(new View.OnTouchListener() {
// @Override
// public boolean onTouch(View v, MotionEvent event) {
// mCamera.autoFocus(null);
// return false;
// }
// });
mCameraLayout.addView(mPreview);
mCamera.startPreview();
}
}
/**
* 获取相机
*
* @return
*/
private Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open();
Camera.Parameters mParameters = c.getParameters();
mParameters.setPictureSize(720, 1280);
c.setParameters(mParameters);
} catch (Exception e) {
e.printStackTrace();
}
return c;
}
/**
* 对焦回调,对焦完成后进行拍照
*/
private Camera.AutoFocusCallback mAutoFocusCallback = new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success) {
mCamera.takePicture(null, null, mPictureCallback);
}
}
};
/**
* 拍照回调
*/
private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(final byte[] data, Camera camera) {
MessageUtils.MakeToast("拍照!");
mCamera.startPreview();
}
};
/**
* 两个按钮的事件
*
* @param view
*/
@OnClick({R.id.more_take_photo_button_capture, R.id.more_takephoto_ok})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.more_take_photo_button_capture:
mCamera.autoFocus(mAutoFocusCallback);
break;
case R.id.more_takephoto_ok:
break;
}
}
//将相机设置成竖屏
public static void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) {
int degrees = 0;
//可以获得摄像头信息
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
//获取屏幕旋转方向
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360;
} else {
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
}

View File

@@ -0,0 +1,25 @@
package com.example.ninefourone.nutritionmaster.cardconfig;
import android.content.Context;
import android.util.TypedValue;
/**
* 初始化一些配置信息、固定数据
*/
public class CardConfig {
//屏幕上最多同时显示几个Item
public static int MAX_SHOW_COUNT;
//每一级Scale相差0.05ftranslationY相差15dp,translationZ相差0.5dp左右
public static float SCALE_GAP;
public static int TRANS_Y_GAP;
public static int TRANS_Z_GAP;
public static void initConfig(Context context) {
MAX_SHOW_COUNT = 4;
SCALE_GAP = 0.05f;
//这里是把dp转换成px
TRANS_Y_GAP = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15f, context.getResources().getDisplayMetrics());
TRANS_Z_GAP = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0.5f, context.getResources().getDisplayMetrics());
}
}

View File

@@ -0,0 +1,256 @@
package com.example.ninefourone.nutritionmaster.cardconfig;
import android.graphics.Canvas;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.View;
import com.example.ninefourone.nutritionmaster.adapter.CardAdapter;
import com.example.ninefourone.nutritionmaster.adapter.CardHolder;
import java.util.List;
/**
* Created by ScorpioMiku on 2018/9/2.
*/
public class CardItemTouchCallBack extends ItemTouchHelper.Callback {
private static final String TAG = "CardItemTouchCallBack";
private RecyclerView mRecyclerView;
private CardAdapter mAdapter;
private List mDatas;
public CardItemTouchCallBack(RecyclerView recyclerView, CardAdapter adapter, List datas) {
this.mRecyclerView = recyclerView;
this.mAdapter = adapter;
this.mDatas = datas;
}
/**
* 是否开启长按拖拽
* true开启
* false,不开启长按退拽
*
* @return
*/
@Override
public boolean isLongPressDragEnabled() {
return false;
}
/**
* 是否开启滑动
* true开启
* false,不开启长按退拽
*
* @return
*/
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
/**
* ItemTouchHelper支持设置事件方向并且必须重写当前getMovementFlags来指定支持的方向
* dragFlags 表示拖拽的方向有六个类型的值LEFT、RIGHT、START、END、UP、DOWN
* swipeFlags 表示滑动的方向有六个类型的值LEFT、RIGHT、START、END、UP、DOWN
* 最后要通过makeMovementFlagsdragFlagswipe创建方向的Flag
*/
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
/**
* 由于我们不需要长按拖拽所以直接传入0即可传入0代表不监听
*/
int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT | ItemTouchHelper.UP | ItemTouchHelper.DOWN;
return makeMovementFlags(0, swipeFlags);
}
/**
* 长按item就可以拖动然后拖动到其他item的时候触发onMove
* 这里我们不需要
*
* @param recyclerView
* @param viewHolder 拖动的viewholder
* @param target 目标位置的viewholder
* @return
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
/**
* 把item滑走(飞出屏幕)的时候调用
*
* @param viewHolder 滑动的viewholder
* @param direction 滑动的方向
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
//这里来判断画出的方向,左边是4,右边是8,然后可以做一些数据操作
Log.d(TAG, "onSwiped: " + direction);
switch (direction) {
case 4:
Log.d(TAG, "onSwiped: 左边滑出");
mAdapter.swipe2left();
break;
case 8:
Log.d(TAG, "onSwiped: 右边滑出");
mAdapter.swipe2Right();
break;
}
//移除这条数据
Object remove = mDatas.remove(viewHolder.getLayoutPosition());
/** 这个位置可以用来加载数据,当滑到还剩4个或者多少个时可以在后面加载数据添加到mDatas中*/
//这里就为了方便,直接循环了,把移除的元素再添加到末尾
mDatas.add(mDatas.size(), remove);
//刷新
mAdapter.notifyDataSetChanged();
//复位
viewHolder.itemView.setRotation(0);
if (viewHolder instanceof CardHolder) {
CardHolder holder = (CardHolder) viewHolder;
}
}
/**
* 只要拖动、滑动了item,就会触发这个方法,而且是动的过程中会一直触发
* 所以动画效果就是在这个方法中来实现的
*
* @param c
* @param recyclerView
* @param viewHolder
* @param dX
* @param dY
* @param actionState
* @param isCurrentlyActive
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
float dX, float dY, int actionState, boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
double swipeValue = Math.sqrt(dX * dX + dY * dY); //滑动离中心的距离
double fraction = swipeValue / (mRecyclerView.getWidth() * 0.5f);
//边界修正 最大为1
if (fraction > 1) {
fraction = 1;
}
/**
* 调整每个子view的缩放、位移之类的
*/
int childCount = recyclerView.getChildCount(); //拿到子view的数量
isUpOrDown(mRecyclerView.getChildAt(childCount - 1));
for (int i = 0; i < childCount; i++) {
/** 拿到子view 注意这里,先绘制的i=0所以最下面一层view的i=0,最上面的i=3*/
View childView = recyclerView.getChildAt(i);
int level = childCount - i - 1; //转换一下,level代表层数,最上面是第0层
if (level > 0) {
//下面层,每一层的水平方向都要增大
childView.setScaleX((float) (1 - CardConfig.SCALE_GAP * level + fraction * CardConfig.SCALE_GAP));
if (level < CardConfig.MAX_SHOW_COUNT - 1) {
//1 2层
childView.setScaleY((float) (1 - CardConfig.SCALE_GAP * level + fraction * CardConfig.SCALE_GAP));
childView.setTranslationY((float) (CardConfig.TRANS_Y_GAP * level - fraction * CardConfig.TRANS_Y_GAP));
childView.setTranslationZ((float) (CardConfig.TRANS_Z_GAP * (CardConfig.MAX_SHOW_COUNT - 1 - level)
+ fraction * CardConfig.TRANS_Z_GAP));
} else {
//最下面一层,3层,这层不用变,所以这里不用写
}
} else {
//第0层
//拿到水平方向的偏移比率
float xFraction = dX / (mRecyclerView.getWidth() * 0.5f);
//边界修正,有正有负,因为旋转有两个方向
if (xFraction > 1) {
xFraction = 1;
} else if (xFraction < -1) {
xFraction = -1;
}
//第一层左右滑动的时候稍微有点旋转
childView.setRotation(xFraction * 15); //这里最多旋转15度
if (viewHolder instanceof CardHolder) {
CardHolder holder = (CardHolder) viewHolder;
if (dX > 0) {
//右滑,显示爱心
// holder.iv_love.setAlpha(xFraction);
} else if (dX < 0) {
//左滑,显示叉,注意这里xFraction为负数所以要取反
// holder.iv_del.setAlpha(-xFraction);
} else {
// holder.iv_love.setAlpha(0f);
// holder.iv_del.setAlpha(0f);
}
}
}
}
}
@Override
public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) {
// Log.i(TAG, "getSwipeThreshold: ");
// if (isUpOrDown(viewHolder.itemView)) { //如果是向上或者向下滑动
// return Float.MAX_VALUE; //就返回阈值为很大
// }
return super.getSwipeThreshold(viewHolder);
}
/**
* 获得逃脱(swipe)速度
*
* @param defaultValue
* @return
*/
@Override
public float getSwipeEscapeVelocity(float defaultValue) {
Log.d(TAG, "getSwipeEscapeVelocity: " + defaultValue);
View topView = mRecyclerView.getChildAt(mRecyclerView.getChildCount() - 1);
if (isUpOrDown(topView)) { //如果是向上或者向下滑动
return Float.MAX_VALUE; //就返回阈值为很大
}
return super.getSwipeEscapeVelocity(defaultValue);
}
/**
* 获得swipe的速度阈值
*
* @param defaultValue
* @return
*/
@Override
public float getSwipeVelocityThreshold(float defaultValue) {
Log.d(TAG, "getSwipeVelocityThreshold: " + defaultValue);
View topView = mRecyclerView.getChildAt(mRecyclerView.getChildCount() - 1);
if (isUpOrDown(topView)) { //如果是向上或者向下滑动
return Float.MAX_VALUE; //就返回阈值为很大
}
return super.getSwipeVelocityThreshold(defaultValue);
}
/**
* 判断是否是向上滑或者向下滑
*/
private boolean isUpOrDown(View topView) {
float x = topView.getX();
float y = topView.getY();
int left = topView.getLeft();
int top = topView.getTop();
if (Math.pow(x - left, 2) > Math.pow(y - top, 2)) {
//水平方向大于垂直方向
// Log.i(TAG, "isUpOrDown: 不是");
return false;
} else {
return true;
// Log.i(TAG, "isUpOrDown: 是");
}
}
}

View File

@@ -0,0 +1,98 @@
package com.example.ninefourone.nutritionmaster.cardconfig;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by ScorpioMiku on 2018/9/2.
*/
public class SwipeCardLayoutManager extends RecyclerView.LayoutManager {
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
/**
* 在这里面给子view布局,也就是item
*
* @param recycler
* @param state
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
//在布局之前将所有的子View先Detach掉放入到Scrap缓存中
detachAndScrapAttachedViews(recycler);
//拿到总item数量
int itemCount = getItemCount();
if (itemCount < 1) {//没有item当然就没必要布局了
return;
}
int bottomPosition; //用来记录最底层view的postion
if (itemCount < CardConfig.MAX_SHOW_COUNT) { //如果不足最大数量(4个)
//那么最底层就是最后一条数据对应的position
bottomPosition = itemCount - 1;
} else {
//否则最底层就是第MAX_SHOW_COUNT(4)条数据对应的position
bottomPosition = CardConfig.MAX_SHOW_COUNT - 1;
}
/**
* 这里开始布局且绘制子view
* 注意:这里要先从最底层开始绘制,因为后绘制的才能覆盖先绘制的,
* 滑动的时候是滑最上面一层的,也就是后绘制的
* position也是层数
*/
for (int position = bottomPosition; position >= 0; position--) {
//根据position找recycler要itemview
View view = recycler.getViewForPosition(position);
//将子View添加至RecyclerView中
addView(view);
//测量子view并且把Margin也作为子控件的一部分
measureChildWithMargins(view, 0, 0);
//宽度空隙 getWidth()得到Recycler控件的宽度,getDecoratedMeasuredWidth(view)拿到子view的宽度
int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
//高度空隙
int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);
//给子view布局,这里居中了
layoutDecoratedWithMargins(view, widthSpace / 2, 0,
widthSpace / 2 + getDecoratedMeasuredWidth(view),
getDecoratedMeasuredHeight(view) + 0);
/**
* 下面要调整每一层itemview的的大小及Y轴和Z轴的偏移
* 最上面一层第0层的Scale为1,translationY为0
* 依次往下,每层比上面一层:
* (1)Scale相差0.05f
* (2)translationY相差7dp
* (3)translationZ相差1dp
*
* 注意:最后一层,除了水平方向的大小其他都与上一层一样,所以要特殊判断
*/
if (position > 0) { //大于0就是不是最上面那层
//依次往下,每层都要水平方向缩小
view.setScaleX(1 - CardConfig.SCALE_GAP * position);
if (position < CardConfig.MAX_SHOW_COUNT - 1) {
//如果,不是最后一层,就都要调整
view.setScaleY(1 - CardConfig.SCALE_GAP * position); //垂直方向缩小
view.setTranslationY(CardConfig.TRANS_Y_GAP * position); //向下平移
view.setTranslationZ(CardConfig.TRANS_Z_GAP * (CardConfig.MAX_SHOW_COUNT - 1 - position)); //Z轴方向的平移
} else {
//否则,就是最后一层,与上一层保持一致
view.setScaleY(1 - CardConfig.SCALE_GAP * (position - 1)); //垂直方向缩小
view.setTranslationY(CardConfig.TRANS_Y_GAP * (position - 1)); //向下平移
view.setTranslationZ(CardConfig.TRANS_Z_GAP * (CardConfig.MAX_SHOW_COUNT - 1 - (position - 1))); //Z轴方向的平移
}
} else {
//否则是第0层(最上面那层),只需调整Z轴高度
view.setTranslationZ(CardConfig.TRANS_Z_GAP * (CardConfig.MAX_SHOW_COUNT - 1)); //Z轴方向的平移
}
}
}
}

View File

@@ -1,31 +1,54 @@
package com.example.ninefourone.nutritionmaster.modules;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.ToxicBakery.viewpager.transforms.AccordionTransformer;
import com.ToxicBakery.viewpager.transforms.CubeInTransformer;
import com.ToxicBakery.viewpager.transforms.CubeOutTransformer;
import com.ToxicBakery.viewpager.transforms.DepthPageTransformer;
import com.ToxicBakery.viewpager.transforms.FlipHorizontalTransformer;
import com.ToxicBakery.viewpager.transforms.FlipVerticalTransformer;
import com.ToxicBakery.viewpager.transforms.RotateUpTransformer;
import com.ToxicBakery.viewpager.transforms.StackTransformer;
import com.ToxicBakery.viewpager.transforms.TabletTransformer;
import com.ToxicBakery.viewpager.transforms.ZoomInTransformer;
import com.cb.ratingbar.CBRatingBar;
import com.example.ninefourone.nutritionmaster.R;
import com.example.ninefourone.nutritionmaster.adapter.HomePagerAdapter;
import com.example.ninefourone.nutritionmaster.base.BaseActivity;
import com.example.ninefourone.nutritionmaster.camera.FoodMaterialCamera;
import com.example.ninefourone.nutritionmaster.ui.NoScrollViewPager;
import com.example.ninefourone.nutritionmaster.utils.MessageUtils;
import com.example.ninefourone.nutritionmaster.utils.PermissionUtils;
import com.flyco.tablayout.SlidingTabLayout;
import com.github.mikephil.charting.charts.RadarChart;
import com.github.mikephil.charting.components.Description;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.RadarData;
import com.github.mikephil.charting.data.RadarDataSet;
import com.github.mikephil.charting.data.RadarEntry;
import com.github.mikephil.charting.formatter.IndexAxisValueFormatter;
import com.github.siyamed.shapeimageview.CircularImageView;
import com.miguelcatalan.materialsearchview.MaterialSearchView;
import com.mxn.soul.flowingdrawer_core.ElasticDrawer;
import com.mxn.soul.flowingdrawer_core.FlowingDrawer;
import com.nightonke.boommenu.BoomButtons.HamButton;
import com.nightonke.boommenu.BoomButtons.OnBMClickListener;
import com.nightonke.boommenu.BoomMenuButton;
import com.orhanobut.logger.Logger;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends BaseActivity {
@BindView(R.id.drawerlayout)
@@ -36,6 +59,28 @@ public class MainActivity extends BaseActivity {
NoScrollViewPager viewPager;
@BindView(R.id.sliding_tab_layout)
SlidingTabLayout slidingTabLayout;
@BindView(R.id.bar_cover)
FrameLayout barCover;
@BindView(R.id.cb_rating_bar)
CBRatingBar cbRatingBar;
@BindView(R.id.toolbar_user_avatar)
CircularImageView toolbarUserAvatar;
@BindView(R.id.drawer_user_avatar)
CircularImageView drawerUserAvatar;
// @BindView(R.id.spiderWeb_mainActivity)
// SpiderWebScoreView spiderWebMainActivity;
// @BindView(R.id.layout_mainActivity_circular)
// CircularLayout layoutMainActivityCircular;
// @BindView(R.id.search_button)
// ImageView searchButton;
@BindView(R.id.search_view)
MaterialSearchView searchView;
@BindView(R.id.tool_bar)
Toolbar toolBar;
@BindView(R.id.boom_menu_button)
BoomMenuButton boomMenuButton;
@BindView(R.id.spider_view)
RadarChart spiderView;
@Override
@@ -47,10 +92,13 @@ public class MainActivity extends BaseActivity {
public void initViews(Bundle savedInstanceState) {
mDrawer.setTouchMode(ElasticDrawer.TOUCH_MODE_BEZEL);
mDrawer.setOnDrawerStateChangeListener(new ElasticDrawer.OnDrawerStateChangeListener() {
@SuppressLint("ResourceAsColor")
@Override
public void onDrawerStateChange(int oldState, int newState) {
if (newState == ElasticDrawer.STATE_CLOSED) {
// Logger.i("Drawer STATE_CLOSED");
barCover.setVisibility(View.INVISIBLE);
} else {
barCover.setVisibility(View.VISIBLE);
}
}
@@ -59,7 +107,10 @@ public class MainActivity extends BaseActivity {
// Logger.i("openRatio=" + openRatio + " ,offsetPixels=" + offsetPixels);
}
});
initSpiderView();
initViewPager();
initSearchView();
initBMB();
}
/**
@@ -75,7 +126,6 @@ public class MainActivity extends BaseActivity {
viewPager.setPageTransformer(true, new CubeOutTransformer());
slidingTabLayout.setViewPager(viewPager);
viewPager.setCurrentItem(1);
}
@Override
@@ -88,13 +138,34 @@ public class MainActivity extends BaseActivity {
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// TODO: add setContentView(...) invocation
ButterKnife.bind(this);
Logger.d("oncreate");
setSupportActionBar(toolBar);
askPermission();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
Logger.d("oncreateMenu");
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem item = menu.findItem(R.id.id_action_search);
searchView.setMenuItem(item);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
Logger.d("prepareMenu");
return super.onPrepareOptionsMenu(menu);
}
/**
* 点击事件
*/
@@ -102,4 +173,136 @@ public class MainActivity extends BaseActivity {
public void onViewClicked() {
mDrawer.openMenu();
}
/**
* 初始化蛛网图
*/
private void initSpiderView() {
float[] scores = {9.1f, 5.5f, 7.7f, 8.9f, 4.6f};
String[] flags = {"糖分", "淡水", "蛋白质", "维生素", "矿物质"};
List<RadarEntry> radarEntries = new ArrayList<>();
for (int i = 0; i < flags.length; i++) {
RadarEntry radarEntry = new RadarEntry(scores[i], flags[i]);
radarEntries.add(radarEntry);
}
Description description = new Description();
description.setText("");
spiderView.setDescription(description);
spiderView.setWebLineWidth(1.5f);
// 内部线条宽度,外面的环状线条
spiderView.setWebLineWidthInner(1.5f);
// 所有线条WebLine透明度
spiderView.setWebAlpha(300);
Legend legend = spiderView.getLegend();
legend.setEnabled(false);
XAxis xAxis = spiderView.getXAxis();
// X坐标值字体样式
// xAxis.setTypeface(tf);
// X坐标值字体大小
xAxis.setTextSize(8f);
ArrayList<String> xVals = new ArrayList<String>();
for (String flag : flags) {
xVals.add(flag);
}
xAxis.setValueFormatter(new IndexAxisValueFormatter(xVals));
YAxis yAxis = spiderView.getYAxis();
// Y坐标值字体样式
// yAxis.setTypeface(tf);
// Y坐标值字体大小
yAxis.setTextSize(0f);
// Y坐标值是否从0开始
yAxis.setStartAtZero(true);
// 是否显示y值在图表上
yAxis.setDrawLabels(false);
yAxis.setAxisLineWidth(2f);
RadarDataSet set = new RadarDataSet(radarEntries, "体质情况");
// set.setColor(R.color.bar_open);
set.setLineWidth(0.5f);
set.setDrawFilled(true);
// set.setFillColor(R.color.spider_view_color);
// set.resetColors();
RadarData data = new RadarData(set);
data.setDrawValues(false);
spiderView.setData(data);
spiderView.setTouchEnabled(false);
spiderView.invalidate();
}
/**
* 初始化SearchView
*/
private void initSearchView() {
searchView.setOnQueryTextListener(new MaterialSearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
MessageUtils.MakeToast(query);
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
// MessageUtils.MakeToast(newText);
return false;
}
});
searchView.setOnSearchViewListener(new MaterialSearchView.SearchViewListener() {
@Override
public void onSearchViewShown() {
// MessageUtils.MakeToast("Shown");
}
@Override
public void onSearchViewClosed() {
// MessageUtils.MakeToast("closed");
}
});
}
/**
* 初始化悬浮按钮
*/
private void initBMB() {
HamButton.Builder builder = new HamButton.Builder()
.normalImageRes(R.drawable.food_material)
.normalTextRes(R.string.food_meterial_title)
.listener(new OnBMClickListener() {
@Override
public void onBoomButtonClick(int index) {
Intent cameraIntent = new Intent(MainActivity.this, FoodMaterialCamera.class);
startActivity(cameraIntent);
}
});
boomMenuButton.addBuilder(builder);
HamButton.Builder builder2 = new HamButton.Builder()
.normalImageRes(R.drawable.foods)
.normalTextRes(R.string.food_title);
boomMenuButton.addBuilder(builder2);
}
/**
* 请求权限
*/
private void askPermission() {
PermissionUtils.requestCameraPermission(this);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
MessageUtils.MakeToast("权限赋予成功");
}
}

View File

@@ -1,20 +1,34 @@
package com.example.ninefourone.nutritionmaster.modules.viewpagerfragments.bodyinformation;
import android.graphics.Color;
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.os.RemoteException;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.akexorcist.roundcornerprogressbar.IconRoundCornerProgressBar;
import com.akexorcist.roundcornerprogressbar.RoundCornerProgressBar;
import com.example.ninefourone.nutritionmaster.R;
import com.example.ninefourone.nutritionmaster.base.BaseFragment;
import com.gelitenight.waveview.library.WaveView;
import com.example.ninefourone.nutritionmaster.utils.ChartDrawer;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.today.step.lib.ISportStepInterface;
import com.today.step.lib.TodayStepManager;
import com.today.step.lib.TodayStepService;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import me.itangqi.waveloadingview.WaveLoadingView;
/**
* Created by ScorpioMiku on 2018/8/26.
@@ -22,13 +36,27 @@ import butterknife.Unbinder;
public class BodyInformationFragment extends BaseFragment {
@BindView(R.id.progress_1)
RoundCornerProgressBar progress1;
@BindView(R.id.progress_2)
IconRoundCornerProgressBar progress2;
Unbinder unbinder;
@BindView(R.id.wave_view)
WaveView waveView;
@BindView(R.id.step_text_view)
TextView stepTextView;
@BindView(R.id.waveLoadingView)
WaveLoadingView waveLoadingView;
@BindView(R.id.weight_line_chart)
LineChart weightLineChart;
@BindView(R.id.step_line_chart)
LineChart stepLineChart;
private int stepCount = 0;
private static final int REFRESH_STEP_WHAT = 0;
//循环取当前时刻的步数中间的间隔时间
private long TIME_INTERVAL_REFRESH = 500;
private Handler mDelayHandler = new Handler(new TodayStepCounterCall());
private ISportStepInterface iSportStepInterface;
@Override
public int getLayoutResId() {
@@ -37,31 +65,8 @@ public class BodyInformationFragment extends BaseFragment {
@Override
public void initView(Bundle state) {
progress1.setProgressColor(Color.parseColor("#ed3b27"));
progress1.setProgressBackgroundColor(Color.parseColor("#808080"));
progress1.setMax(70);
progress1.setProgress(15);
int progressColor1 = progress1.getProgressColor();
int backgroundColor1 = progress1.getProgressBackgroundColor();
int max1 = (int) progress1.getMax();
int progress_1 = (int) progress1.getProgress();
progress2.setProgressColor(Color.parseColor("#56d2c2"));
progress2.setProgressBackgroundColor(Color.parseColor("#757575"));
progress2.setIconBackgroundColor(Color.parseColor("#38c0ae"));
progress2.setMax(550);
progress2.setProgress(147);
progress2.setIconImageResource(R.drawable.test_avatar);
int progressColor2 = progress2.getProgressColor();
int backgroundColor2 = progress2.getProgressBackgroundColor();
int headerColor2 = progress2.getColorIconBackground();
int max2 = (int) progress2.getMax();
int progress_2 = (int) progress2.getProgress();
waveView.setShapeType(WaveView.ShapeType.CIRCLE);
initStepCounter();
initChart();
}
@@ -82,4 +87,91 @@ public class BodyInformationFragment extends BaseFragment {
super.onDestroyView();
unbinder.unbind();
}
/**
* 计步器初始化
*/
private void initStepCounter() {
TodayStepManager.init(getActivity().getApplication());
//开启计步
Intent stepCounterStart = new Intent(getActivity(), TodayStepService.class);
getActivity().startService(stepCounterStart);
getActivity().bindService(stepCounterStart, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iSportStepInterface = ISportStepInterface.Stub.asInterface(service);
try {
stepCount = iSportStepInterface.getCurrentTimeSportStep();
updateStepCount();
} catch (RemoteException e) {
e.printStackTrace();
}
mDelayHandler.sendEmptyMessageDelayed(REFRESH_STEP_WHAT, TIME_INTERVAL_REFRESH);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}, Context.BIND_AUTO_CREATE);
}
/**
* 改变记步UI中的数字
*/
private void updateStepCount() {
stepTextView.setText(stepCount + "");
}
/**
* 定时器修改UI
*/
class TodayStepCounterCall implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case REFRESH_STEP_WHAT: {
//每隔500毫秒获取一次计步数据刷新UI
if (null != iSportStepInterface) {
int step = 0;
try {
step = iSportStepInterface.getCurrentTimeSportStep();
} catch (RemoteException e) {
e.printStackTrace();
}
if (stepCount != step) {
stepCount = step;
updateStepCount();
}
}
mDelayHandler.sendEmptyMessageDelayed(REFRESH_STEP_WHAT, TIME_INTERVAL_REFRESH);
break;
}
}
return false;
}
}
/**
* 初始化表格
*/
private void initChart() {
ArrayList<Entry> weightPointValues = new ArrayList<>();
for (int i = 1; i < 15; i++) {
int y = (int) (Math.random() * 20);
weightPointValues.add(new Entry(i, y));
}
ChartDrawer.initSingleLineChart(weightLineChart, weightPointValues, "体重");
ArrayList<Entry> stepPointValues = new ArrayList<>();
for (int i = 1; i < 15; i++) {
int y = (int) (Math.random() * 20);
stepPointValues.add(new Entry(i, y));
}
ChartDrawer.initSingleLineChart(stepLineChart, stepPointValues, "步数");
}
}

View File

@@ -0,0 +1,111 @@
package com.example.ninefourone.nutritionmaster.modules.viewpagerfragments.customization;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.ninefourone.nutritionmaster.R;
import com.example.ninefourone.nutritionmaster.adapter.CardAdapter;
import com.example.ninefourone.nutritionmaster.adapter.CardHolder;
import com.example.ninefourone.nutritionmaster.base.BaseFragment;
import com.example.ninefourone.nutritionmaster.bean.DailyCard;
import com.example.ninefourone.nutritionmaster.cardconfig.CardConfig;
import com.example.ninefourone.nutritionmaster.cardconfig.CardItemTouchCallBack;
import com.example.ninefourone.nutritionmaster.cardconfig.SwipeCardLayoutManager;
import com.example.ninefourone.nutritionmaster.utils.ConstantUtils;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* Created by ScorpioMiku on 2018/8/26.
*/
public class CustomizationFragment extends BaseFragment {
@BindView(R.id.card_recycler_view)
RecyclerView cardRecyclerView;
Unbinder unbinder;
private CardAdapter cardAdapter;
private CardHolder cardHolder;
private ArrayList<DailyCard> mDataList = new ArrayList<>();
private int[] picList = new int[]{
R.drawable.monday,
R.drawable.tuesday,
R.drawable.wednesday,
R.drawable.thursday,
R.drawable.friday,
R.drawable.saturday,
R.drawable.sunday
};
@Override
public int getLayoutResId() {
return R.layout.customization;
}
@Override
public void initView(Bundle state) {
loadData();
initCardRecyclerView();
}
public static BaseFragment getInstance() {
return new CustomizationFragment();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// TODO: inflate a fragment view
View rootView = super.onCreateView(inflater, container, savedInstanceState);
unbinder = ButterKnife.bind(this, rootView);
return rootView;
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
protected void loadData() {
super.loadData();
for (int i = 1; i <= 7; i++) {
// mDataList.add("周" + ConstantUtils.arab2Chinese(i) + "美食普");
DailyCard dailyCard = new DailyCard(
"" + ConstantUtils.arab2Chinese(i) + "美食普",
"这里放描述",
picList[i - 1]
);
mDataList.add(dailyCard);
}
}
/**
* 初始化card recyclerview
*/
private void initCardRecyclerView() {
CardConfig.initConfig(getContext());
cardRecyclerView.setLayoutManager(new SwipeCardLayoutManager());
cardAdapter = new CardAdapter(getContext(), mDataList);
cardRecyclerView.setAdapter(cardAdapter);
CardItemTouchCallBack callBack = new CardItemTouchCallBack(cardRecyclerView, cardAdapter, mDataList);
//2.创建ItemTouchHelper并把callBack传进去
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callBack);
//3.与RecyclerView关联起来
itemTouchHelper.attachToRecyclerView(cardRecyclerView);
}
}

View File

@@ -1,27 +0,0 @@
package com.example.ninefourone.nutritionmaster.modules.viewpagerfragments.page1;
import android.os.Bundle;
import com.example.ninefourone.nutritionmaster.R;
import com.example.ninefourone.nutritionmaster.base.BaseFragment;
/**
* Created by ScorpioMiku on 2018/8/26.
*/
public class Page1 extends BaseFragment {
@Override
public int getLayoutResId() {
return R.layout.page_1;
}
@Override
public void initView(Bundle state) {
}
public static BaseFragment getInstance() {
return new Page1();
}
}

View File

@@ -0,0 +1,28 @@
package com.example.ninefourone.nutritionmaster.step;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.example.ninefourone.nutritionmaster.NutritionMaster;
import com.example.ninefourone.nutritionmaster.modules.MainActivity;
import com.orhanobut.logger.Logger;
public class StepStarter extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
// throw new UnsupportedOperationException("Not yet implemented");
NutritionMaster nutritionMaster = (NutritionMaster) context.getApplicationContext();
if (!nutritionMaster.isForeground()) {
Intent mainIntent = new Intent(context, MainActivity.class);
mainIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mainIntent);
}else {
Logger.d("已经在计步了");
}
}
}

View File

@@ -0,0 +1,59 @@
package com.example.ninefourone.nutritionmaster.utils;
/**
* Created by ScorpioMiku on 2018/8/29.
*/
public class CalculateUtils {
/**
* 计算BMI值 BMI值計算公式: BMI = 體重(公斤) / 身高2(公尺2)
*
* @param height
* @param weight
* @return
*/
public static float BMI(float height, float weight) {
if (height > 10) {
height = height / 100;
}
return weight / (height * height);
}
/**
* 通过身高获得健康的体重
*
* @param height
* @return
*/
public static float[] standardH2W(float height) {
if (height > 10) {
height = height / 100;
}
float min;
float max;
min = (float) 18.5 * height * height;
max = (float) 14 * height * height;
float[] re = {min, max};
return re;
}
/**
* 根据BMI得到体质情况
*
* @param BMI
* @return
*/
public static String bodyStatus(float BMI) {
if (BMI < 18.5) {
return "轻体重";
} else if (BMI < 24) {
return "健康体重";
} else if (BMI < 27) {
return "轻度肥胖";
} else if (BMI < 30) {
return "中度肥胖";
} else {
return "重度肥胖";
}
}
}

View File

@@ -0,0 +1,203 @@
package com.example.ninefourone.nutritionmaster.utils;
import android.content.Context;
import android.graphics.Color;
import com.example.ninefourone.nutritionmaster.R;
import com.github.mikephil.charting.animation.Easing;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Description;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IndexAxisValueFormatter;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.orhanobut.logger.Logger;
import java.util.ArrayList;
import java.util.List;
/**
* Created by ScorpioMiku on 2018/8/30.
*/
public class ChartDrawer {
/**
* 创建一条折线
*
* @param index
* @param datas
* @param linename
* @return
*/
public static void initSingleLineChart(LineChart mLineChart, ArrayList<Entry> pointValues, String linename) {
// if (index.length != datas.length) {
// MessageUtils.MakeToast("index长度与datas长度不符");
// Logger.d("长度不符");
// return;
// } else {
// ArrayList<String> xValues = new ArrayList<>();
// for (int i = 0; i < datas.length; i++) {
// xValues.add(index[i] + "");
// }
// ArrayList<Entry> pointValues = new ArrayList<>();
// for (int i = 0; i < datas.length; i++) {
// pointValues.add(new Entry(datas[i], i));
// }
// LineDataSet dataSet = new LineDataSet(pointValues, linename);
// dataSet.setLineWidth(1.75f);
// dataSet.setColor(R.color.colorPrimary);
//
// ArrayList<ILineDataSet> dataSetArrayList = new ArrayList<>();
// dataSetArrayList.add(dataSet);
//
// LineData lineData = new LineData(dataSetArrayList);
//表格属性
// lineChart.setDrawBorders(false);
// lineChart.setDrawGridBackground(false); //表格颜色
// lineChart.setGridBackgroundColor(Color.GRAY & 0x70FFFFFF); //表格的颜色,设置一个透明度
// lineChart.setTouchEnabled(true); //可点击
// lineChart.setDragEnabled(true); //可拖拽
// lineChart.setScaleEnabled(true); //可缩放
// lineChart.setPinchZoom(false);
// lineChart.setBackgroundColor(Color.WHITE); //设置背景颜色
//
// lineChart.setData(lineData);
//
// Legend mLegend = lineChart.getLegend(); //设置标示就是那个一组y的value的
// mLegend.setForm(Legend.LegendForm.SQUARE); //样式
// mLegend.setFormSize(6f); //字体
// mLegend.setTextColor(Color.GRAY); //颜色
// lineChart.setVisibleXRange(0, 4); //x轴可显示的坐标范围
// XAxis xAxis = lineChart.getXAxis(); //x轴的标示
// xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); //x轴位置
// xAxis.setTextColor(Color.GRAY); //字体的颜色
// xAxis.setTextSize(10f); //字体大小
// xAxis.setGridColor(Color.GRAY);//网格线颜色
// xAxis.setDrawGridLines(false); //不显示网格线
// YAxis axisLeft = lineChart.getAxisLeft(); //y轴左边标示
// YAxis axisRight = lineChart.getAxisRight(); //y轴右边标示
// axisLeft.setTextColor(Color.GRAY); //字体颜色
// axisLeft.setTextSize(10f); //字体大小
// //axisLeft.setAxisMaxValue(800f); //最大值
// axisLeft.setLabelCount(5, true); //显示格数
// axisLeft.setGridColor(Color.GRAY); //网格线颜色
//
// axisRight.setDrawAxisLine(false);
// axisRight.setDrawGridLines(false);
// axisRight.setDrawLabels(false);
//
// //设置动画效果
// lineChart.animateY(2000, Easing.EasingOption.Linear);
// lineChart.animateX(2000, Easing.EasingOption.Linear);
// lineChart.invalidate();
mLineChart.setNoDataText("没有数据喔~~");
//设置是否绘制chart边框的线
mLineChart.setDrawBorders(true);
//设置chart边框线颜色
mLineChart.setBorderColor(Color.GRAY);
//设置chart边框线宽度
mLineChart.setBorderWidth(1f);
//设置chart是否可以触摸
mLineChart.setTouchEnabled(true);
//设置是否可以拖拽
mLineChart.setDragEnabled(true);
//设置是否可以缩放 x和y默认true
mLineChart.setScaleEnabled(false);
//设置是否可以通过双击屏幕放大图表。默认是true
mLineChart.setDoubleTapToZoomEnabled(false);
//设置chart动画
mLineChart.animateXY(1000, 1000);
//=========================设置图例=========================
// 像"□ xxx"就是图例
Legend legend = mLineChart.getLegend();
legend.setEnabled(false);
//=======================设置X轴显示效果==================
XAxis xAxis = mLineChart.getXAxis();
//是否启用X轴
xAxis.setEnabled(true);
//是否绘制X轴线
xAxis.setDrawAxisLine(true);
//设置X轴上每个竖线是否显示
xAxis.setDrawGridLines(true);
//设置是否绘制X轴上的对应值(标签)
xAxis.setDrawLabels(true);
//设置X轴显示位置
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
//设置竖线为虚线样式
// xAxis.enableGridDashedLine(10f, 10f, 0f);
//设置x轴标签数
xAxis.setLabelCount(8,false);
xAxis.setTextSize(5);
//图表第一个和最后一个label数据不超出左边和右边的Y轴
// xAxis.setAvoidFirstLastClipping(true);
xAxis.setDrawGridLines(false);//设置x轴上每个点对应的线
//修改横轴
//准备好每个点对应的x轴数值
List<String> list = new ArrayList<>();
for (int i = 0; i < pointValues.size(); i++) {
list.add(String.valueOf(i+1).concat(""));
}
xAxis.setValueFormatter(new IndexAxisValueFormatter(list));
YAxis rightAxis = mLineChart.getAxisRight();
rightAxis.setDrawAxisLine(false);
rightAxis.setDrawGridLines(false);
rightAxis.setEnabled(false);
YAxis leftAxis = mLineChart.getAxisLeft();
leftAxis.setEnabled(false);
leftAxis.setDrawAxisLine(false);
//点构成的某条线
LineDataSet lineDataSet = new LineDataSet(pointValues, "体重");
//设置该线的颜色
lineDataSet.setColor(R.color.color_bar_background);
//设置每个点的颜色
lineDataSet.setCircleColor(0xff0171c9);
//设置该线的宽度
lineDataSet.setLineWidth(0f);
//设置每个坐标点的圆大小
//lineDataSet.setCircleRadius(1f);
//设置是否画圆
lineDataSet.setDrawCircles(false);
// 设置平滑曲线模式
// lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
//设置线一面部分是否填充颜色
lineDataSet.setDrawFilled(true);
//设置填充的颜色
lineDataSet.setFillColor(0x20A0FF);
//设置是否显示点的坐标值
lineDataSet.setDrawValues(false);
//隐藏x轴描述
Description description = new Description();
description.setEnabled(false);
mLineChart.setDescription(description);
mLineChart.setDrawBorders(false);
//线的集合(可单条或多条线)
List<ILineDataSet> dataSets = new ArrayList<>();
dataSets.add(lineDataSet);
//把要画的所有线(线的集合)添加到LineData里
LineData lineData = new LineData(dataSets);
//把最终的数据setData
mLineChart.setData(lineData);
mLineChart.invalidate();
}
}

View File

@@ -1,8 +1,31 @@
package com.example.ninefourone.nutritionmaster.utils;
import java.util.ArrayList;
/**
* Created by ScorpioMiku on 2018/8/26.
*/
public class ConstantUtils {
public static String arab2Chinese(int number) {
switch (number) {
case 1:
return "";
case 2:
return "";
case 3:
return "";
case 4:
return "";
case 5:
return "";
case 6:
return "";
case 7:
return "";
default:
return "";
}
}
}

View File

@@ -0,0 +1,44 @@
package com.example.ninefourone.nutritionmaster.utils;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
/**
* Created by ScorpioMiku on 2018/9/3.
*/
public class PermissionUtils {
public static final int REQUEST_CAMERA = 1056;
/**
* 动态获取相机权限
*
* @param activity
*/
public static void requestCameraPermission(Activity activity) {
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
/**
* 直接请求四个权限
*/
ActivityCompat.requestPermissions(activity,
new String[]{
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE
}, REQUEST_CAMERA);
// MessageUtils.MakeToast("权限赋予成功");
} else {
/**
* 否则
*/
}
}
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false" android:drawable="@mipmap/camera_button" />
<item android:state_pressed="true" android:drawable="@mipmap/camera_button_pressed" />
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

View File

@@ -0,0 +1,6 @@
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#35c4f9" android:pathData="M512,1024C229.7,1024 0,794.3 0,512S229.7,0 512,0s512,229.7 512,512 -229.7,512 -512,512zM512,64C265,64 64,265 64,512c0,247 201,448 448,448s448,-201 448,-448c0,-247 -201,-448 -448,-448z"/>
<path android:fillColor="#35c4f9" android:pathData="M323.4,635.7L247.7,635.7c-10.9,0 -18.7,-2.4 -23.4,-7.3 -4.7,-4.9 -7,-12.7 -7,-23.4v-186.1c0,-10.9 2.4,-18.8 7.2,-23.6 4.8,-4.8 12.5,-7.2 23.2,-7.2h80.2c11.8,0 22.1,0.7 30.8,2.2 8.6,1.5 16.4,4.3 23.3,8.4a60.6,60.6 0,0 1,25.8 31c2.4,6.5 3.5,13.3 3.5,20.5 0,24.8 -12.4,42.9 -37.2,54.4 32.5,10.4 48.8,30.5 48.8,60.5 0,13.9 -3.5,26.3 -10.7,37.4a63.8,63.8 0,0 1,-28.7 24.6,100.7 100.7,0 0,1 -26,6.7 265.9,265.9 0,0 1,-34.2 1.9zM267.5,425.9v64h45.9c12.5,0 22.1,-1.2 29,-3.6a27.3,27.3 0,0 0,15.6 -13.5,30.1 30.1,0 0,0 4.3,-15.9c0,-12.5 -4.4,-20.8 -13.3,-24.9 -8.9,-4.1 -22.5,-6.1 -40.7,-6.1L267.5,425.9zM319.6,525.9h-52.2v72.3h53.9c33.9,0 50.8,-12.2 50.8,-36.7 0,-12.5 -4.4,-21.6 -13.2,-27.2s-21.9,-8.4 -39.4,-8.4zM550,598.5l-39.7,-157.8v170.9c0,9.4 -2.1,16.5 -6.4,21.2a21.3,21.3 0,0 1,-16.8 7.1,21.4 21.4,0 0,1 -16.6,-7c-4.3,-4.7 -6.4,-11.8 -6.4,-21.3v-195.9c0,-10.8 2.8,-18.1 8.4,-21.9 5.6,-3.8 13.2,-5.7 22.8,-5.7h15.5c9.3,0 16.1,0.8 20.4,2.5s7.3,4.7 9.3,9.1c2,4.4 4.4,11.5 6.9,21.4l36,135.6 35.9,-135.6c2.6,-9.9 4.9,-17.1 6.9,-21.4a16.9,16.9 0,0 1,9.4 -9.1c4.2,-1.7 11,-2.5 20.4,-2.5h15.5c9.6,0 17.2,1.9 22.8,5.7 5.6,3.7 8.4,11.1 8.4,21.9v195.9c0,9.4 -2.1,16.5 -6.3,21.2a21.6,21.6 0,0 1,-17 7.1,21 21,0 0,1 -16.4,-7.1c-4.3,-4.7 -6.4,-11.8 -6.4,-21.2v-170.9l-39.7,157.8c-2.6,10.2 -4.7,17.7 -6.3,22.5a31.4,31.4 0,0 1,-9 13.1c-4.4,4 -10.5,6 -18.2,6 -5.9,0 -10.8,-1.3 -14.9,-3.8s-7.2,-5.8 -9.5,-9.7a54.9,54.9 0,0 1,-5.3 -13.1c-1.3,-4.8 -2.6,-9.8 -3.9,-14.9zM756.5,609.4v-195.1c0,-10.1 2.3,-17.7 6.9,-22.8s10.6,-7.6 17.9,-7.6a24,24 0,0 1,18.4 7.5c4.7,5 7,12.7 7,22.9v195.1c0,10.2 -2.3,17.9 -7,22.9a23.9,23.9 0,0 1,-18.4 7.6c-7.2,0 -13.1,-2.6 -17.8,-7.7s-7,-12.8 -7,-22.9z"/>
<path android:fillColor="#35c4f9" android:pathData="M512,128c211.7,0 384,172.3 384,384 0,211.7 -172.3,384 -384,384S128,723.7 128,512C128,300.3 300.3,128 512,128m0,-32C282.2,96 96,282.2 96,512s186.2,416 416,416 416,-186.2 416,-416S741.8,96 512,96z"/>
</vector>

View File

@@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ffffff" android:pathData="M160,448h704c1.9,0 4.5,0 6.4,-0.6 0.6,0 1.9,-0.6 2.6,-0.6 1.3,0 1.9,-0.6 3.2,-1.3 1.3,-0.6 1.9,-1.3 3.2,-1.3 0.6,-0.6 1.9,-0.6 2.6,-1.3 1.9,-1.3 3.2,-2.6 4.5,-3.8 1.3,-1.3 2.6,-3.2 3.8,-4.5 0.6,-0.6 0.6,-1.9 1.3,-2.6 0.6,-1.3 1.3,-1.9 1.3,-3.2 0.6,-1.3 0.6,-1.9 1.3,-3.2 0,-0.6 0.6,-1.9 0.6,-2.6 0.6,-3.8 0.6,-8.3 0,-12.8 0,-0.6 -0.6,-1.9 -0.6,-2.6 -0.6,-1.3 -0.6,-2.6 -1.3,-3.2 -0.6,-1.3 -1.3,-1.9 -1.3,-3.2 -0.6,-0.6 -0.6,-1.9 -1.3,-2.6 -1.3,-1.9 -2.6,-3.2 -3.8,-4.5l-224,-224c-12.8,-12.8 -32.6,-12.8 -45.4,0 -12.8,12.8 -12.8,32.6 0,45.4L786.6,384H160c-17.9,0 -32,14.1 -32,32s14.1,32 32,32zM864,576H160c-1.9,0 -3.8,0 -5.8,0.6 -1.3,0 -1.9,0.6 -2.6,0.6 -1.3,0 -1.9,0.6 -3.2,1.3 -1.3,0.6 -1.9,1.3 -3.2,1.9 -0.6,0.6 -1.9,0.6 -2.6,1.3 -1.9,1.3 -3.2,2.6 -4.5,3.8 -1.3,1.3 -2.6,3.2 -3.8,4.5 -0.6,0.6 -0.6,1.9 -1.3,2.6 -0.6,1.3 -1.3,1.9 -1.3,3.2 -0.6,1.3 -0.6,1.9 -1.3,3.2 0,0.6 -0.6,1.9 -0.6,2.6 -0.6,3.8 -0.6,8.3 0,12.8 0,0.6 0.6,1.9 0.6,2.6 0.6,1.3 0.6,1.9 1.3,3.2 0.6,1.3 1.3,1.9 1.3,3.2 0.6,0.6 0.6,1.9 1.3,2.6 1.3,1.9 2.6,3.2 3.8,4.5l224,224c6.4,6.4 14.7,9.6 22.4,9.6s16.6,-3.2 22.4,-9.6c12.8,-12.8 12.8,-32.6 0,-45.4L237.4,640H864c17.9,0 32,-14.1 32,-32s-14.1,-32 -32,-32z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#35c4f9" android:pathData="M443.9,597.3H482v142.6h-38.1z"/>
<path android:fillColor="#35c4f9" android:pathData="M511.3,64.2c-247.4,0 -448,200.6 -448,448s200.6,448 448,448 448,-200.6 448,-448 -200.5,-448 -448,-448zM647.7,450.4c0,-7.9 6.4,-14.3 14.3,-14.3s14.3,6.4 14.3,14.3v96.4c0,7.9 -6.4,14.3 -14.3,14.3s-14.3,-6.4 -14.3,-14.3v-96.4zM463,307.3c28.5,0 51.8,23.3 51.8,51.8 0,28.5 -23.3,51.8 -51.8,51.8 -28.5,0 -51.8,-23.3 -51.8,-51.8 -0.1,-28.5 23.3,-51.8 51.8,-51.8zM725.1,754.3c0,7.9 -6.4,14.3 -14.3,14.3L310.3,768.6c-7.9,0 -14.3,-6.4 -14.3,-14.3s6.4,-14.3 14.3,-14.3h109.1L419.4,449.9c-69.2,-19 -120.4,-82.1 -121,-157.1v-0.1c0,-5.9 4.8,-10.7 10.7,-10.7 5.9,0 10.7,4.8 10.7,10.7 0.7,78.3 64.6,141.8 143.1,141.8S605.3,371 606,292.7c0,-5.9 4.8,-10.7 10.7,-10.7 5.9,0 10.7,4.8 10.7,10.7 -0.6,75.1 -51.8,138.2 -121,157.3v290h190L696.4,389.7c0,-7.9 6.4,-14.3 14.3,-14.3s14.3,6.4 14.3,14.3v364.6zM725.1,337.1c0,7.9 -6.4,14.3 -14.3,14.3s-14.3,-6.4 -14.3,-14.3v-40.9c0,-7.9 6.4,-14.3 14.3,-14.3s14.3,6.4 14.3,14.3v40.9z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#20A0FF" android:pathData="M512,998.4c-268.8,0 -486.4,-217.6 -486.4,-486.4S243.2,25.6 512,25.6s486.4,217.6 486.4,486.4 -217.6,486.4 -486.4,486.4zM512,55.8c-251.9,0 -456.2,204.3 -456.2,456.2 0,251.9 204.3,456.2 456.2,456.2 251.9,0 456.2,-204.3 456.2,-456.2 0,-251.9 -204.3,-456.2 -456.2,-456.2z"/>
<path android:fillColor="#20A0FF" android:pathData="M815.1,499.7h-37.4v-1h-20.5c-10.2,0 -18.4,-8.2 -18.4,-18.4s8.2,-18.4 18.4,-18.4h20.5c-2.6,-33.8 -11.3,-66 -25.6,-95.2l-17.4,10.2c-3.1,1.5 -6.1,2.6 -9.2,2.6 -6.7,0 -12.8,-3.1 -16.4,-9.2 -5.1,-8.7 -2,-20.5 6.7,-25.6l17.4,-9.7c-18.4,-27.1 -42,-50.2 -69.1,-68.6l-10.2,17.4c-3.6,6.1 -9.7,9.2 -16.4,9.2 -3.1,0 -6.1,-1 -9.2,-2.6 -8.7,-5.1 -11.8,-16.4 -6.7,-25.6l10.2,-17.4c-29.2,-14.3 -61.4,-23 -95.7,-25.6v23c0,10.2 -8.2,18.4 -18.4,18.4s-18.4,-8.2 -18.4,-18.4v-23c-33.3,2.6 -65,11.3 -93.7,25.1l10.2,17.9c5.1,8.7 2,20 -6.7,25.6 -3.1,1.5 -6.1,2.6 -9.2,2.6 -6.7,0 -12.8,-3.1 -16.4,-9.2l-10.2,-17.9c-27.6,18.4 -51.2,42 -69.6,69.1l18.4,10.8c8.7,5.1 11.8,16.4 6.7,25.6 -3.6,6.1 -9.7,9.2 -16.4,9.2 -3.1,0 -6.1,-1 -9.2,-2.6l-18.4,-10.8c-14.3,29.2 -23.6,61.4 -26.1,95.2h20.5c10.2,0 18.4,8.2 18.4,18.4s-8.2,18.4 -18.4,18.4h-21v1.5h-37.4c-0.5,-7.2 -0.5,-13.8 -0.5,-20.5 0,-163.3 133.6,-296.4 298,-296.4s298,133.1 298,296.4c0,6.7 -0.5,13.3 -1,19.5zM324.1,641.5c5.1,-2 11.8,1.5 14.8,7.2 3.1,5.6 1.5,11.8 -3.6,13.8 -5.1,2 -11.8,-1.5 -14.8,-7.2 -3.1,-6.1 -1.5,-12.3 3.6,-13.8zM382,563.2c7.7,-2.6 17.4,2 22,10.8 4.6,8.7 2.6,17.9 -5.1,20.5s-17.4,-2 -22,-10.8c-4.6,-8.7 -2.6,-17.4 5.1,-20.5zM351.7,637.4c-6.1,2 -14.3,-1.5 -18.4,-8.7 -4.1,-7.2 -2,-14.8 4.1,-16.9 6.1,-2 14.3,1.5 18.4,8.7 4.1,7.2 2,14.8 -4.1,16.9zM357.4,587.8c7.7,-2.6 17.4,2 22,10.8 4.6,8.7 2.6,17.9 -5.1,20.5s-17.4,-2 -22,-10.8c-4.6,-8.7 -2,-17.9 5.1,-20.5zM410.6,576.5c-5.1,-10.8 -2.6,-22.5 5.1,-26.1 8.2,-3.6 18.4,2.6 23.6,13.3 5.1,10.8 2.6,22.5 -5.1,26.1 -8.2,3.6 -18.4,-2.6 -23.6,-13.3zM420.9,603.1c30.2,1 36.4,36.4 36.4,36.4 0.5,10.2 3.6,26.6 -6.1,42.5 -9.7,15.9 -25.6,79.4 12.3,109.6 37.9,29.7 20.5,62 12.3,72.7 -13.3,17.9 -67.6,14.3 -73.2,-24.1 -11.8,-82.4 -33.3,-85.5 -48.6,-109.6 -3.1,-4.6 -15.9,-42 -6.1,-60.9 14.8,-27.6 43,-67.1 73.2,-66.6zM517.6,443.4c6.7,0 12.8,2 18.4,5.1l101.4,-58.4c8.7,-5.1 20.5,-2 25.6,6.7 5.1,8.7 2,20 -6.7,25.1l-100.9,57.9c0,20.5 -16.9,36.9 -37.4,36.9s-37.4,-16.4 -37.4,-36.9c-0.5,-19.5 16.4,-36.4 36.9,-36.4zM572.4,591.4c-8.2,-3.6 -10.2,-14.8 -5.1,-25.6s15.4,-16.9 23.6,-13.3c8.2,3.6 10.2,14.8 5.1,25.6 -5.1,10.2 -15.4,16.4 -23.6,13.3zM543.7,792.6c37.9,-29.7 21.5,-93.2 12.3,-109.1 -9.7,-15.9 -6.1,-32.3 -6.1,-42.5 0,0 6.1,-35.8 36.4,-36.4 30.2,-1 57.9,38.9 72.2,66.6 9.7,18.4 -3.1,55.8 -6.1,60.4 -15.4,24.1 -36.9,26.6 -48.1,109.1 -5.6,38.4 -58.9,42 -72.2,24.1 -8.7,-10.2 -26.1,-42.5 11.8,-72.2zM668.2,612.9c6.1,2 8.2,9.7 4.1,16.9s-12.3,11.3 -18.4,8.7c-6.1,-2 -8.2,-9.7 -4.1,-16.9s12.3,-10.8 18.4,-8.7zM607.2,596c-7.2,-2.6 -9.7,-11.8 -5.1,-20.5 4.6,-8.7 14.3,-13.3 22,-10.8 7.2,2.6 9.7,11.8 5.1,20.5 -4.6,8.7 -14.3,13.3 -22,10.8zM648.7,588.8c7.2,2.6 9.7,11.8 5.1,20.5 -4.6,8.7 -14.3,13.3 -22,10.8 -7.2,-2.6 -9.7,-11.8 -5.1,-20.5 4.6,-8.7 14.3,-13.3 22,-10.8zM682,642.6c5.1,2 6.7,7.7 3.1,13.8 -3.1,5.6 -9.7,8.7 -14.3,7.2 -5.1,-2 -6.7,-7.7 -3.1,-13.8 2.6,-5.6 9.2,-8.7 14.3,-7.2z"/>
</vector>

View File

@@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ffffff" android:pathData="M512,62.4c-248.3,0 -449.6,201.3 -449.6,449.6s201.3,449.6 449.6,449.6 449.6,-201.3 449.6,-449.6S760.3,62.4 512,62.4zM728.1,403.9 L478.8,653.3c-4.6,4.6 -10.6,6.9 -16.6,6.9s-12,-2.3 -16.6,-6.9c-37.4,-37.4 -149.6,-149.6 -149.6,-149.6 -9.2,-9.2 -9.2,-24.1 0,-33.2 9.2,-9.2 24.1,-9.2 33.2,0l133,109.5 232.7,-209.2c9.2,-9.2 24.1,-9.2 33.2,0C737.3,379.9 737.3,394.8 728.1,403.9z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ff5b20" android:pathData="M826.3,128.6c-50.8,176.8 -184.4,77.2 -341.4,253.9 -157,176.7 -48.6,375.6 -48.6,375.6l-92.8,75.2 78.9,57.4 91.2,-68.6c311.7,94.5 439.9,-150.4 439.9,-150.4 166.6,-347.3 -127.3,-543.2 -127.3,-543.2zM648.8,647.9C534.7,756.7 430.9,830.3 430.9,830.3l-6.8,-8.1c123.8,-92.8 214.1,-166.8 276.1,-244.4 -11.9,-15.4 -37.8,-64.6 -29,-197.8l7.9,1.3s-11.2,106.6 18.9,166.8c0,0 8.1,14.9 18.3,8.8 126.1,-158.3 133,-284.2 133,-284.2h8.1c-13.4,126.6 -90.8,245.3 -176.3,340.3l0.4,-0.2c-17.8,20.2 -10.1,29.9 -10.1,29.9 85.8,27.7 224.2,-45.5 224.2,-45.5l4.4,6.6c-139.6,75 -226.6,51.2 -251.3,44.2z"/>
<path android:fillColor="#f54e4b" android:pathData="M678.2,902.6a421.9,421.9 0,0 1,-164.2 33.2C280.1,935.8 90,745.7 90,512c0,-233.7 190.2,-423.8 423.8,-423.8 58.3,0 113.6,11.9 164.2,33.2l53.4,-53.4c-65.7,-32.3 -139.6,-50.6 -217.6,-50.6C241,17.4 19.2,239.2 19.2,512c0,272.8 221.8,494.6 494.6,494.6 78,0 151.9,-18.3 217.6,-50.6l-53.2,-53.4z"/>
</vector>

View File

@@ -0,0 +1,7 @@
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ffffff" android:pathData="M893.7,295.5C835.9,204.1 745.9,140.7 640.4,117c-105.5,-23.6 -213.9,-4.9 -305.4,53 -103.3,65.3 -169.9,171.3 -185,290.2l-43.3,-64.4c-6.6,-9.7 -19.8,-12.3 -29.7,-5.8 -9.8,6.6 -12.4,19.9 -5.8,29.7l75,111.5c3.5,5.1 9,8.5 15.1,9.2 1,0.2 2.2,0.3 3.1,0.2 5.1,-0.2 10,-2.1 13.8,-5.5l91.2,-82.3c8.8,-8 9.5,-21.5 1.6,-30.2 -8,-8.8 -21.5,-9.4 -30.2,-1.6l-48.2,43.6c13.8,-106 73.3,-200.3 165.3,-258.5 81.7,-51.8 178.8,-68.6 273.2,-47.4 94.4,21.2 174.9,77.9 226.7,159.6 51.8,81.7 68.5,178.8 47.3,273.2 -21.2,94.4 -77.8,174.9 -159.6,226.6 -81.7,51.9 -178.8,68.6 -273.2,47.3 -94.4,-21.1 -174.9,-77.9 -226.6,-159.6 -6.3,-9.9 -19.5,-12.8 -29.5,-6.6 -10,6.3 -13,19.5 -6.7,29.5C286.4,850.3 417.9,917 552.2,917c74,0 148.9,-20.2 215.9,-62.7C957,734.8 1013.2,484.1 893.7,295.5zM893.7,295.5"/>
<path android:fillColor="#ffffff" android:pathData="M552.2,919.6c-140.9,0 -269.9,-70.8 -345,-189.5 -7,-11.1 -3.7,-26 7.4,-33.1 3.9,-2.4 8.4,-3.7 12.9,-3.7 8.3,0 15.9,4.1 20.2,11.1 51.6,81.3 131.5,137.6 225,158.4 26.3,6 53.1,9 79.8,9 67.6,0 133.8,-19.4 191.4,-55.9 81.1,-51.2 137.4,-131.2 158.5,-225 21,-93.8 4.3,-190.1 -47,-271.2C804,238.6 724,182.3 630.3,161.2c-26.2,-5.9 -52.9,-8.9 -79.4,-8.9 -67.7,0 -134,19.4 -191.8,55.9 -88.4,55.9 -147.6,146.6 -163.1,249.5l43,-38.7c4.4,-4 10.1,-6.1 16.1,-6.1 6.8,0 13.3,2.9 17.8,7.9 8.8,9.8 8,25 -1.7,34L179.9,537c-4.3,3.8 -9.8,6 -15.5,6.1 -0.7,0.2 -2.3,0 -3.6,-0.2 -6.8,-0.8 -13,-4.6 -16.9,-10.4l-75,-111.4c-3.6,-5.4 -4.9,-11.7 -3.6,-18.1 1.2,-6.3 4.8,-11.7 10.2,-15.3 4,-2.6 8.6,-4 13.4,-4 8,0 15.5,4 19.9,10.6l39.5,58.8c17,-117.6 84.2,-221.3 185.3,-285.3 65.5,-41.5 140.6,-63.4 217.3,-63.4 30.1,0 60.4,3.4 90.1,10 106.3,23.9 196.8,87.7 255,179.6 58.2,91.8 77.1,201 53.2,307.3 -23.9,106.4 -87.7,196.9 -179.6,255.1 -65.3,41.4 -140.4,63.2 -217.4,63.2zM227.5,698.6c-3.6,0 -7,1 -10.1,2.9 -8.9,5.6 -11.4,17 -5.9,25.9 74.2,117.1 201.6,187 340.6,187 76,0 150.2,-21.6 214.6,-62.3 90.7,-57.4 153.7,-146.8 177.2,-251.8 23.6,-105 4.9,-212.7 -52.5,-303.4 -57.5,-90.8 -146.9,-153.7 -251.7,-177.3 -29.3,-6.6 -59.3,-9.9 -88.9,-9.9 -75.7,0 -149.8,21.6 -214.5,62.5 -101.7,64.4 -168.7,169.4 -183.8,288.3l-0.9,6.9 -47.2,-70.2c-3.5,-5.2 -9.3,-8.3 -15.6,-8.3 -3.7,0 -7.3,1.1 -10.5,3.2 -4.1,2.8 -7,7 -8,11.9s0.1,9.9 2.9,14.1l75,111.5c3.1,4.5 7.9,7.5 13.3,8.1 0.7,0.1 1.3,0.2 1.9,0.2l0.8,-0.1c4.5,-0.2 8.8,-1.8 12.2,-4.8l91.2,-82.3c7.6,-7 8.3,-18.9 1.4,-26.6 -6.7,-7.4 -19.2,-8 -26.6,-1.4L189,471.3l0.9,-7c14,-107.4 74.7,-202.3 166.5,-260.3 58.6,-37.1 125.9,-56.8 194.5,-56.8 26.9,0 54,3 80.6,9 95.2,21.4 176.2,78.5 228.3,160.8 52.1,82.3 69,180 47.7,275.1 -21.4,95.2 -78.5,176.3 -160.8,228.2 -58.5,37.1 -125.6,56.8 -194.2,56.8 -27,0 -54.3,-3.1 -80.9,-9.1 -94.9,-21.2 -176,-78.3 -228.3,-160.8 -3.4,-5.4 -9.3,-8.6 -15.8,-8.6z"/>
<path android:fillColor="#ffffff" android:pathData="M539.3,235.9c-17,0 -30.8,13.8 -30.8,30.9v264.3c0,8.2 3.2,16.1 9,21.8l152.3,152.3c6,6 13.9,9 21.9,9 7.9,0 15.8,-3 21.8,-9 12.1,-12.1 12.1,-31.6 0,-43.7L570.2,518.3L570.2,266.8c0,-17.1 -13.8,-30.9 -30.9,-30.9zM539.3,235.9"/>
<path android:fillColor="#ffffff" android:pathData="M691.7,716.8c-9,0 -17.4,-3.5 -23.7,-9.8L515.7,554.8c-6.2,-6.2 -9.8,-14.8 -9.8,-23.7V266.8c0,-18.5 15,-33.6 33.4,-33.6 18.5,0 33.5,15 33.5,33.6v250.4l142.6,142.5c13,13.1 13,34.3 0,47.4 -6.4,6.3 -14.8,9.7 -23.7,9.7zM539.3,238.5c-15.6,0 -28.2,12.7 -28.2,28.4v264.3c0,7.5 3,14.8 8.3,20l152.3,152.3c5.4,5.3 12.4,8.3 20,8.3 7.5,0 14.6,-3 20,-8.3 11,-11 11,-29 0,-40l-144.1,-144V266.8c0,-15.6 -12.7,-28.3 -28.3,-28.3z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#35c4f9" android:pathData="M512,1024C229.2,1024 0,794.8 0,512S229.2,0 512,0s512,229.2 512,512 -229.2,512 -512,512zM512,983c260.1,0 471,-210.9 471,-471C983,251.9 772.1,41 512,41 251.9,41 41,251.9 41,512c0,260.1 210.9,471 471,471z"/>
<path android:fillColor="#35c4f9" android:pathData="M640,341.3L640,277.3a21.3,21.3 0,1 1,42.7 0L682.7,341.3h64a21.3,21.3 0,1 1,0 42.7L682.7,384v64a21.3,21.3 0,1 1,-42.7 0L640,384h-64a21.3,21.3 0,1 1,0 -42.7L640,341.3zM607.1,690.9a28.2,28.2 0,0 1,1.1 7.8,26.2 26.2,0 0,1 -8,19.1 26.8,26.8 0,0 1,-19.7 8.1c-13.3,0 -22,-6.5 -26.1,-19.4l-17.7,-60.5c-0.4,-1.8 -1.7,-2.8 -3.9,-2.8L407.4,643.2c-2.2,0 -3.5,0.9 -3.9,2.8l-17.7,60.5c-4.1,12.9 -12.8,19.4 -26.1,19.4a26.8,26.8 0,0 1,-19.7 -8.1,26.2 26.2,0 0,1 -8,-19.1 28.2,28.2 0,0 1,1.1 -7.8l110.9,-376.6c3.7,-12.9 12.4,-19.4 26.1,-19.4 13.7,0 22.4,6.5 26.1,19.4l110.9,376.6zM518.9,585.6l-47.7,-162.5c0,-0.7 -0.4,-1.1 -1.1,-1.1s-1.1,0.4 -1.1,1.1l-47.7,162.5c-0.7,1.8 0,2.8 2.2,2.8h93.2c2.2,0 3,-0.9 2.2,-2.8z"/>
</vector>

View File

@@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ffffff" android:pathData="M689,596c30,-47.2 47.6,-103.2 47.6,-163.4 0,-168.2 -136.2,-304.6 -304.2,-304.6C264.2,128 128,264.4 128,432.6c0,168.2 136.2,304.6 304.2,304.6 61,0 117.8,-18 165.4,-48.8l13.8,-9.6L828.6,896l67.4,-68.6 -217,-217.2 10,-14.2zM602.8,262.4c45.4,45.4 70.4,105.8 70.4,170s-25,124.6 -70.4,170c-45.4,45.4 -105.8,70.4 -170,70.4s-124.6,-25 -170,-70.4c-45.4,-45.4 -70.4,-105.8 -70.4,-170s25,-124.6 70.4,-170c45.4,-45.4 105.8,-70.4 170,-70.4s124.6,25 170,70.4z"/>
</vector>

View File

@@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#35f9e9" android:pathData="M893.3,219c-66.7,94.3 -156.1,105.2 -252.2,47.6 -6.5,-3.9 -35.6,-20 -42,-23.9 -154.7,-92.6 -309.2,-56.3 -412.8,90 -44,62.2 57.8,121.2 101.3,59.7 53.5,-75.6 121.6,-97.5 196,-73.5 -38.1,66.7 -71.4,133.1 -118.5,227.3 -47,94.2 -150.9,169.5 -250.7,110.6 -72,-42.4 -136.9,61.9 -65.1,104.2 136.2,80.3 296,31 377.5,-73.4 2.8,1.5 5.8,2.9 9.1,4.1 66.6,23.4 153.9,85.7 180.5,107.8 26.6,22.1 72.3,134.6 99.4,191.2 32.9,68.6 139.2,18.6 106.2,-50.3 -30.8,-64.1 -82.4,-192.2 -122.7,-224.6 -32.3,-26 -95,-74.3 -148.2,-101.8 36,-70.3 73.5,-139.9 112.9,-208.2 125.8,38.9 245.3,-6.9 330.4,-127.2C1038.7,216.4 936.9,157.4 893.3,219zM702.2,252.7c64.2,0 116.2,-52.5 116.2,-117.2 0,-64.7 -52,-117.2 -116.2,-117.2C638,18.3 586,70.8 586,135.5 586,200.2 638,252.7 702.2,252.7z"/>
</vector>

View File

@@ -0,0 +1,6 @@
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#35c4f9" android:pathData="M652.8,278.7a137.5,137.5 0,0 0,-102 -46.9h-79.3a137.5,137.5 0,0 0,-102 46.9l-127,142.8a18.4,18.4 0,0 0,0 25.5l43.4,43.4a17.3,17.3 0,0 0,13.3 5.4,16.8 16.8,0 0,0 12.5,-6.1l90.5,-106.1v467.3a17.6,17.6 0,0 0,17.6 17.9h60.7a17.6,17.6 0,0 0,17.6 -17.9V578.7h25.5v272.2a17.6,17.6 0,0 0,17.6 17.9h60.5a17.6,17.6 0,0 0,17.6 -17.9V383.5l90.5,106.1a17.9,17.9 0,0 0,12.8 6.1,17.6 17.6,0 0,0 13,-5.4l42.9,-43.9a18.4,18.4 0,0 0,0 -25.5l-126,-142.8zM510.2,205.8a100,100 0,0 0,98.5 -102,98.7 98.7,0 1,0 -197.2,0 100.2,100.2 0,0 0,98.7 102z"/>
<path android:fillColor="#35c4f9" android:pathData="M879.6,800.1c-46.7,-37.5 -124.7,-56.9 -177.3,-66.6a29.8,29.8 0,0 0,-36.2 25.5,30.4 30.4,0 0,0 25.5,36.7 378.5,378.5 0,0 1,138.5 46.2c19.9,12.8 27.8,25.5 27.8,31.1a16.3,16.3 0,0 1,-3.3 9.2c-21.2,31.6 -140.3,82.9 -344.3,82.9 -224.2,0 -347.1,-58.7 -347.1,-91.8 0,-14.8 39.8,-55.3 162.7,-76.5a30.4,30.4 0,0 0,25.5 -36.7,29.8 29.8,0 0,0 -36.2,-25.5c-79.6,14.5 -213.2,51 -213.2,135.9C102.1,973 304.7,1024 506.9,1024c202.5,0 408.1,-51 412.2,-150.7v-7.9,-3.1"/>
<path android:fillColor="#35c4f9" android:pathData="M514.3,1024C716.9,1024 918.4,973 918.4,869.4c0,-84.4 -133.7,-121.4 -213.2,-135.9a29.8,29.8 0,0 0,-36.2 25.5,30.4 30.4,0 0,0 25.5,36.7c122.7,21.9 162.5,62.5 162.5,76.5 0,33.2 -122.7,91.8 -346.9,91.8"/>
</vector>

View File

@@ -0,0 +1,6 @@
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ffffff" android:pathData="M620.1,338.7c-31,-11 -63.7,-16.5 -97.1,-16.5 -16.8,0 -39.3,3.1 -66.8,9.3 -7.5,1.7 -12.2,9.1 -10.5,16.5 1.7,7.5 9.1,12.2 16.6,10.5 25.2,-5.6 46.2,-8.6 60.8,-8.6 30.3,0 59.9,5 87.9,14.9 1.5,0.5 3.1,0.8 4.6,0.8 5.7,0 11.1,-3.5 13.1,-9.2C631.1,349.1 627.3,341.2 620.1,338.7z"/>
<path android:fillColor="#ffffff" android:pathData="M350.3,389.2c-8.6,0 -15.6,13 -15.6,29.1s7,29.1 15.6,29.1 15.6,-13 15.6,-29.1S358.9,389.2 350.3,389.2z"/>
<path android:fillColor="#ffffff" android:pathData="M512.1,65.5C265.7,65.5 65.9,265.3 65.9,511.8c0,246.5 199.8,446.3 446.3,446.3 246.5,0 446.3,-199.8 446.3,-446.3C958.4,265.3 758.6,65.5 512.1,65.5zM818.2,617.9c-9.5,-0.7 -27.9,-3.9 -48.4,-18.4 -6.1,22.7 -15.9,45.6 -29.7,68.2 -8,13.1 -44.8,74.9 -64,74.9 -30,0 -76,0 -76,0 -7.6,0 -13.1,-6.5 -12.2,-14l1.2,-19.3c0.1,-7.6 -6,-12.8 -13.5,-11.5 0,0 -32.8,5.8 -57.5,5.8 -16.3,0 -35.1,-2.2 -35.1,-2.2 -7.6,-0.9 -15.2,4.5 -16.9,12l-4.5,15.8c-2.4,7.2 -10.7,13.4 -18.3,13.4l-62.2,0c-7.6,0 -13.4,-6.5 -12.8,-14.1l-0.8,-52.1c-0.9,-7.6 -4.1,-15.4 -7.2,-17.3 0,0 -0,0 -2.8,-1.8 -42.1,-28 -55.3,-71.7 -108.1,-71.8 -13,-0 -18.6,-14.5 -18.6,-14.5 -2.7,-7.1 -5.2,-19.2 -5.2,-26.8l0,-56.1c0,-7.6 2.4,-19.7 5.2,-26.8 0,0 5.8,-14.5 18.8,-14.5 38.3,0 34.4,-25.8 54.9,-52.8 9.6,-12.6 24.8,-25.6 24.8,-25.6 5.8,-5 6.9,-14.1 2.6,-20.4 0,0 -34.6,-49.5 -44.7,-62.1 -2.4,-3 -1.3,-5.3 2.6,-5.1 48.4,3.2 95.8,36.2 95.8,36.2 6.2,4.4 17.3,6.1 24.6,3.9 0,0 67,-20.4 107.9,-20.4 122.4,0 223.4,78.3 251.7,180.9 6.8,24.6 9.4,50.7 7.1,77.4 9.4,18.3 25.9,46.6 41.8,56.2C822.1,617.1 822.1,618.2 818.2,617.9z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

View File

@@ -11,74 +11,141 @@
app:edMenuSize="230dp"
app:edPosition="1">
<FrameLayout
<RelativeLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
<FrameLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
app:contentInsetStart="0dp"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
android:layout_height="wrap_content">
<FrameLayout
android:id="@+id/bar_cover"
android:layout_width="match_parent"
android:layout_height="110dp"
android:background="@color/bar_open"
android:visibility="gone">
</FrameLayout>
<LinearLayout
android:id="@+id/navigation_layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:contentInsetStart="0dp"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/navigation_layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_drawer_home" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_drawer_home" />
<com.github.siyamed.shapeimageview.CircularImageView
android:id="@+id/toolbar_user_avatar"
android:layout_width="34dp"
android:layout_height="31dp"
android:layout_marginEnd="3dp"
android:layout_marginStart="15dp"
android:src="@drawable/test_avatar" />
<com.github.siyamed.shapeimageview.CircularImageView
android:id="@+id/toolbar_user_avatar"
android:layout_width="34dp"
android:layout_height="31dp"
android:layout_marginEnd="3dp"
android:layout_marginStart="15dp"
android:src="@drawable/test_avatar" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:maxLines="1"
android:text="营养大师"
android:textColor="#FFFF"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:maxLines="1"
android:text="营养大师"
android:textColor="#FFFF"
android:textSize="15sp" />
</LinearLayout>
<!--<LinearLayout-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="match_parent"-->
<!--android:layout_alignParentRight="true"-->
<!--android:gravity="center_vertical"-->
<!--android:orientation="horizontal">-->
<!--<ImageView-->
<!--android:id="@+id/exchange_button"-->
<!--android:layout_width="@dimen/icon_size"-->
<!--android:layout_height="@dimen/icon_size"-->
<!--android:src="@drawable/ic_exchange" />-->
<!--<TextView-->
<!--android:layout_width="20dp"-->
<!--android:layout_height="match_parent" />-->
<!--<ImageView-->
<!--android:id="@+id/record_button"-->
<!--android:layout_width="22dp"-->
<!--android:layout_height="22dp"-->
<!--android:src="@drawable/ic_record" />-->
<!--<TextView-->
<!--android:layout_width="20dp"-->
<!--android:layout_height="match_parent" />-->
<!--<ImageView-->
<!--android:id="@+id/search_button"-->
<!--android:layout_width="18dp"-->
<!--android:layout_height="18dp"-->
<!--android:src="@drawable/ic_search" />-->
<!--<TextView-->
<!--android:layout_width="25dp"-->
<!--android:layout_height="match_parent" />-->
<!--</LinearLayout>-->
</RelativeLayout>
</android.support.v7.widget.Toolbar>
<com.flyco.tablayout.SlidingTabLayout
android:id="@+id/sliding_tab_layout"
android:layout_width="match_parent"
android:layout_height="48dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
app:tl_indicator_corner_radius="1dp"
app:tl_indicator_height="2dp"
app:tl_indicator_width="40dp"
app:tl_tab_space_equal="true">
</com.flyco.tablayout.SlidingTabLayout>
</LinearLayout>
</android.support.v7.widget.Toolbar>
<com.flyco.tablayout.SlidingTabLayout
android:id="@+id/sliding_tab_layout"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@color/colorPrimary"
android:paddingLeft="10dp"
android:paddingRight="10dp"
app:tl_indicator_corner_radius="1dp"
app:tl_indicator_height="2dp"
app:tl_indicator_width="40dp"
app:tl_tab_space_equal="true">
</com.flyco.tablayout.SlidingTabLayout>
</FrameLayout>
</android.support.design.widget.AppBarLayout>
<com.example.ninefourone.nutritionmaster.ui.NoScrollViewPager
@@ -89,7 +156,22 @@
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
</FrameLayout>
<com.miguelcatalan.materialsearchview.MaterialSearchView
android:id="@+id/search_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.nightonke.boommenu.BoomMenuButton
android:id="@+id/boom_menu_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
app:bmb_buttonEnum="ham"
app:bmb_buttonPlaceEnum="buttonPlace_ham_2"
app:bmb_piecePlaceEnum="piecePlace_ham_2" />
</RelativeLayout>
<!--menu-->
<com.mxn.soul.flowingdrawer_core.FlowingMenuLayout
@@ -102,31 +184,415 @@
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="@color/colorPrimary"
android:gravity="center"
android:orientation="vertical">
<com.github.siyamed.shapeimageview.CircularImageView
android:id="@+id/drawer_user_avatar"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/test_avatar" />
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginTop="10dp">
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="110dp"
android:layout_height="match_parent"
android:text="ScorpioMiku"
android:textColor="#FFF" />
android:gravity="center"
android:orientation="vertical">
<com.github.siyamed.shapeimageview.CircularImageView
android:id="@+id/drawer_user_avatar"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/test_avatar" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginTop="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="ScorpioMiku"
android:textColor="#FFF" />
</RelativeLayout>
</LinearLayout>
<ImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="10dp"
android:layout_marginEnd="10dp"
android:alpha="0.2"
android:src="@drawable/icon_black" />
</RelativeLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="5dp" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="36dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="65dp"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_score" />
<TextView
android:layout_width="wrap_content"
android:layout_height="10dp"
android:text="体质"
android:textColor="@color/colorPrimary"
android:textSize="8sp" />
</LinearLayout>
<com.cb.ratingbar.CBRatingBar
android:id="@+id/cb_rating_bar"
android:layout_width="150dp"
android:layout_height="36dp"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
android:layout_marginTop="3dp"
app:starCanTouch="true"
app:starCount="5"
app:starCoverDir="left_to_right"
app:starEndColor="#2a00ff"
app:starFillColor="#c6c6c6"
app:starMaxProgress="120"
app:starPathData="@string/pig"
app:starProgress="60"
app:starShowStroke="false"
app:starSize="20dp"
app:starSpace="10dp"
app:starStartColor="#30e2f5"
app:starStrokeWidth="1dp"
app:starUseGradient="true" />
</RelativeLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false">
<!--<me.panpf.swsv.SpiderWebScoreView-->
<!--android:id="@+id/spiderWeb_mainActivity"-->
<!--android:layout_width="100dp"-->
<!--android:layout_height="100dp"-->
<!--android:layout_gravity="center"-->
<!--app:scoreColor="@color/colorPrimary"-->
<!--app:scoreStrokeColor="@color/colorPrimary" />-->
<!--<me.panpf.swsv.CircularLayout-->
<!--android:id="@+id/layout_mainActivity_circular"-->
<!--android:layout_width="100dp"-->
<!--android:layout_height="100dp"-->
<!--android:layout_gravity="center"-->
<!--android:clipChildren="false" />-->
<com.github.mikephil.charting.charts.RadarChart
android:id="@+id/spider_view"
android:layout_width="170dp"
android:layout_height="170dp"
android:layout_gravity="center">
</com.github.mikephil.charting.charts.RadarChart>
</FrameLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="65dp"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_bmi" />
<TextView
android:layout_width="wrap_content"
android:layout_height="10dp"
android:text="BMI值"
android:textColor="@color/colorPrimary"
android:textSize="8sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="8dp"
android:layout_height="8dp"
android:background="@color/color_bar_self" />
<TextView
android:layout_width="wrap_content"
android:layout_height="8dp"
android:text="@string/self_information"
android:textSize="5sp" />
<TextView
android:layout_width="8dp"
android:layout_height="8dp"
android:background="@color/color_bar_deeper" />
<TextView
android:layout_width="wrap_content"
android:layout_height="8dp"
android:text="@string/standrad_information"
android:textSize="5sp" />
</LinearLayout>
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.5" />
</LinearLayout>
<com.akexorcist.roundcornerprogressbar.RoundCornerProgressBar
android:layout_width="145dp"
android:layout_height="36dp"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
android:layout_marginTop="3dp"
app:rcBackgroundColor="@color/color_bar_background"
app:rcBackgroundPadding="5dp"
app:rcMax="100"
app:rcProgress="56.6"
app:rcProgressColor="@color/color_bar_self"
app:rcRadius="10dp"
app:rcReverse="false"
app:rcSecondaryProgress="74.1"
app:rcSecondaryProgressColor="@color/color_bar_deeper" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="65dp"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_height" />
<TextView
android:layout_width="wrap_content"
android:layout_height="10dp"
android:text="身高"
android:textColor="@color/colorPrimary"
android:textSize="8sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="8dp"
android:layout_height="8dp"
android:background="@color/color_bar_self" />
<TextView
android:layout_width="wrap_content"
android:layout_height="8dp"
android:text="@string/self_information"
android:textSize="5sp" />
<TextView
android:layout_width="8dp"
android:layout_height="8dp"
android:background="@color/color_bar_deeper" />
<TextView
android:layout_width="wrap_content"
android:layout_height="8dp"
android:text="@string/standrad_information"
android:textSize="5sp" />
</LinearLayout>
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.5" />
</LinearLayout>
<com.akexorcist.roundcornerprogressbar.RoundCornerProgressBar
android:layout_width="145dp"
android:layout_height="36dp"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
android:layout_marginTop="3dp"
app:rcBackgroundColor="@color/color_bar_background"
app:rcBackgroundPadding="5dp"
app:rcMax="100"
app:rcProgress="16.6"
app:rcProgressColor="@color/color_bar_self"
app:rcRadius="10dp"
app:rcReverse="false"
app:rcSecondaryProgress="32.1"
app:rcSecondaryProgressColor="@color/color_bar_deeper" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="65dp"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_weight" />
<TextView
android:layout_width="wrap_content"
android:layout_height="10dp"
android:text="体重"
android:textColor="@color/colorPrimary"
android:textSize="8sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="8dp"
android:layout_height="8dp"
android:background="@color/color_bar_self" />
<TextView
android:layout_width="wrap_content"
android:layout_height="8dp"
android:text="@string/self_information"
android:textSize="5sp" />
<TextView
android:layout_width="8dp"
android:layout_height="8dp"
android:background="@color/color_bar_deeper" />
<TextView
android:layout_width="wrap_content"
android:layout_height="8dp"
android:text="@string/standrad_information"
android:textSize="5sp" />
</LinearLayout>
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.5" />
</LinearLayout>
<com.akexorcist.roundcornerprogressbar.RoundCornerProgressBar
android:layout_width="145dp"
android:layout_height="36dp"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
android:layout_marginTop="3dp"
app:rcBackgroundColor="@color/color_bar_background"
app:rcBackgroundPadding="5dp"
app:rcMax="100"
app:rcProgress="32.6"
app:rcProgressColor="@color/color_bar_self"
app:rcRadius="10dp"
app:rcReverse="false"
app:rcSecondaryProgress="56.1"
app:rcSecondaryProgressColor="@color/color_bar_deeper" />
</RelativeLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
</com.mxn.soul.flowingdrawer_core.FlowingMenuLayout>

View File

@@ -1,39 +1,335 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/cardview_dark_background"
android:gravity="center"
android:orientation="vertical">
android:overScrollMode="never"
android:scrollbars="none
">
<com.akexorcist.roundcornerprogressbar.RoundCornerProgressBar
android:id="@+id/progress_1"
android:layout_width="150dp"
android:layout_height="40dp"
app:rcBackgroundPadding="5dp" />
<TextView
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp" />
android:layout_height="match_parent"
android:orientation="vertical">
<com.akexorcist.roundcornerprogressbar.IconRoundCornerProgressBar
android:id="@+id/progress_2"
android:layout_width="150dp"
android:layout_height="wrap_content"
app:rcBackgroundColor="#ece9e9"
app:rcBackgroundPadding="5dp"
app:rcIconPadding="5dp"
app:rcIconSize="50dp"
app:rcRadius="10dp" />
<ImageView
android:layout_width="match_parent"
android:layout_height="180dp"
android:scaleType="fitXY"
android:src="@drawable/body_bg" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/infor_layout_height"
android:orientation="horizontal">
<com.gelitenight.waveview.library.WaveView
android:id="@+id/wave_view"
android:layout_width="200dp"
android:layout_height="200dp" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
</LinearLayout>
<ImageView
android:layout_width="@dimen/infor_image_height"
android:layout_height="@dimen/infor_image_height"
android:src="@drawable/ic_power" />
</RelativeLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="3"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="能量记录"
android:textSize="15sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="还可以再吃"
android:textSize="10sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="1804"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="千卡"
android:textSize="10sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:gravity="center"
android:orientation="vertical">
<me.itangqi.waveloadingview.WaveLoadingView
android:id="@+id/waveLoadingView"
android:layout_width="90dp"
android:layout_height="90dp"
app:wlv_borderColor="#ff5b20"
app:wlv_borderWidth="3dp"
app:wlv_progressValue="40"
app:wlv_round_rectangle="true"
app:wlv_shapeType="circle"
app:wlv_titleCenter="今日卡路里"
app:wlv_titleCenterColor="@android:color/white"
app:wlv_titleCenterSize="10sp"
app:wlv_titleCenterStrokeColor="#f52121"
app:wlv_titleCenterStrokeWidth="3dp"
app:wlv_triangle_direction="north"
app:wlv_waveAmplitude="70"
app:wlv_waveColor="#f54e4b" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="0.1dp"
android:background="@color/place_holder" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/infor_layout_height"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<ImageView
android:layout_width="@dimen/infor_image_height"
android:layout_height="@dimen/infor_image_height"
android:src="@drawable/ic_infor_weight" />
</RelativeLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="3"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="体重记录"
android:textSize="15sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="1804"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="公斤"
android:textSize="10sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:gravity="center"
android:orientation="vertical">
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/weight_line_chart"
android:layout_width="150dp"
android:layout_height="@dimen/infor_chart_height">
</com.github.mikephil.charting.charts.LineChart>
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="0.1dp"
android:background="@color/place_holder" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/infor_layout_height"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<ImageView
android:layout_width="@dimen/infor_image_height"
android:layout_height="@dimen/infor_image_height"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_step" />
</RelativeLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="3"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="今日步数"
android:textSize="15sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/step_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="1804"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="步"
android:textSize="10sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:gravity="center"
android:orientation="vertical">
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/step_line_chart"
android:layout_width="150dp"
android:layout_height="@dimen/infor_chart_height">
</com.github.mikephil.charting.charts.LineChart>
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="0.1dp"
android:background="@color/place_holder" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="9">
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<TextView
android:id="@+id/results_text_view"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
tools:text="@string/app_name" />
</FrameLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.2"
android:alpha="0.4"
android:background="#8A000000">
<ImageView
android:id="@+id/more_take_photo_button_capture"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:src="@drawable/selector" />
<ImageView
android:id="@+id/more_takephoto_ok"
android:layout_width="50dp"
android:layout_height="60dp"
android:layout_centerVertical="true"
android:layout_marginLeft="50dp"
android:layout_marginTop="15dp"
android:layout_toRightOf="@id/more_take_photo_button_capture"
android:src="@drawable/ic_ok" />
</RelativeLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/more_camera_cover_linearlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.3"
android:background="@color/place_holder"
android:visibility="invisible">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
</FrameLayout>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="420dp"
android:layout_gravity="center"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="10dp"
app:cardCornerRadius="5dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_photo"
android:layout_width="match_parent"
android:layout_height="350dp"
/>
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/iv_photo"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="Rachel"
android:textColor="#000000"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_sign"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tv_name"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="其他"
android:textSize="10sp" />
</RelativeLayout>
</android.support.v7.widget.CardView>

View File

@@ -0,0 +1,13 @@
<?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:gravity="center">
<android.support.v7.widget.RecyclerView
android:id="@+id/card_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/cardview_dark_background">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="page1" />
</android.support.constraint.ConstraintLayout>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="10sp">
</TextView>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/id_action_exchange"
android:icon="@drawable/ic_exchange"
android:title="切换"
app:showAsAction="always"
/>
<item
android:id="@+id/id_action_record"
android:icon="@drawable/ic_record"
android:orderInCategory="100"
android:title="浏览记录"
app:showAsAction="always"
/>
<item
android:id="@+id/id_action_search"
android:icon="@drawable/ic_search"
android:orderInCategory="100"
android:title="搜索"
app:showAsAction="always"
/>
</menu>

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="sections">
<item>page1</item>
<item>page2</item>
<item>一周定制</item>
<item>今日信息</item>
<item>page3</item>
</string-array>
</resources>

View File

@@ -1,13 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#FF03A9F4</color>
<color name="colorPrimaryDark">#ff0171c9</color>
<color name="colorPrimary">#25d43c</color>
<color name="colorPrimaryDark">#17a346</color>
<color name="colorAccent">#FF00E5FF</color>
<color name="colorControlNormal">#FF78909C</color>
<color name="colorControlActivated">#FF03A9F4</color>
<color name="colorSwitchThumbNormal">#FF78909C</color>
<color name="bar_open">#17a346</color>
<color name="place_holder">#b3b3b3</color>
<color name="color_bar_background">#e6e5e5</color>
<color name="color_bar_deeper">#52ec2f</color>
<color name="color_bar_self">#9ac3f9</color>
<color name="spider_view_color">#ff0000</color>
</resources>

View File

@@ -12,4 +12,13 @@
<dimen name="bt_height">36dp</dimen>
<dimen name="infor_layout_height">120dp</dimen>
<dimen name="infor_image_height">35dp</dimen>
<dimen name="infor_chart_height">90dp</dimen>
<dimen name="infor_chart_width">200dp</dimen>
<dimen name="icon_size">20dp</dimen>
</resources>

View File

@@ -1,3 +1,8 @@
<resources>
<string name="app_name">NutritionMaster</string>
<string name="self_information">当前值</string>
<string name="standrad_information">标准值</string>
<string name="pig">M1080.3,453.7c-77.2,88.2 -214.6,234.4 -214.6,234.4s22,160.2 35.3,269.7c5.9,55.9 -37.5,80.1 -86,58.1 -92.6,-43.4 -233.7,-111 -265.3,-126.4 -32.3,14.7 -174.2,81.6 -267.5,124.9 -49.2,21.3 -92.6,-2.2 -87.5,-58.1 12.5,-109.5 35.3,-269 35.3,-269S91.1,541.9 13.2,453.7c-27.9,-32.3 -9.6,-77.9 44.8,-86 111.7,-19.8 284.4,-51.4 284.4,-51.4s94.8,-163.1 154.3,-263.1C529.8,-7.8 552.6,-0.4 556.3,1c10.3,2.9 26.5,15.4 47,52.2 58.8,99.9 152.1,263.1 152.1,263.1s170.5,31.6 280.7,51.4c53.6,8.1 71.3,54.4 44.1,86z</string>
<string name="food_meterial_title">食材识别</string>
<string name="food_title">菜品识别</string>
</resources>

View File

@@ -21,6 +21,7 @@ allprojects {
repositories {
google()
jcenter()
maven { url 'https://jitpack.io' }
}
}

View File

@@ -1 +1 @@
include ':app'
include ':app', ':todaystepcounterlib'

1
todaystepcounterlib/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,34 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug{
buildConfigField "boolean", "TODAY_STEP_DEBUG", "true"
}
release {
buildConfigField "boolean", "TODAY_STEP_DEBUG", "true"
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:26.1.0'
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
testCompile 'junit:junit:4.12'
testCompile 'org.robolectric:robolectric:3.0-rc3'
testCompile 'org.mockito:mockito-core:1.+'
compile files('libs/microlog4android-1.0.0.jar')
}

Binary file not shown.

25
todaystepcounterlib/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,25 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/jiahongfei/Documents/DeveloperSoftware/adt-bundle-mac-x86_64-20140702/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,70 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.today.step.lib">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<!-- 协处理器计步权限 -->
<uses-feature
android:name="android.hardware.sensor.stepcounter"
android:required="true" />
<uses-feature
android:name="android.hardware.sensor.stepdetector"
android:required="true" />
<application>
<!--计步Service-->
<service
android:name=".TodayStepService"
android:enabled="true"
android:exported="false"
android:process=":todaystep"
android:launchMode="singleInstance"
android:priority="1000">
<intent-filter>
<!-- 系统启动完成后会调用 -->
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.DATE_CHANGED" />
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.intent.action.ACTION_TIME_TICK" />
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
</intent-filter>
</service>
<!--开机自启动-->
<receiver
android:name=".TodayStepBootCompleteReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!-- 关机广播 -->
<receiver android:name=".TodayStepShutdownReceiver" >
<intent-filter>
<!-- 关机广播 -->
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
</intent-filter>
</receiver>
<!--0点分隔alertmanager-->
<receiver
android:name=".TodayStepAlertReceive"
android:enabled="true"
android:exported="false"></receiver>
<service android:name=".JobSchedulerService"
android:permission="android.permission.BIND_JOB_SERVICE" />
</application>
</manifest>

View File

@@ -0,0 +1,35 @@
// ISportStepInterface.aidl
package com.today.step.lib;
interface ISportStepInterface {
/**
* 获取当前时间运动步数
*/
int getCurrentTimeSportStep();
/**
* 获取所有步数列表json格式如果数据过多建议在线程中获取否则会阻塞UI线程
*/
String getTodaySportStepArray();
/**
* 根据时间获取步数列表
*
* @param dateString 格式yyyy-MM-dd
* @return
*/
String getTodaySportStepArrayByDate(String date);
/**
* 根据时间和天数获取步数列表
* 例如:
* startDate = 2018-01-15
* days = 3
* 获取 2018-01-15、2018-01-16、2018-01-17三天的步数
*
* @param startDate 格式yyyy-MM-dd
* @param days
* @return
*/
String getTodaySportStepArrayByStartDateAndDays(String date, int days);
}

View File

@@ -0,0 +1,4 @@
# This is a simple Microlog configuration file
microlog.level=DEBUG
microlog.appender=LogCatAppender;FileAppender
microlog.formatter=SimpleFormatter

View File

@@ -0,0 +1,12 @@
package com.today.step.lib;
import android.content.BroadcastReceiver;
/**
* 通知栏点击通知
* Created by jiahongfei on 2017/10/19.
*/
public abstract class BaseClickBroadcast extends BroadcastReceiver {
}

View File

@@ -0,0 +1,72 @@
package com.today.step.lib;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Description: 时间工具类(时间格式转换方便类)
*/
class DateUtils {
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat();
/**
* 返回一定格式的当前时间
*
* @param pattern "yyyy-MM-dd HH:mm:ss E"
* @return
*/
public static String getCurrentDate(String pattern) {
SIMPLE_DATE_FORMAT.applyPattern(pattern);
Date date = new Date(System.currentTimeMillis());
String dateString = SIMPLE_DATE_FORMAT.format(date);
return dateString;
}
public static long getDateMillis(String dateString, String pattern) {
long millionSeconds = 0;
SIMPLE_DATE_FORMAT.applyPattern(pattern);
try {
millionSeconds = SIMPLE_DATE_FORMAT.parse(dateString).getTime();
} catch (ParseException e) {
e.printStackTrace();
}// 毫秒
return millionSeconds;
}
/**
* 格式化输入的millis
*
* @param millis
* @param pattern yyyy-MM-dd HH:mm:ss E
* @return
*/
public static String dateFormat(long millis, String pattern) {
SIMPLE_DATE_FORMAT.applyPattern(pattern);
Date date = new Date(millis);
String dateString = SIMPLE_DATE_FORMAT.format(date);
return dateString;
}
/**
* 将dateString原来old格式转换成new格式
*
* @param dateString
* @param oldPattern yyyy-MM-dd HH:mm:ss E
* @param newPattern
* @return oldPattern和dateString形式不一样直接返回dateString
*/
public static String dateFormat(String dateString, String oldPattern,
String newPattern) {
long millis = getDateMillis(dateString, oldPattern);
if (0 == millis) {
return dateString;
}
String date = dateFormat(millis, newPattern);
return date;
}
}

View File

@@ -0,0 +1,29 @@
package com.today.step.lib;
import java.util.List;
/**
* @author : jiahongfei
* @email : jiahongfeinew@163.com
* @date : 2018/1/22
* @desc :
*/
interface ITodayStepDBHelper {
void createTable();
void deleteTable();
void clearCapacity(String curDate, int limit);
boolean isExist(TodayStepData todayStepData);
void insert(TodayStepData todayStepData);
List<TodayStepData> getQueryAll();
List<TodayStepData> getStepListByDate(String dateString);
List<TodayStepData> getStepListByStartDateAndDays(String startDate, int days);
}

View File

@@ -0,0 +1,35 @@
package com.today.step.lib;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Intent;
import android.os.Build;
import android.support.annotation.RequiresApi;
/**
*
* Created by jiahongfei on 2017/10/13.
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class JobSchedulerService extends JobService {
private static final String TAG = "JobSchedulerService";
@Override
public boolean onStartJob(JobParameters params) {
Intent intent = new Intent(getApplication(), TodayStepService.class);
getApplication().startService(intent);
// Toast.makeText(getApplicationContext(), "onStartJob", Toast.LENGTH_SHORT).show();
Logger.e(TAG,"onStartJob");
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}

View File

@@ -0,0 +1,66 @@
package com.today.step.lib;
import android.text.TextUtils;
import android.util.Log;
/**
* 日志打印工具类,封装到一起,是为了调用时方便
*
* @author Administrator
*/
class Logger {
private static final String TAG = "Logger";
public static boolean sIsDebug = BuildConfig.TODAY_STEP_DEBUG;
public static void v(String message) {
if (sIsDebug)
Log.v(TAG, message);
}
public static void v(String tag, String message) {
if (sIsDebug)
Log.v(tag, message);
}
public static void d(String message) {
if (sIsDebug)
Log.d(TAG, message);
}
public static void i(String message) {
if (sIsDebug)
Log.i(TAG, message);
}
public static void i(String tag, String message) {
if (sIsDebug)
Log.i(tag, message);
}
public static void w(String message) {
if (sIsDebug)
Log.w(TAG, message);
}
public static void w(String tag, String message) {
if (sIsDebug)
Log.w(tag, message);
}
public static void e(String message) {
if (sIsDebug)
Log.e(TAG, message);
}
public static void e(String tag, String message) {
if (sIsDebug)
Log.e(tag, message);
}
public static void d(String tag, String message) {
if (!TextUtils.isEmpty(message) && sIsDebug) {
Log.d(TextUtils.isEmpty(tag) ? TAG : tag, message);
}
}
}

View File

@@ -0,0 +1,35 @@
package com.today.step.lib;
import android.content.Context;
import com.google.code.microlog4android.LoggerFactory;
import com.google.code.microlog4android.appender.FileAppender;
import com.google.code.microlog4android.config.PropertyConfigurator;
/**
* @author : jiahongfei
* @email : jiahongfeinew@163.com
* @date : 2018/2/6
* @desc :
*/
public class Microlog4Android {
private static final com.google.code.microlog4android.Logger logger = LoggerFactory.getLogger();
public void configure(Context context){
if(null != logger) {
PropertyConfigurator.getConfigurator(context).configure();
FileAppender appender = (FileAppender) logger.getAppender(1);
appender.setAppend(true);
logger.addAppender(appender);
}
}
public void error(Object message){
if(null != logger) {
logger.error(message);
}
}
}

View File

@@ -0,0 +1,20 @@
package com.today.step.lib;
/**
* Created by jiahongfei on 2017/6/30.
*/
interface OnStepCounterListener {
/**
* 用于显示步数
* @param step
*/
void onChangeStepCounter(int step);
/**
* 步数清零监听由于跨越0点需要重新计步
*/
void onStepCounterClean();
}

View File

@@ -0,0 +1,119 @@
package com.today.step.lib;
import android.content.Context;
import android.content.SharedPreferences;
/**
* @ClassName: PreferencesHelper
* @Description: (公用类用于缓存一些key——value类型的数据)
*/
class PreferencesHelper {
private static final String TAG = "PreferencesHelper";
public static final String APP_SHARD = "today_step_share_prefs";
// 上一次计步器的步数
public static final String LAST_SENSOR_TIME = "last_sensor_time";
// 步数补偿数值,每次传感器返回的步数-offset=当前步数
public static final String STEP_OFFSET = "step_offset";
// 当天,用来判断是否跨天
public static final String STEP_TODAY = "step_today";
// 清除步数
public static final String CLEAN_STEP = "clean_step";
// 当前步数
public static final String CURR_STEP = "curr_step";
//手机关机监听
public static final String SHUTDOWN = "shutdown";
//系统运行时间
public static final String ELAPSED_REALTIMEl = "elapsed_realtime";
/**
* Get SharedPreferences
*/
private static SharedPreferences getSharedPreferences(Context context) {
return context.getSharedPreferences(APP_SHARD, Context.MODE_PRIVATE);
}
public static void setLastSensorStep(Context context, float lastSensorStep){
Logger.e(TAG, "setLastSensorStep");
getSharedPreferences(context).edit().putFloat(LAST_SENSOR_TIME,lastSensorStep).commit();
}
public static float getLastSensorStep(Context context){
Logger.e(TAG, "getLastSensorStep");
return getSharedPreferences(context).getFloat(LAST_SENSOR_TIME,0.0f);
}
public static void setStepOffset(Context context, float stepOffset){
Logger.e(TAG, "setStepOffset");
getSharedPreferences(context).edit().putFloat(STEP_OFFSET,stepOffset).commit();
}
public static float getStepOffset(Context context){
Logger.e(TAG, "getStepOffset");
return getSharedPreferences(context).getFloat(STEP_OFFSET,0.0f);
}
public static void setStepToday(Context context, String stepToday){
Logger.e(TAG, "setStepToday");
getSharedPreferences(context).edit().putString(STEP_TODAY,stepToday).commit();
}
public static String getStepToday(Context context){
Logger.e(TAG, "getStepToday");
return getSharedPreferences(context).getString(STEP_TODAY,"");
}
/**
* true清除步数从0开始false否
* @param context
* @param cleanStep
*/
public static void setCleanStep(Context context, boolean cleanStep){
Logger.e(TAG, "setCleanStep");
getSharedPreferences(context).edit().putBoolean(CLEAN_STEP,cleanStep).commit();
}
/**
* true 清除步数false否
* @param context
* @return
*/
public static boolean getCleanStep(Context context){
Logger.e(TAG, "getCleanStep");
return getSharedPreferences(context).getBoolean(CLEAN_STEP,true);
}
public static void setCurrentStep(Context context, float currStep){
Logger.e(TAG, "setCurrentStep");
getSharedPreferences(context).edit().putFloat(CURR_STEP,currStep).commit();
}
public static float getCurrentStep(Context context){
Logger.e(TAG, "getCurrentStep");
return getSharedPreferences(context).getFloat(CURR_STEP,0.0f);
}
public static void setShutdown(Context context, boolean shutdown){
Logger.e(TAG, "setShutdown");
getSharedPreferences(context).edit().putBoolean(SHUTDOWN,shutdown).commit();
}
public static boolean getShutdown(Context context){
Logger.e(TAG, "getShutdown");
return getSharedPreferences(context).getBoolean(SHUTDOWN, false);
}
public static void setElapsedRealtime(Context context, long elapsedRealtime){
Logger.e(TAG, "setElapsedRealtime");
getSharedPreferences(context).edit().putLong(ELAPSED_REALTIMEl,elapsedRealtime).commit();
}
public static long getElapsedRealtime(Context context){
Logger.e(TAG, "getElapsedRealtime");
return getSharedPreferences(context).getLong(ELAPSED_REALTIMEl, 0L);
}
}

View File

@@ -0,0 +1,57 @@
package com.today.step.lib;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.List;
/**
* @author : jiahongfei
* @email : jiahongfeinew@163.com
* @date : 2018/1/31
* @desc : 用于解析和生成运动步数Json字符串
*/
public class SportStepJsonUtils {
public static final String SPORT_DATE = "sportDate";
public static final String STEP_NUM = "stepNum";
public static final String DISTANCE = "km";
public static final String CALORIE = "kaluli";
public static final String TODAY = TodayStepDBHelper.TODAY;
static JSONArray getSportStepJsonArray(List<TodayStepData> todayStepDataArrayList) {
JSONArray jsonArray = new JSONArray();
if (null == todayStepDataArrayList || 0 == todayStepDataArrayList.size()) {
return jsonArray;
}
for (int i = 0; i < todayStepDataArrayList.size(); i++) {
TodayStepData todayStepData = todayStepDataArrayList.get(i);
try {
JSONObject subObject = new JSONObject();
subObject.put(TODAY, todayStepData.getToday());
subObject.put(SPORT_DATE, todayStepData.getDate());
subObject.put(STEP_NUM, todayStepData.getStep());
subObject.put(DISTANCE, getDistanceByStep(todayStepData.getStep()));
subObject.put(CALORIE, getCalorieByStep(todayStepData.getStep()));
jsonArray.put(subObject);
} catch (JSONException e) {
e.printStackTrace();
}
}
return jsonArray;
}
// 公里计算公式
static String getDistanceByStep(long steps) {
return String.format("%.2f", steps * 0.6f / 1000);
}
// 千卡路里计算公式
static String getCalorieByStep(long steps) {
return String.format("%.1f", steps * 0.6f * 60 * 1.036f / 1000);
}
}

View File

@@ -0,0 +1,50 @@
package com.today.step.lib;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import java.util.Calendar;
import static android.content.Context.ALARM_SERVICE;
/**
* Created by jiahongfei on 2017/6/18.
*/
class StepAlertManagerUtils {
private static final String TAG = "StepAlertManagerUtils";
/**
* 设置0点分隔Alert当前天+1天的0点启动
*
* @param application
*/
public static void set0SeparateAlertManager(Context application) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.DAY_OF_YEAR,1);
String tomorrow = DateUtils.dateFormat(calendar.getTimeInMillis(),"yyyy-MM-dd");
long timeInMillis = DateUtils.getDateMillis(tomorrow+ " 00:00:00","yyyy-MM-dd HH:mm:ss");
Logger.e(TAG, DateUtils.dateFormat(timeInMillis,"yyyy-MM-dd HH:mm:ss"));
AlarmManager alarmManager = (AlarmManager) application.getSystemService(ALARM_SERVICE);
Intent i1 = new Intent(application, TodayStepAlertReceive.class);
i1.putExtra(TodayStepService.INTENT_NAME_0_SEPARATE, true);
i1.setAction(TodayStepAlertReceive.ACTION_STEP_ALERT);
PendingIntent operation = PendingIntent.getBroadcast(application, 0, i1, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeInMillis, operation);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, timeInMillis, operation);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, timeInMillis, operation);
}
}
}

View File

@@ -0,0 +1,30 @@
package com.today.step.lib;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
* 0点启动app处理步数
* Created by jiahongfei on 2017/6/18.
*/
public class TodayStepAlertReceive extends BroadcastReceiver {
public static final String ACTION_STEP_ALERT = "action_step_alert";
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_STEP_ALERT.equals(intent.getAction())) {
boolean separate = intent.getBooleanExtra(TodayStepService.INTENT_NAME_0_SEPARATE, false);
Intent stepInent = new Intent(context, TodayStepService.class);
stepInent.putExtra(TodayStepService.INTENT_NAME_0_SEPARATE, separate);
context.startService(stepInent);
StepAlertManagerUtils.set0SeparateAlertManager(context.getApplicationContext());
Logger.e("TodayStepAlertReceive","TodayStepAlertReceive");
}
}
}

View File

@@ -0,0 +1,25 @@
package com.today.step.lib;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
* 开机完成广播
*
*/
public class TodayStepBootCompleteReceiver extends BroadcastReceiver {
private static final String TAG = "TodayStepBootCompleteReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Intent todayStepIntent = new Intent(context, TodayStepService.class);
todayStepIntent.putExtra(TodayStepService.INTENT_NAME_BOOT,true);
context.startService(todayStepIntent);
Logger.e(TAG,"TodayStepBootCompleteReceiver");
}
}

View File

@@ -0,0 +1,226 @@
package com.today.step.lib;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.os.PowerManager;
import android.os.SystemClock;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* android4.4 Sensor.TYPE_STEP_COUNTER
* 计步传感器计算当天步数不需要后台Service
* Created by jiahongfei on 2017/6/30.
*/
class TodayStepCounter implements SensorEventListener {
private static final String TAG = "TodayStepCounter";
private int sOffsetStep = 0;
private int sCurrStep = 0;
private String mTodayDate;
private boolean mCleanStep = true;
private boolean mShutdown = false;
/**
* 用来标识对象第一次创建,
*/
private boolean mCounterStepReset = true;
private Context mContext;
private OnStepCounterListener mOnStepCounterListener;
private boolean mSeparate = false;
private boolean mBoot = false;
public TodayStepCounter(Context context, OnStepCounterListener onStepCounterListener, boolean separate, boolean boot) {
this.mContext = context;
this.mSeparate = separate;
this.mBoot = boot;
this.mOnStepCounterListener = onStepCounterListener;
WakeLockUtils.getLock(mContext);
sCurrStep = (int) PreferencesHelper.getCurrentStep(mContext);
mCleanStep = PreferencesHelper.getCleanStep(mContext);
mTodayDate = PreferencesHelper.getStepToday(mContext);
sOffsetStep = (int) PreferencesHelper.getStepOffset(mContext);
mShutdown = PreferencesHelper.getShutdown(mContext);
Logger.e(TAG, "mShutdown : " + mShutdown);
//开机启动监听到,一定是关机开机了
if (mBoot || shutdownBySystemRunningTime()) {
mShutdown = true;
PreferencesHelper.setShutdown(mContext, mShutdown);
Logger.e(TAG, "开机启动监听到");
}
dateChangeCleanStep();
initBroadcastReceiver();
updateStepCounter();
}
private void initBroadcastReceiver() {
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_DATE_CHANGED);
BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
if (Intent.ACTION_TIME_TICK.equals(intent.getAction())
|| Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
Logger.e(TAG, "ACTION_TIME_TICK");
//service存活做0点分隔
dateChangeCleanStep();
}
}
};
mContext.registerReceiver(mBatInfoReceiver, filter);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_STEP_COUNTER) {
int counterStep = (int) event.values[0];
if (mCleanStep) {
//TODO:只有传感器回调才会记录当前传感器步数然后对当天步数进行清零所以步数会少少的步数等于传感器启动需要的步数假如传感器需要10步进行启动那么就少10步
cleanStep(counterStep);
} else {
//处理关机启动
if (mShutdown || shutdownByCounterStep(counterStep)) {
Logger.e(TAG, "onSensorChanged shutdown");
shutdown(counterStep);
}
}
sCurrStep = counterStep - sOffsetStep;
if (sCurrStep < 0) {
//容错处理无论任何原因步数不能小于0如果小于0直接清零
Logger.e(TAG, "容错处理无论任何原因步数不能小于0如果小于0直接清零");
cleanStep(counterStep);
}
PreferencesHelper.setCurrentStep(mContext, sCurrStep);
PreferencesHelper.setElapsedRealtime(mContext, SystemClock.elapsedRealtime());
PreferencesHelper.setLastSensorStep(mContext, counterStep);
Logger.e(TAG, "counterStep : " + counterStep + " --- " + "sOffsetStep : " + sOffsetStep + " --- " + "sCurrStep : " + sCurrStep);
updateStepCounter();
}
}
private void cleanStep(int counterStep) {
//清除步数,步数归零,优先级最高
sCurrStep = 0;
sOffsetStep = counterStep;
PreferencesHelper.setStepOffset(mContext, sOffsetStep);
mCleanStep = false;
PreferencesHelper.setCleanStep(mContext, mCleanStep);
Logger.e(TAG, "mCleanStep : " + "清除步数,步数归零");
}
private void shutdown(int counterStep) {
int tmpCurrStep = (int) PreferencesHelper.getCurrentStep(mContext);
//重新设置offset
sOffsetStep = counterStep - tmpCurrStep;
PreferencesHelper.setStepOffset(mContext, sOffsetStep);
mShutdown = false;
PreferencesHelper.setShutdown(mContext, mShutdown);
}
private boolean shutdownByCounterStep(int counterStep) {
if (mCounterStepReset) {
//只判断一次
if (counterStep < PreferencesHelper.getLastSensorStep(mContext)) {
//当前传感器步数小于上次传感器步数肯定是重新启动了,只是用来增加精度不是绝对的
Logger.e(TAG, "当前传感器步数小于上次传感器步数肯定是重新启动了,只是用来增加精度不是绝对的");
return true;
}
mCounterStepReset = false;
}
return false;
}
private boolean shutdownBySystemRunningTime() {
if (PreferencesHelper.getElapsedRealtime(mContext) > SystemClock.elapsedRealtime()) {
//上次运行的时间大于当前运行时间判断为重启,只是增加精度,极端情况下连续重启,会判断不出来
Logger.e(TAG, "上次运行的时间大于当前运行时间判断为重启,只是增加精度,极端情况下连续重启,会判断不出来");
return true;
}
return false;
}
private synchronized void dateChangeCleanStep() {
//时间改变了清零或者0点分隔回调
if (!getTodayDate().equals(mTodayDate) || mSeparate) {
WakeLockUtils.getLock(mContext);
mCleanStep = true;
PreferencesHelper.setCleanStep(mContext, mCleanStep);
mTodayDate = getTodayDate();
PreferencesHelper.setStepToday(mContext, mTodayDate);
mShutdown = false;
PreferencesHelper.setShutdown(mContext, mShutdown);
mBoot = false;
mSeparate = false;
sCurrStep = 0;
PreferencesHelper.setCurrentStep(mContext, sCurrStep);
if (null != mOnStepCounterListener) {
mOnStepCounterListener.onStepCounterClean();
}
}
}
private String getTodayDate() {
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(date);
}
private void updateStepCounter() {
//每次回调都判断一下是否跨天
dateChangeCleanStep();
if (null != mOnStepCounterListener) {
mOnStepCounterListener.onChangeStepCounter(sCurrStep);
}
}
public int getCurrentStep() {
sCurrStep = (int) PreferencesHelper.getCurrentStep(mContext);
return sCurrStep;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}

View File

@@ -0,0 +1,201 @@
package com.today.step.lib;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 用来记录当天步数列表传感器回调30次记录一条数据
* Created by jiahongfei on 2017/10/9.
*/
class TodayStepDBHelper extends SQLiteOpenHelper implements ITodayStepDBHelper{
private static final String TAG = "TodayStepDBHelper";
private static final String DATE_PATTERN_YYYY_MM_DD = "yyyy-MM-dd";
private static final int VERSION = 1;
private static final String DATABASE_NAME = "TodayStepDB.db";
private static final String TABLE_NAME = "TodayStepData";
private static final String PRIMARY_KEY = "_id";
public static final String TODAY = "today";
public static final String DATE = "date";
public static final String STEP = "step";
private static final String SQL_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " ("
+ PRIMARY_KEY + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ TODAY + " TEXT, "
+ DATE + " long, "
+ STEP + " long);";
private static final String SQL_DELETE_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME;
private static final String SQL_QUERY_ALL = "SELECT * FROM " + TABLE_NAME;
private static final String SQL_QUERY_STEP = "SELECT * FROM " + TABLE_NAME + " WHERE " + TODAY + " = ? AND " + STEP + " = ?";
private static final String SQL_QUERY_STEP_BY_DATE = "SELECT * FROM " + TABLE_NAME + " WHERE " + TODAY + " = ?";
private static final String SQL_DELETE_TODAY = "DELETE FROM " + TABLE_NAME + " WHERE " + TODAY + " = ?";
//只保留mLimit天的数据
private int mLimit = -1;
public static ITodayStepDBHelper factory(Context context){
return new TodayStepDBHelper(context);
}
private TodayStepDBHelper(Context context) {
super(context, DATABASE_NAME, null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
Logger.e(TAG, SQL_CREATE_TABLE);
db.execSQL(SQL_CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
deleteTable();
onCreate(db);
}
@Override
public synchronized boolean isExist(TodayStepData todayStepData) {
Cursor cursor = getReadableDatabase().rawQuery(SQL_QUERY_STEP, new String[]{todayStepData.getToday(), todayStepData.getStep() + ""});
boolean exist = cursor.getCount() > 0 ? true : false;
cursor.close();
return exist;
}
@Override
public synchronized void createTable() {
getWritableDatabase().execSQL(SQL_CREATE_TABLE);
}
@Override
public synchronized void insert(TodayStepData todayStepData) {
ContentValues contentValues = new ContentValues();
contentValues.put(TODAY, todayStepData.getToday());
contentValues.put(DATE, todayStepData.getDate());
contentValues.put(STEP, todayStepData.getStep());
getWritableDatabase().insert(TABLE_NAME, null, contentValues);
}
@Override
public synchronized List<TodayStepData> getQueryAll() {
Cursor cursor = getReadableDatabase().rawQuery(SQL_QUERY_ALL, new String[]{});
List<TodayStepData> todayStepDatas = getTodayStepDataList(cursor);
cursor.close();
return todayStepDatas;
}
/**
* 根据时间获取步数列表
*
* @param dateString 格式yyyy-MM-dd
* @return
*/
@Override
public synchronized List<TodayStepData> getStepListByDate(String dateString) {
Cursor cursor = getReadableDatabase().rawQuery(SQL_QUERY_STEP_BY_DATE, new String[]{dateString});
List<TodayStepData> todayStepDatas = getTodayStepDataList(cursor);
cursor.close();
return todayStepDatas;
}
/**
* 根据时间和天数获取步数列表
* 例如:
* startDate = 2018-01-15
* days = 3
* 获取 2018-01-15、2018-01-16、2018-01-17三天的步数
*
* @param startDate 格式yyyy-MM-dd
* @param days
* @return
*/
@Override
public synchronized List<TodayStepData> getStepListByStartDateAndDays(String startDate, int days) {
List<TodayStepData> todayStepDatas = new ArrayList<>();
for (int i = 0; i < days; i++) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(DateUtils.getDateMillis(startDate, DATE_PATTERN_YYYY_MM_DD));
calendar.add(Calendar.DAY_OF_YEAR, i);
Cursor cursor = getReadableDatabase().rawQuery(SQL_QUERY_STEP_BY_DATE,
new String[]{DateUtils.dateFormat(calendar.getTimeInMillis(), DATE_PATTERN_YYYY_MM_DD)});
todayStepDatas.addAll(getTodayStepDataList(cursor));
cursor.close();
}
return todayStepDatas;
}
private List<TodayStepData> getTodayStepDataList(Cursor cursor) {
List<TodayStepData> todayStepDatas = new ArrayList<>();
while (cursor.moveToNext()) {
String today = cursor.getString(cursor.getColumnIndex(TODAY));
long date = cursor.getLong(cursor.getColumnIndex(DATE));
long step = cursor.getLong(cursor.getColumnIndex(STEP));
TodayStepData todayStepData = new TodayStepData();
todayStepData.setToday(today);
todayStepData.setDate(date);
todayStepData.setStep(step);
todayStepDatas.add(todayStepData);
}
return todayStepDatas;
}
/**
* 根据limit来清除数据库
* 例如:
* curDate = 2018-01-10 limit=0;表示只保留2018-01-10
* curDate = 2018-01-10 limit=1;表示保留2018-01-10、2018-01-09等
* @param curDate
* @param limit -1失效
*/
@Override
public synchronized void clearCapacity(String curDate, int limit) {
mLimit = limit;
if (mLimit <= 0) {
return;
}
try {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(DateUtils.getDateMillis(curDate, DATE_PATTERN_YYYY_MM_DD));
calendar.add(Calendar.DAY_OF_YEAR, -(mLimit));
String date = DateUtils.dateFormat(calendar.getTimeInMillis(), DATE_PATTERN_YYYY_MM_DD);
Log.e(TAG, date);
List<TodayStepData> todayStepDataList = getQueryAll();
Set<String> delDateSet = new HashSet<>();
for (TodayStepData tmpTodayStepData : todayStepDataList) {
long dbTodayDate = DateUtils.getDateMillis(tmpTodayStepData.getToday(), DATE_PATTERN_YYYY_MM_DD);
if (calendar.getTimeInMillis() >= dbTodayDate) {
delDateSet.add(tmpTodayStepData.getToday());
}
}
for (String delDate : delDateSet) {
getWritableDatabase().execSQL(SQL_DELETE_TODAY, new String[]{delDate});
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public synchronized void deleteTable() {
getWritableDatabase().execSQL(SQL_DELETE_TABLE);
}
}

View File

@@ -0,0 +1,84 @@
package com.today.step.lib;
import android.os.Parcel;
import android.os.Parcelable;
import java.io.Serializable;
public class TodayStepData implements Serializable, Parcelable {
//当天时间,只显示到天 yyyy-MM-dd
private String today;
//步数时间,显示到毫秒
private long date;
//对应date时间的步数
private long step;
public TodayStepData() {
}
protected TodayStepData(Parcel in) {
today = in.readString();
date = in.readLong();
step = in.readLong();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(today);
dest.writeLong(date);
dest.writeLong(step);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<TodayStepData> CREATOR = new Creator<TodayStepData>() {
@Override
public TodayStepData createFromParcel(Parcel in) {
return new TodayStepData(in);
}
@Override
public TodayStepData[] newArray(int size) {
return new TodayStepData[size];
}
};
public long getDate() {
return date;
}
public void setDate(long date) {
this.date = date;
}
public long getStep() {
return step;
}
public void setStep(long step) {
this.step = step;
}
public String getToday() {
return today;
}
public void setToday(String today) {
this.today = today;
}
@Override
public String toString() {
return "TodayStepData{" +
", today=" + today +
", date=" + date +
", step=" + step +
'}';
}
}

View File

@@ -0,0 +1,309 @@
package com.today.step.lib;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.os.PowerManager;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* Sensor.TYPE_ACCELEROMETER
* 加速度传感器计算当天步数需要保持后台Service
*/
class TodayStepDetector implements SensorEventListener{
private final String TAG = "TodayStepDetector";
//存放三轴数据
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 = 400;
private int count = 0;
private int mCount = 0;
private OnStepCounterListener mOnStepCounterListener;
private Context mContext;
private long timeOfLastPeak1 = 0;
private long timeOfThisPeak1 = 0;
private String mTodayDate;
public TodayStepDetector(Context context, OnStepCounterListener onStepCounterListener){
super();
mContext = context;
this.mOnStepCounterListener = onStepCounterListener;
WakeLockUtils.getLock(mContext);
mCount = (int) PreferencesHelper.getCurrentStep(mContext);
mTodayDate = PreferencesHelper.getStepToday(mContext);
dateChangeCleanStep();
initBroadcastReceiver();
updateStepCounter();
}
private void initBroadcastReceiver() {
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_DATE_CHANGED);
BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
if (Intent.ACTION_TIME_TICK.equals(intent.getAction())
|| Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
Logger.e(TAG, "ACTION_TIME_TICK");
//service存活做0点分隔
dateChangeCleanStep();
}
}
};
mContext.registerReceiver(mBatInfoReceiver, filter);
}
private synchronized void dateChangeCleanStep() {
//时间改变了清零或者0点分隔回调
if (!getTodayDate().equals(mTodayDate)) {
WakeLockUtils.getLock(mContext);
mCount = 0;
PreferencesHelper.setCurrentStep(mContext, mCount);
mTodayDate = getTodayDate();
PreferencesHelper.setStepToday(mContext, mTodayDate);
setSteps(0);
if(null != mOnStepCounterListener){
mOnStepCounterListener.onStepCounterClean();
}
}
}
private String getTodayDate() {
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(date);
}
private void updateStepCounter(){
//每次回调都判断一下是否跨天
dateChangeCleanStep();
if (null != mOnStepCounterListener) {
mOnStepCounterListener.onChangeStepCounter(mCount);
}
}
@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) {
//
}
/*
* 检测步子,并开始计步
* 1.传入sersor中的数据
* 2.如果检测到了波峰并且符合时间差以及阈值的条件则判定为1步
* 3.符合时间差条件波峰波谷差值大于initialValue则将该差值纳入阈值的计算中
* */
private 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;
/*
* 更新界面的处理,不涉及到算法
* 一般在通知更新界面之前,增加下面处理,为了处理无效运动:
* 1.连续记录10才开始计步
* 2.例如记录的9步用户停住超过3秒则前面的记录失效下次从头开始
* 3.连续记录了9步用户还在运动之前的数据才有效
* */
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.所以要记录每次的波谷值,为了和下次的波峰做对比
* */
private 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中计算阈值
* */
private 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.通过均值将阈值梯度化在一个范围里
* */
private 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.7;
}
return ave;
}
/*
* 连续走十步才会开始计步
* 连续走了9步以下,停留超过3秒,则计数清空
* */
private void countStep() {
this.timeOfLastPeak1 = this.timeOfThisPeak1;
this.timeOfThisPeak1 = System.currentTimeMillis();
if (this.timeOfThisPeak1 - this.timeOfLastPeak1 <= 3000L){
if(this.count<9){
this.count++;
}else if(this.count == 9){
this.count++;
this.mCount += this.count;
PreferencesHelper.setCurrentStep(mContext, mCount);
updateStepCounter();
}else{
this.mCount++;
PreferencesHelper.setCurrentStep(mContext, mCount);
updateStepCounter();
}
}else{//超时
this.count = 1;//为1,不是0
}
}
private void setSteps(int initValue) {
this.mCount = initValue;
this.count = 0;
timeOfLastPeak1 = 0;
timeOfThisPeak1 = 0;
}
public int getCurrentStep() {
return mCount;
}
}

View File

@@ -0,0 +1,63 @@
package com.today.step.lib;
import android.app.Application;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.support.annotation.RequiresApi;
/**
* 计步SDK初始化方法
* Created by jiahongfei on 2017/10/9.
*/
public class TodayStepManager {
private static final String TAG = "TodayStepManager";
private static final int JOB_ID = 100;
/**
* 在程序的最开始调用最好在自定义的application oncreate中调用
*
* @param application
*/
public static void init(Application application) {
StepAlertManagerUtils.set0SeparateAlertManager(application);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// initJobScheduler(application);
}
startTodayStepService(application);
}
public static void startTodayStepService(Application application) {
Intent intent = new Intent(application, TodayStepService.class);
application.startService(intent);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private static void initJobScheduler(Application application) {
Logger.e(TAG, "initJobScheduler");
JobScheduler jobScheduler = (JobScheduler)
application.getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = new JobInfo.Builder(
JOB_ID,
new ComponentName(application.getPackageName(), JobSchedulerService.class.getName()));
builder.setMinimumLatency(5000)// 设置任务运行最少延迟时间
.setOverrideDeadline(60000)// 设置deadline若到期还没有达到规定的条件则会开始执行
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)// 设置网络条件
.setRequiresCharging(true)// 设置是否充电的条件
.setRequiresDeviceIdle(false);// 设置手机是否空闲的条件
int resultCode = jobScheduler.schedule(builder.build());
if (JobScheduler.RESULT_FAILURE == resultCode) {
Logger.e(TAG, "jobScheduler 失败");
}
}
}

View File

@@ -0,0 +1,467 @@
package com.today.step.lib;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.BitmapFactory;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.support.v7.app.NotificationCompat;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONArray;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import static com.today.step.lib.SportStepJsonUtils.getCalorieByStep;
import static com.today.step.lib.SportStepJsonUtils.getDistanceByStep;
public class TodayStepService extends Service implements Handler.Callback {
private static final String TAG = "TodayStepService";
/**
* 数据库中保存多少天的运动数据
*/
private static final int DB_LIMIT = 2;
//保存数据库频率
private static final int DB_SAVE_COUNTER = 50;
//传感器的采样周期这里使用SensorManager.SENSOR_DELAY_FASTEST如果使用SENSOR_DELAY_UI会导致部分手机后台清理内存之后传感器不记步
private static final int SAMPLING_PERIOD_US = SensorManager.SENSOR_DELAY_FASTEST;
private static final int HANDLER_WHAT_SAVE_STEP = 0;
//如果走路如果停止10秒钟后保存数据库
private static final int LAST_SAVE_STEP_DURATION = 10*1000;
private static final int BROADCAST_REQUEST_CODE = 100;
public static final String INTENT_NAME_0_SEPARATE = "intent_name_0_separate";
public static final String INTENT_NAME_BOOT = "intent_name_boot";
public static final String INTENT_JOB_SCHEDULER = "intent_job_scheduler";
public static int CURRENT_SETP = 0;
private SensorManager sensorManager;
// private TodayStepDcretor stepDetector;
private TodayStepDetector mStepDetector;
private TodayStepCounter stepCounter;
private NotificationManager nm;
Notification notification;
private NotificationCompat.Builder builder;
private boolean mSeparate = false;
private boolean mBoot = false;
private int mDbSaveCount = 0;
private ITodayStepDBHelper mTodayStepDBHelper;
private final Handler sHandler = new Handler(this);
private Microlog4Android mMicrolog4Android = new Microlog4Android();
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case HANDLER_WHAT_SAVE_STEP: {
Logger.e(TAG, "HANDLER_WHAT_SAVE_STEP");
microlog4AndroidError("HANDLER_WHAT_SAVE_STEP");
mDbSaveCount = 0;
saveDb(true, CURRENT_SETP);
break;
}
default:
break;
}
return false;
}
@Override
public void onCreate() {
Logger.e(TAG, "onCreate:" + CURRENT_SETP);
super.onCreate();
mTodayStepDBHelper = TodayStepDBHelper.factory(getApplicationContext());
sensorManager = (SensorManager) this
.getSystemService(SENSOR_SERVICE);
initNotification(CURRENT_SETP);
if(null != mMicrolog4Android) {
mMicrolog4Android.configure(this);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Logger.e(TAG, "onStartCommand:" + CURRENT_SETP);
if (null != intent) {
mSeparate = intent.getBooleanExtra(INTENT_NAME_0_SEPARATE, false);
mBoot = intent.getBooleanExtra(INTENT_NAME_BOOT, false);
}
mDbSaveCount = 0;
updateNotification(CURRENT_SETP);
//注册传感器
startStepDetector();
//TODO:测试数据Start
// if(Logger.sIsDebug) {
// if (!isStepCounter()) {
// Toast.makeText(getApplicationContext(), "Lib 当前手机没有计步传感器", Toast.LENGTH_LONG).show();
// } else {
// Toast.makeText(getApplicationContext(), "Lib 当前手机使用计步传感器", Toast.LENGTH_LONG).show();
//
// }
// }
//TODO:测试数据End
microlog4AndroidError("onStartCommand");
return START_STICKY;
}
private void initNotification(int currentStep) {
builder = new NotificationCompat.Builder(this);
builder.setPriority(Notification.PRIORITY_MIN);
String receiverName = getReceiver(getApplicationContext());
PendingIntent contentIntent = PendingIntent.getBroadcast(this, BROADCAST_REQUEST_CODE, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT);
if (!TextUtils.isEmpty(receiverName)) {
try {
contentIntent = PendingIntent.getBroadcast(this, BROADCAST_REQUEST_CODE, new Intent(this, Class.forName(receiverName)), PendingIntent.FLAG_UPDATE_CURRENT);
} catch (Exception e) {
e.printStackTrace();
contentIntent = PendingIntent.getBroadcast(this, BROADCAST_REQUEST_CODE, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT);
}
}
builder.setContentIntent(contentIntent);
int smallIcon = getResources().getIdentifier("icon_step_small", "mipmap", getPackageName());
if (0 != smallIcon) {
Logger.e(TAG, "smallIcon");
builder.setSmallIcon(smallIcon);
} else {
builder.setSmallIcon(R.mipmap.ic_notification_default);// 设置通知小ICON
}
int largeIcon = getResources().getIdentifier("icon_step_large", "mipmap", getPackageName());
if (0 != largeIcon) {
Logger.e(TAG, "largeIcon");
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), largeIcon));
} else {
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_notification_default));
}
builder.setTicker(getString(R.string.app_name));
builder.setContentTitle(getString(R.string.title_notification_bar, String.valueOf(currentStep)));
String km = getDistanceByStep(currentStep);
String calorie = getCalorieByStep(currentStep);
builder.setContentText(calorie + " 千卡 " + km + " 公里");
//设置不可清除
builder.setOngoing(true);
notification = builder.build();
//将Service设置前台这里的id和notify的id一定要相同否则会出现后台清理内存Service被杀死通知还存在的bug
startForeground(R.string.app_name, notification);
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.notify(R.string.app_name, notification);
}
@Override
public IBinder onBind(Intent intent) {
Logger.e(TAG, "onBind:" + CURRENT_SETP);
return mIBinder.asBinder();
}
private void startStepDetector() {
// getLock(this);
//android4.4以后如果有stepcounter可以使用计步传感器
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && isStepCounter()) {
addStepCounterListener();
} else {
addBasePedoListener();
}
}
private void addStepCounterListener() {
Logger.e(TAG, "addStepCounterListener");
if (null != stepCounter) {
Logger.e(TAG, "已经注册TYPE_STEP_COUNTER");
WakeLockUtils.getLock(this);
CURRENT_SETP = stepCounter.getCurrentStep();
updateNotification(CURRENT_SETP);
return;
}
Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
if (null == countSensor) {
return;
}
stepCounter = new TodayStepCounter(getApplicationContext(), mOnStepCounterListener, mSeparate, mBoot);
Logger.e(TAG, "countSensor");
sensorManager.registerListener(stepCounter, countSensor, SAMPLING_PERIOD_US);
}
private void addBasePedoListener() {
Logger.e(TAG, "addBasePedoListener");
if (null != mStepDetector) {
WakeLockUtils.getLock(this);
Logger.e(TAG, "已经注册TYPE_ACCELEROMETER");
CURRENT_SETP = mStepDetector.getCurrentStep();
updateNotification(CURRENT_SETP);
return;
}
//没有计步器的时候开启定时器保存数据
Sensor sensor = sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (null == sensor) {
return;
}
mStepDetector = new TodayStepDetector(this, mOnStepCounterListener);
Log.e(TAG, "TodayStepDcretor");
// 获得传感器的类型,这里获得的类型是加速度传感器
// 此方法用来注册只有注册过才会生效参数SensorEventListener的实例Sensor的实例更新速率
sensorManager.registerListener(mStepDetector, sensor, SAMPLING_PERIOD_US);
}
@Override
public void onDestroy() {
Logger.e(TAG, "onDestroy:" + CURRENT_SETP);
Intent intent = new Intent(this, TodayStepService.class);
startService(intent);
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Logger.e(TAG, "onUnbind:" + CURRENT_SETP);
return super.onUnbind(intent);
}
/**
* 步数每次回调的方法
*
* @param currentStep
*/
private void updateTodayStep(int currentStep) {
microlog4AndroidError(" currentStep : " + currentStep);
CURRENT_SETP = currentStep;
updateNotification(CURRENT_SETP);
saveStep(currentStep);
}
private void saveStep(int currentStep) {
sHandler.removeMessages(HANDLER_WHAT_SAVE_STEP);
sHandler.sendEmptyMessageDelayed(HANDLER_WHAT_SAVE_STEP, LAST_SAVE_STEP_DURATION);
microlog4AndroidError(" mDbSaveCount : " + mDbSaveCount);
if (DB_SAVE_COUNTER > mDbSaveCount) {
mDbSaveCount++;
return;
}
mDbSaveCount = 0;
saveDb(false, currentStep);
}
/**
* @param handler true handler回调保存步数否false
* @param currentStep
*/
private void saveDb(boolean handler, int currentStep) {
TodayStepData todayStepData = new TodayStepData();
todayStepData.setToday(getTodayDate());
todayStepData.setDate(System.currentTimeMillis());
todayStepData.setStep(currentStep);
if (null != mTodayStepDBHelper) {
Logger.e(TAG, "saveDb handler : " + handler);
if (!handler || !mTodayStepDBHelper.isExist(todayStepData)) {
Logger.e(TAG, "saveDb currentStep : " + currentStep);
microlog4AndroidError("saveDb currentStep : " + currentStep);
mTodayStepDBHelper.insert(todayStepData);
}
}
}
private void cleanDb() {
Logger.e(TAG, "cleanDb");
mDbSaveCount = 0;
if (null != mTodayStepDBHelper) {
mTodayStepDBHelper.clearCapacity(DateUtils.dateFormat(System.currentTimeMillis(), "yyyy-MM-dd"), DB_LIMIT);
}
// if (null != mTodayStepDBHelper) {
//保存多天的步数
// mTodayStepDBHelper.deleteTable();
// mTodayStepDBHelper.createTable();
// }
}
private String getTodayDate() {
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(date);
}
/**
* 更新通知
*/
private void updateNotification(int stepCount) {
if (null == builder || null == nm) {
return;
}
builder.setContentTitle(getString(R.string.title_notification_bar, String.valueOf(stepCount)));
String km = getDistanceByStep(stepCount);
String calorie = getCalorieByStep(stepCount);
builder.setContentText(calorie + " 千卡 " + km + " 公里");
notification = builder.build();
nm.notify(R.string.app_name, notification);
}
private boolean isStepCounter() {
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_COUNTER);
}
private boolean isStepDetector() {
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_DETECTOR);
}
private OnStepCounterListener mOnStepCounterListener = new OnStepCounterListener() {
@Override
public void onChangeStepCounter(int step) {
updateTodayStep(step);
}
@Override
public void onStepCounterClean() {
CURRENT_SETP = 0;
updateNotification(CURRENT_SETP);
cleanDb();
}
};
private final ISportStepInterface.Stub mIBinder = new ISportStepInterface.Stub() {
@Override
public int getCurrentTimeSportStep() throws RemoteException {
return CURRENT_SETP;
}
private JSONArray getSportStepJsonArray(List<TodayStepData> todayStepDataArrayList) {
return SportStepJsonUtils.getSportStepJsonArray(todayStepDataArrayList);
}
@Override
public String getTodaySportStepArray() throws RemoteException {
if (null != mTodayStepDBHelper) {
List<TodayStepData> todayStepDataArrayList = mTodayStepDBHelper.getQueryAll();
JSONArray jsonArray = getSportStepJsonArray(todayStepDataArrayList);
Logger.e(TAG, jsonArray.toString());
return jsonArray.toString();
}
return null;
}
@Override
public String getTodaySportStepArrayByDate(String date) throws RemoteException {
if (null != mTodayStepDBHelper) {
List<TodayStepData> todayStepDataArrayList = mTodayStepDBHelper.getStepListByDate(date);
JSONArray jsonArray = getSportStepJsonArray(todayStepDataArrayList);
Logger.e(TAG, jsonArray.toString());
return jsonArray.toString();
}
return null;
}
@Override
public String getTodaySportStepArrayByStartDateAndDays(String date, int days) throws RemoteException {
if (null != mTodayStepDBHelper) {
List<TodayStepData> todayStepDataArrayList = mTodayStepDBHelper.getStepListByStartDateAndDays(date, days);
JSONArray jsonArray = getSportStepJsonArray(todayStepDataArrayList);
Logger.e(TAG, jsonArray.toString());
return jsonArray.toString();
}
return null;
}
};
public static String getReceiver(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_RECEIVERS);
ActivityInfo[] activityInfos = packageInfo.receivers;
if (null != activityInfos && activityInfos.length > 0) {
for (int i = 0; i < activityInfos.length; i++) {
String receiverName = activityInfos[i].name;
Class superClazz = Class.forName(receiverName).getSuperclass();
int count = 1;
while (null != superClazz) {
if (superClazz.getName().equals("java.lang.Object")) {
break;
}
if (superClazz.getName().equals(BaseClickBroadcast.class.getName())) {
Log.e(TAG, "receiverName : " + receiverName);
return receiverName;
}
if (count > 20) {
//用来做容错如果20个基类还不到Object直接跳出防止while死循环
break;
}
count++;
superClazz = superClazz.getSuperclass();
Log.e(TAG, "superClazz : " + superClazz);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void microlog4AndroidError(String msg){
if (null != mMicrolog4Android) {
mMicrolog4Android.error(DateUtils.getCurrentDate("yyyy-MM-dd HH:mm:ss") + " " + msg);
}
}
}

View File

@@ -0,0 +1,23 @@
package com.today.step.lib;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
* Created by jiahongfei on 2017/9/27.
*/
public class TodayStepShutdownReceiver extends BroadcastReceiver {
private static final String TAG = "TodayStepShutdownReceiver";
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SHUTDOWN)) {
Logger.e(TAG,"TodayStepShutdownReceiver");
PreferencesHelper.setShutdown(context,true);
}
}
}

View File

@@ -0,0 +1,39 @@
package com.today.step.lib;
import android.content.Context;
import android.os.PowerManager;
import java.util.Calendar;
/**
* @author : jiahongfei
* @email : jiahongfeinew@163.com
* @date : 2018/2/12
* @desc :
*/
class WakeLockUtils {
private static PowerManager.WakeLock mWakeLock;
synchronized static PowerManager.WakeLock getLock(Context context) {
if (mWakeLock != null) {
if (mWakeLock.isHeld())
mWakeLock.release();
mWakeLock = null;
}
if (mWakeLock == null) {
PowerManager mgr = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
mWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
TodayStepService.class.getName());
mWakeLock.setReferenceCounted(true);
Calendar c = Calendar.getInstance();
c.setTimeInMillis(System.currentTimeMillis());
mWakeLock.acquire();
}
return (mWakeLock);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,4 @@
<resources>
<string name="app_name">TodayStepCounterLib</string>
<string name="title_notification_bar">当前步数:%1$s</string>
</resources>

View File

@@ -0,0 +1,53 @@
package com.today.step.lib;
import org.junit.runners.model.InitializationError;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.manifest.AndroidManifest;
import org.robolectric.res.Fs;
/**
* @author : jiahongfei
* @email : jiahongfeinew@163.com
* @date : 2018/1/22
* @desc :
*/
public class MyRobolectricTestRunner extends RobolectricTestRunner {
/**
* Creates a runner to run {@code testClass}. Looks in your working directory for your AndroidManifest.xml file
* and res directory by default. Use the {@link Config} annotation to configure.
*
* @param testClass the test class to be run
* @throws InitializationError if junit says so
*/
public MyRobolectricTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
}
@Override
protected AndroidManifest getAppManifest(Config config) {
String projectName = "TodayStepCounter";
int nameLength = projectName.length();
String rootPath = System.getProperty("user.dir", "./");
int index = rootPath.indexOf(projectName);
if (index == -1) {
throw new RuntimeException("project name not found in user.dir");
}
//获取项目的根目录
rootPath = rootPath.substring(0, index + nameLength);
String manifestProperty = rootPath + "/todaystepcounterlib/src/main/AndroidManifest.xml";
String resProperty = rootPath + "/todaystepcounterlib/src/main/res";
String assetsProperty = rootPath + "/todaystepcounterlib/src/main/assets";
return new AndroidManifest(
Fs.fileFromPath(manifestProperty),
Fs.fileFromPath(resProperty),
Fs.fileFromPath(assetsProperty)) {
@Override
public int getTargetSdkVersion() {
return 21;
}
};
}
}

View File

@@ -0,0 +1,110 @@
package com.today.step.lib;
import android.app.Application;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.Calendar;
import java.util.List;
/**
* @author : jiahongfei
* @email : jiahongfeinew@163.com
* @date : 2018/1/22
* @desc :
*/
@RunWith(MyRobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class TodayStepDBHelperTest {
private static final String SPORT_DATE = "sportDate";
private static final String STEP_NUM = "stepNum";
private ITodayStepDBHelper mTodayStepDBHelper;
@Before
public void before(){
Application application = RuntimeEnvironment.application;
System.out.println(application);
mTodayStepDBHelper = TodayStepDBHelper.factory(application);
}
@Test
public void insert(){
//10天
for (int i = 0; i<10; i++){
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(DateUtils.getDateMillis("2018-01-01","yyyy-MM-dd"));
if(4 == i || 5 == i || 7 == i || 8 == i){
continue;
}
calendar.add(Calendar.DAY_OF_YEAR,i);
//每天存储5次步数
for (int j = 0; j<5; j++){
TodayStepData todayStepData = new TodayStepData();
todayStepData.setToday(DateUtils.dateFormat(calendar.getTimeInMillis(),"yyyy-MM-dd"));
todayStepData.setStep(100*j);
Calendar hourCalendar = Calendar.getInstance();
hourCalendar.setTimeInMillis(DateUtils.getDateMillis("2018-01-01 08:00","yyyy-MM-dd HH:mm"));
hourCalendar.add(Calendar.HOUR_OF_DAY,j);
todayStepData.setDate(hourCalendar.getTimeInMillis());
mTodayStepDBHelper.insert(todayStepData);
}
}
List<TodayStepData> todayStepDataList = mTodayStepDBHelper.getQueryAll();
JSONArray jsonArray = getSportStepJsonArray(todayStepDataList);
System.out.println(jsonArray.toString());
todayStepDataList = mTodayStepDBHelper.getStepListByDate("2018-01-01");
jsonArray = getSportStepJsonArray(todayStepDataList);
System.out.println(jsonArray.toString());
todayStepDataList = mTodayStepDBHelper.getStepListByStartDateAndDays("2018-01-03",3);
jsonArray = getSportStepJsonArray(todayStepDataList);
System.out.println(jsonArray.toString());
// mTodayStepDBHelper.clearCapacity("2018-01-10",7);
//
// todayStepDataList = mTodayStepDBHelper.getQueryAll();
// jsonArray = getSportStepJsonArray(todayStepDataList);
// Systemhttp://pa.mokous.com/share/renewal/esb_plus_award_notice.html.out.println(jsonArray.toString());
}
private JSONArray getSportStepJsonArray(List<TodayStepData> todayStepDataArrayList){
JSONArray jsonArray = new JSONArray();
if (null == todayStepDataArrayList || 0 == todayStepDataArrayList.size()) {
return jsonArray;
}
for (int i = 0; i < todayStepDataArrayList.size(); i++) {
TodayStepData todayStepData = todayStepDataArrayList.get(i);
try {
JSONObject subObject = new JSONObject();
subObject.put(TodayStepDBHelper.TODAY, todayStepData.getToday());
subObject.put(SPORT_DATE, DateUtils.dateFormat(todayStepData.getDate(),"yyyy-MM-dd HH:mm"));
subObject.put(STEP_NUM, todayStepData.getStep());
jsonArray.put(subObject);
} catch (JSONException e) {
e.printStackTrace();
}
}
return jsonArray;
}
}