From: kfl_614 Date: Sun, 22 Mar 2020 11:08:39 +0000 (+0800) Subject: 1.血压,天气,计步UI X-Git-Url: http://git.snicker.com.cn/Users/apple/Desktop/static/gitweb.js?a=commitdiff_plain;h=19b74fb63ed1060b01140141a8b0ea7694501428;p=ichardware.git 1.血压,天气,计步UI --- 19b74fb63ed1060b01140141a8b0ea7694501428 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..603b140 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..681f41a --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,116 @@ + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+
+
\ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..d291b3d --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..7bfef59 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..b95b0e3 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,74 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.2" + defaultConfig { + applicationId "com.ic.hardware" + minSdkVersion 19 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + //使用JDK1.8 + compileOptions { + targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_1_8 + } + + dataBinding { + enabled = true + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + sourceSets { + main { + jni.srcDirs = [] + manifest.srcFile 'src/main/AndroidManifest.xml' + java.srcDirs = ['src/main/java', 'src/main/aidl'] + resources.srcDirs = ['src/main/java', 'src/main/aidl'] + aidl.srcDirs = ['src/main/aidl'] + res.srcDirs = ['src/main/res'] + assets.srcDirs = ['src/main/assets'] + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + + // ViewModel + implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0" + // LiveData + implementation "androidx.lifecycle:lifecycle-livedata:2.2.0" + // Saved state module for ViewModel + implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0" + // alternately - if using Java8, use the following instead of lifecycle-compiler + implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0" + // optional - ReactiveStreams support for LiveData + implementation "androidx.lifecycle:lifecycle-reactivestreams:2.2.0" + + implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.19' + + //recyclerview + implementation "androidx.recyclerview:recyclerview:1.1.0" + implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0' + + implementation 'com.google.android.material:material:1.2.0-alpha05' + + implementation 'com.jakewharton.threetenabp:threetenabp:1.2.2' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# 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 diff --git a/app/src/androidTest/java/com/ic/hardware/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/ic/hardware/ExampleInstrumentedTest.java new file mode 100644 index 0000000..ce894eb --- /dev/null +++ b/app/src/androidTest/java/com/ic/hardware/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package com.ic.hardware; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.ic.hardware", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..aa92f96 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/aidl/com/ic/aidl/blood/BloodState.java b/app/src/main/aidl/com/ic/aidl/blood/BloodState.java new file mode 100644 index 0000000..82ed7f7 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/blood/BloodState.java @@ -0,0 +1,16 @@ +package com.ic.aidl.blood; + +public class BloodState { + + public static final int BLOOD_NULL_TIPS = -1; + public static final int BLOOD_NOT_DEVICE = 1001; + + public static final int BLOOD_PLEASE_QUIET = 1002; + public static final int BLOOD_START_CHECK= 1003; + + public static final int BLOOD_NOT_WEAR=1004; + public static final int BLOOD_ING_CHECK=1005; + + public static final int BLOOD_STOP_CHECK=1006; + public static final int BLOOD_NOT_DATA_CHECK=1007; +} diff --git a/app/src/main/aidl/com/ic/aidl/blood/IBloodAidlInterface.aidl b/app/src/main/aidl/com/ic/aidl/blood/IBloodAidlInterface.aidl new file mode 100644 index 0000000..092c192 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/blood/IBloodAidlInterface.aidl @@ -0,0 +1,14 @@ +// IWeatherAidlInterface.aidl +package com.ic.aidl.blood; + +// Declare any non-default types here with import statements + +interface IBloodAidlInterface { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + + void updateBloodCheckResult(int high,int low,int heart); + void updateBloodCheckTips(int top,int bottom); +} diff --git a/app/src/main/aidl/com/ic/aidl/blood/IBloodRemoteService.aidl b/app/src/main/aidl/com/ic/aidl/blood/IBloodRemoteService.aidl new file mode 100644 index 0000000..00546c2 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/blood/IBloodRemoteService.aidl @@ -0,0 +1,18 @@ +// IWeatherRemoteService.aidl +package com.ic.aidl.blood; + +// Declare any non-default types here with import statements + +import com.ic.aidl.blood.IBloodAidlInterface; + +interface IBloodRemoteService { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + void registerCallback(IBloodAidlInterface cb); + void unregisterCallback(IBloodAidlInterface cb); + + void startCheckBlood(); + void stopCheckBlood(); +} diff --git a/app/src/main/aidl/com/ic/aidl/ped/IPedAidlInterface.aidl b/app/src/main/aidl/com/ic/aidl/ped/IPedAidlInterface.aidl new file mode 100644 index 0000000..b9615f6 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/ped/IPedAidlInterface.aidl @@ -0,0 +1,15 @@ +// IWeatherAidlInterface.aidl +package com.ic.aidl.ped; + +// Declare any non-default types here with import statements +import com.ic.aidl.ped.RecordParcelable; + +interface IPedAidlInterface { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + void updatePedCount(int count); + void updatePedRecord(in List record); + +} diff --git a/app/src/main/aidl/com/ic/aidl/ped/IPedRemoteService.aidl b/app/src/main/aidl/com/ic/aidl/ped/IPedRemoteService.aidl new file mode 100644 index 0000000..60b57a3 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/ped/IPedRemoteService.aidl @@ -0,0 +1,20 @@ +// IWeatherRemoteService.aidl +package com.ic.aidl.ped; + +// Declare any non-default types here with import statements + +import com.ic.aidl.ped.IPedAidlInterface; + +interface IPedRemoteService { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + void registerCallback(IPedAidlInterface cb); + void unregisterCallback(IPedAidlInterface cb); + + void queryPedCount(); + void queryPedRecord(); + void syncPedHeightSetting(int height); + void syncPedWeightSetting(int weight); +} diff --git a/app/src/main/aidl/com/ic/aidl/ped/RecordParcelable.aidl b/app/src/main/aidl/com/ic/aidl/ped/RecordParcelable.aidl new file mode 100644 index 0000000..7f54af8 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/ped/RecordParcelable.aidl @@ -0,0 +1,3 @@ +package com.ic.aidl.ped; + +parcelable RecordParcelable; \ No newline at end of file diff --git a/app/src/main/aidl/com/ic/aidl/ped/RecordParcelable.java b/app/src/main/aidl/com/ic/aidl/ped/RecordParcelable.java new file mode 100644 index 0000000..bcdef77 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/ped/RecordParcelable.java @@ -0,0 +1,88 @@ +package com.ic.aidl.ped; + +import android.os.Parcel; +import android.os.Parcelable; + +public class RecordParcelable implements Parcelable { + private int number; + private String distance; + private String calorie; + private String date; + + public RecordParcelable() { + number = 0; + distance = null; + calorie = null; + date = ""; + } + + public RecordParcelable(int number, String distance, String calorie, String date) { + this.number = number; + this.distance = distance; + this.calorie = calorie; + this.date = date; + } + + public RecordParcelable(Parcel p) { + this.number = p.readInt(); + this.distance = p.readString(); + this.calorie = p.readString(); + this.date = p.readString(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(number); + dest.writeString(distance); + dest.writeString(calorie); + dest.writeString(date); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public RecordParcelable createFromParcel(Parcel in) { + return new RecordParcelable(in); + } + + public RecordParcelable[] newArray(int size) { + return new RecordParcelable[size]; + } + }; + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + public String getDistance() { + return distance; + } + + public void setDistance(String distance) { + this.distance = distance; + } + + public String getCalorie() { + return calorie; + } + + public void setCalorie(String calorie) { + this.calorie = calorie; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } +} diff --git a/app/src/main/aidl/com/ic/aidl/weather/IWeatherAidlInterface.aidl b/app/src/main/aidl/com/ic/aidl/weather/IWeatherAidlInterface.aidl new file mode 100644 index 0000000..219c69e --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/weather/IWeatherAidlInterface.aidl @@ -0,0 +1,14 @@ +// IWeatherAidlInterface.aidl +package com.ic.aidl.weather; + +// Declare any non-default types here with import statements +import com.ic.aidl.weather.WeatherParcelable; + +interface IWeatherAidlInterface { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + void updateCurrWeather(in WeatherParcelable weather); + +} diff --git a/app/src/main/aidl/com/ic/aidl/weather/IWeatherRemoteService.aidl b/app/src/main/aidl/com/ic/aidl/weather/IWeatherRemoteService.aidl new file mode 100644 index 0000000..2f33b2b --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/weather/IWeatherRemoteService.aidl @@ -0,0 +1,17 @@ +// IWeatherRemoteService.aidl +package com.ic.aidl.weather; + +// Declare any non-default types here with import statements + +import com.ic.aidl.weather.IWeatherAidlInterface; + +interface IWeatherRemoteService { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + void registerCallback(IWeatherAidlInterface cb); + void unregisterCallback(IWeatherAidlInterface cb); + + void queryWeatherInfo(); +} diff --git a/app/src/main/aidl/com/ic/aidl/weather/WeatherParcelable.aidl b/app/src/main/aidl/com/ic/aidl/weather/WeatherParcelable.aidl new file mode 100644 index 0000000..59b6fd3 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/weather/WeatherParcelable.aidl @@ -0,0 +1,3 @@ +package com.ic.aidl.weather; + +parcelable WeatherParcelable; \ No newline at end of file diff --git a/app/src/main/aidl/com/ic/aidl/weather/WeatherParcelable.java b/app/src/main/aidl/com/ic/aidl/weather/WeatherParcelable.java new file mode 100644 index 0000000..e7c9bbb --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/weather/WeatherParcelable.java @@ -0,0 +1,144 @@ +package com.ic.aidl.weather; + +import android.os.Parcel; +import android.os.Parcelable; + +public class WeatherParcelable implements Parcelable { + private String city; + private String statusDay; // 白天状态,如:晴 + private String statusNight; // 晚上状态 + private String figureDay; // 状态索引 + private String figureNight; + private String temperatureDay; // 白天温度 或 最低温度 + private String temperatureNight; // 晚上温度 或 最低温度 + private String updateTime; // 更新时间 + + public WeatherParcelable() { + city = ""; + statusDay = ""; + statusNight = ""; + figureDay = ""; + figureNight = ""; + temperatureDay = ""; + temperatureNight = ""; + updateTime = ""; + } + + public WeatherParcelable(String city, + String statusDay, String statusNight, + String figureDay, String figureNight, + String temperatureDay, String temperatureNight, + String updateTime) { + this.city = city; + this.statusDay = statusDay; + this.statusNight = statusNight; + this.figureDay = figureDay; + this.figureNight =figureNight; + this.temperatureDay = temperatureDay; + this.temperatureNight = temperatureNight; + this.updateTime =updateTime; + } + + public WeatherParcelable(Parcel p) { + this.city = p.readString(); + this.statusDay = p.readString(); + this.statusNight = p.readString(); + this.figureDay = p.readString(); + this.figureNight = p.readString(); + this.temperatureDay = p.readString(); + this.temperatureNight = p.readString(); + this.updateTime = p.readString(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(city); + dest.writeString(statusDay); + dest.writeString(statusNight); + dest.writeString(figureDay); + dest.writeString(figureNight); + dest.writeString(temperatureDay); + dest.writeString(temperatureNight); + dest.writeString(updateTime); + } + + public static final Creator CREATOR + = new Creator() { + public WeatherParcelable createFromParcel(Parcel in) { + return new WeatherParcelable(in); + } + + public WeatherParcelable[] newArray(int size) { + return new WeatherParcelable[size]; + } + }; + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getStatusDay() { + return statusDay; + } + + public void setStatusDay(String statusDay) { + this.statusDay = statusDay; + } + + public String getStatusNight() { + return statusNight; + } + + public void setStatusNight(String statusNight) { + this.statusNight = statusNight; + } + + public String getFigureDay() { + return figureDay; + } + + public void setFigureDay(String figureDay) { + this.figureDay = figureDay; + } + + public String getFigureNight() { + return figureNight; + } + + public void setFigureNight(String figureNight) { + this.figureNight = figureNight; + } + + public String getTemperatureDay() { + return temperatureDay; + } + + public void setTemperatureDay(String temperatureDay) { + this.temperatureDay = temperatureDay; + } + + public String getTemperatureNight() { + return temperatureNight; + } + + public void setTemperatureNight(String temperatureNight) { + this.temperatureNight = temperatureNight; + } + + public String getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(String updateTime) { + this.updateTime = updateTime; + } +} diff --git a/app/src/main/assets/fonts/Baloo2-SemiBold.ttf b/app/src/main/assets/fonts/Baloo2-SemiBold.ttf new file mode 100644 index 0000000..fe3453d Binary files /dev/null and b/app/src/main/assets/fonts/Baloo2-SemiBold.ttf differ diff --git a/app/src/main/assets/only_hr_check.gif b/app/src/main/assets/only_hr_check.gif new file mode 100644 index 0000000..67011c6 Binary files /dev/null and b/app/src/main/assets/only_hr_check.gif differ diff --git a/app/src/main/java/com/ic/hardware/BloodActivity.java b/app/src/main/java/com/ic/hardware/BloodActivity.java new file mode 100644 index 0000000..dd89530 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/BloodActivity.java @@ -0,0 +1,31 @@ +package com.ic.hardware; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + +import android.os.Bundle; + +import com.ic.hardware.fragment.BloodFragment; + +public class BloodActivity extends AppCompatActivity { + + private FragmentManager fragmentManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_blood); + fragmentManager = getSupportFragmentManager(); + commitFragment(BloodFragment.newInstance()); + } + + private void commitFragment(Fragment fragment) { + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.replace(R.id.main_content_fl, fragment); + fragmentTransaction.commit(); + } + + +} diff --git a/app/src/main/java/com/ic/hardware/HardwareApp.java b/app/src/main/java/com/ic/hardware/HardwareApp.java new file mode 100644 index 0000000..e6e1e68 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/HardwareApp.java @@ -0,0 +1,17 @@ +package com.ic.hardware; + +import android.app.Application; + +import com.ic.hardware.util.IcLog; +import com.jakewharton.threetenabp.AndroidThreeTen; + +public class HardwareApp extends Application { + + @Override + public void onCreate() { + super.onCreate(); + IcLog.setLogHead("IcHardware"); + + AndroidThreeTen.init(this); + } +} diff --git a/app/src/main/java/com/ic/hardware/MainClockGestureDetectorImpl.java b/app/src/main/java/com/ic/hardware/MainClockGestureDetectorImpl.java new file mode 100644 index 0000000..8ffa181 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/MainClockGestureDetectorImpl.java @@ -0,0 +1,44 @@ +package com.ic.hardware; + +import android.view.GestureDetector; +import android.view.MotionEvent; + +import com.ic.hardware.util.IcLog; + + +public class MainClockGestureDetectorImpl extends GestureDetector.SimpleOnGestureListener { + private static final String TAG = "MainClockGesture"; + + public interface OnClockGestureFlingListener{ + void onDirection(int flag); + } + + private OnClockGestureFlingListener mListener; + + public MainClockGestureDetectorImpl(OnClockGestureFlingListener flingListener ){ + this.mListener = flingListener; + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + IcLog.i(TAG, "onFling x1:" + e1.getX()+ "x2:" + e2.getX()); + + if(e1.getX() - e2.getX() > 30){ + onCallBackListener(1); + return true; + } + + if(e2.getX() - e1.getX() > 30){ + onCallBackListener(2); + return true; + } + + return super.onFling(e1, e2, velocityX, velocityY); + } + + private void onCallBackListener(int flag){ + if(mListener != null){ + mListener.onDirection(flag); + } + } +} diff --git a/app/src/main/java/com/ic/hardware/PedometerActivity.java b/app/src/main/java/com/ic/hardware/PedometerActivity.java new file mode 100644 index 0000000..7e98bfb --- /dev/null +++ b/app/src/main/java/com/ic/hardware/PedometerActivity.java @@ -0,0 +1,180 @@ +package com.ic.hardware; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.view.GestureDetectorCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.os.Bundle; +import android.view.MotionEvent; + +import com.ic.hardware.adapter.IndicatorAdapter; +import com.ic.hardware.fragment.pedometer.PedMainFragment; +import com.ic.hardware.fragment.pedometer.PedRecordFragment; +import com.ic.hardware.fragment.pedometer.PedSetupDialogFragment; +import com.ic.hardware.fragment.pedometer.PedSetupFragment; +import com.ic.hardware.model.PedometerModel; +import com.ic.hardware.util.IcLog; +import com.ic.hardware.util.SPUtils; + +public class PedometerActivity extends AppCompatActivity + implements PedSetupDialogFragment.NoticeDialogListener, + PedMainFragment.QueryPedometerCountListener, + PedRecordFragment.QueryPedometerRecordListener, + MainClockGestureDetectorImpl.OnClockGestureFlingListener { + + private static final String TAG = "PedometerActivity"; + + private FragmentManager fragmentManager; + + private PedometerModel pedometerModel; + private IndicatorAdapter indicatorAdapter; + private int currIndex; + private Fragment[] mFtList; + + private GestureDetectorCompat gesture; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_pedometer); + initFt(); + initIndicator(); + initPedometerModel(); + initOnTouchListener(); + } + + private void initPedometerModel() { + PedometerModel.Factory factory = new PedometerModel.Factory(getApplication()); + pedometerModel = new ViewModelProvider(this, factory).get(PedometerModel.class); + + pedometerModel.getObsPedCount().observe(this, integer -> { + ((PedMainFragment) mFtList[1]).updatePedNumber(integer); + }); + + pedometerModel.getObsPedRecord().observe(this, record -> { + ((PedRecordFragment) mFtList[2]).updatePedRecord(record); + }); + + pedometerModel.onBindService(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (pedometerModel != null) { + pedometerModel.onUnBindService(); + pedometerModel = null; + } + } + + @Override + public void onQueryCount() { + pedometerModel.queryPedCount(); + } + + @Override + public void onQueryRecord() { + pedometerModel.queryPedRecord(); + } + + @Override + public void onDialogUpdate(int type, int value) { + ((PedSetupFragment) mFtList[0]).updateSetuUpValue(type, value); + switch (type) { + case 0: + pedometerModel.syncPedHeightSetting(value); + SPUtils.setPedHeightSP(getApplicationContext(), value); + case 1: + pedometerModel.syncPedWeightSetting(value); + SPUtils.setPedWighttSP(getApplicationContext(), value); + break; + } + } + + @Override + public void onDirection(int flag) { + switch (flag) { + case 1: + //左滑 + if (currIndex == mFtList.length - 1) { + return; + } else { + currIndex++; + commitFragment(mFtList[currIndex]); + indicatorAdapter.updateIndicatorState(currIndex); + } + break; + case 2: + //右滑 + IcLog.i(TAG,"Right >>>>>>>>>>>>>>>"); + if (currIndex == 0) { + return; + } else { + currIndex--; + commitFragment(mFtList[currIndex]); + indicatorAdapter.updateIndicatorState(currIndex); + } + break; + } + } + + + private void initFt() { + fragmentManager = getSupportFragmentManager(); + mFtList = new Fragment[3]; + mFtList[0] = PedSetupFragment.newInstance(); + mFtList[1] = PedMainFragment.newInstance(); + mFtList[2] = PedRecordFragment.newInstance(); + currIndex = 1; + commitFragment(mFtList[1]); + } + + private void initIndicator() { + RecyclerView indicatorRv = findViewById(R.id.ped_indicator_rv); + indicatorAdapter = new IndicatorAdapter(); + LinearLayoutManager mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); + indicatorRv.setLayoutManager(mLayoutManager); + indicatorRv.setAdapter(indicatorAdapter); + } + + private void commitFragment(Fragment fragment) { + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + + for (int i = 0; i < mFtList.length; i++) { + if(mFtList[i].isAdded()){ + fragmentTransaction.hide(mFtList[i]); + } + } + + if (fragment.isAdded()) { + fragmentTransaction.show(fragment); + } else { + fragmentTransaction.add(R.id.ped_content_fl, fragment); + } + + + fragmentTransaction.commit(); + } + + + private void initOnTouchListener() { + gesture = new GestureDetectorCompat(this ,new MainClockGestureDetectorImpl(this)); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + gesture.onTouchEvent(ev); + super.dispatchTouchEvent(ev); + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return gesture.onTouchEvent(event); + } +} diff --git a/app/src/main/java/com/ic/hardware/WeatherActivity.java b/app/src/main/java/com/ic/hardware/WeatherActivity.java new file mode 100644 index 0000000..d786e16 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/WeatherActivity.java @@ -0,0 +1,30 @@ +package com.ic.hardware; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + +import android.os.Bundle; + +import com.ic.hardware.fragment.WeatherFragment; + +public class WeatherActivity extends AppCompatActivity { + + private FragmentManager fragmentManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_weather); + fragmentManager = getSupportFragmentManager(); + commitFragment(WeatherFragment.newInstance()); + } + + private void commitFragment(Fragment fragment) { + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.replace(R.id.weather_content_fl, fragment); + fragmentTransaction.commit(); + } + +} diff --git a/app/src/main/java/com/ic/hardware/adapter/IndicatorAdapter.java b/app/src/main/java/com/ic/hardware/adapter/IndicatorAdapter.java new file mode 100644 index 0000000..fcddf59 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/adapter/IndicatorAdapter.java @@ -0,0 +1,58 @@ +package com.ic.hardware.adapter; + +import android.view.LayoutInflater; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.ic.hardware.databinding.ItemIndicatorLayoutBinding; + +public class IndicatorAdapter extends RecyclerView.Adapter { + + private boolean[] stateList = new boolean[]{false, true, false}; + + private int oldCheckIndex=1; + + public void updateIndicatorState(int index){ + if(oldCheckIndex != index){ + stateList[index] = true; + stateList[oldCheckIndex] =false; + oldCheckIndex = index; + + notifyDataSetChanged(); + } + } + + @NonNull + @Override + public IndicatorHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new IndicatorHolder(ItemIndicatorLayoutBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull IndicatorHolder holder, int position) { + holder.bindItem(stateList[position]); + } + + @Override + public int getItemCount() { + return stateList.length; + } + + static class IndicatorHolder extends RecyclerView.ViewHolder { + private ItemIndicatorLayoutBinding binding = null; + + public IndicatorHolder(@NonNull ItemIndicatorLayoutBinding itemView) { + super(itemView.getRoot()); + binding = itemView; + } + + public void bindItem(boolean state) { + if (binding != null) { + binding.setIsCheckItem(state); + binding.executePendingBindings(); + } + } + } +} diff --git a/app/src/main/java/com/ic/hardware/adapter/PedRecordAdapter.java b/app/src/main/java/com/ic/hardware/adapter/PedRecordAdapter.java new file mode 100644 index 0000000..42f40a9 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/adapter/PedRecordAdapter.java @@ -0,0 +1,83 @@ +package com.ic.hardware.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.view.LayoutInflater; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.ic.aidl.ped.RecordParcelable; +import com.ic.hardware.R; +import com.ic.hardware.databinding.ItemPedRecordBinding; + +import java.util.ArrayList; +import java.util.List; + +public class PedRecordAdapter extends RecyclerView.Adapter { + + private Context mContext; + private List mPedRecord; + + public PedRecordAdapter(Context context){ + this.mContext = context; + this.mPedRecord = new ArrayList<>(); + } + + public void updatePedRecordList(List records){ + mPedRecord.clear(); + mPedRecord.addAll(records); + notifyDataSetChanged(); + } + + @NonNull + @Override + public RecordHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new RecordHolder(ItemPedRecordBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull RecordHolder holder, int position) { + holder.bindPedRecord(mContext,mPedRecord.get(position)); + } + + @Override + public int getItemCount() { + return mPedRecord.size(); + } + + static class RecordHolder extends RecyclerView.ViewHolder { + private ItemPedRecordBinding binding = null; + + public RecordHolder(@NonNull ItemPedRecordBinding itemView) { + super(itemView.getRoot()); + binding = itemView; + } + + public void bindPedRecord(Context context,RecordParcelable entity) { + if (binding == null || entity == null) { + return; + } + + binding.setTakingIcon(R.drawable.ic_ped_taking); + binding.setTakingColor(Color.parseColor("#FFA500")); + binding.setTakingUnit(context.getString(R.string.tips_target_unit)); + + binding.setCaloriesIcon(R.drawable.ic_ped_calories); + binding.setCaloriesColor(Color.WHITE); + binding.setCaloriesUnit(context.getString(R.string.tips_calories_unit)); + + binding.setDistanceIcon(R.drawable.ic_ped_distance); + binding.setDistanceColor(Color.WHITE); + binding.setDistanceUnit(context.getString(R.string.tips_distance_unit)); + + binding.setRecordCalories(entity.getCalorie()); + binding.setRecordDate(entity.getDate()); + binding.setRecordDistance(entity.getDistance()); + binding.setRecordTaking(String.valueOf(entity.getNumber())); + + binding.executePendingBindings(); + } + } +} diff --git a/app/src/main/java/com/ic/hardware/adapter/PedSetupAdapter.java b/app/src/main/java/com/ic/hardware/adapter/PedSetupAdapter.java new file mode 100644 index 0000000..6aae4b1 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/adapter/PedSetupAdapter.java @@ -0,0 +1,104 @@ +package com.ic.hardware.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.RecyclerView; + +import com.ic.hardware.R; +import com.ic.hardware.databinding.ItemPedSetupBinding; +import com.ic.hardware.entitys.PedSetupEntity; +import com.ic.hardware.fragment.pedometer.PedSetupFragment; +import com.ic.hardware.util.SPUtils; + + +public class PedSetupAdapter extends RecyclerView.Adapter { + + private final PedSetupEntity[] setupArray; + + private static final int[] TITLE_RES = new int[]{ + R.string.ped_height_name, + R.string.tips_weight_name, + R.string.tips_target_name, + }; + + private static final int[] UNIT_RES = new int[]{ + R.string.tips_height_unit, + R.string.tips_weight_unit, + R.string.tips_target_unit, + }; + + private static final int[] ICON_RES = new int[]{ + R.drawable.ic_ped_height, + R.drawable.ic_ped_weight, + R.drawable.ic_ped_task, + }; + + private PedSetupFragment.OnPedSetupItemClickListener mListener; + + public PedSetupAdapter(Context context, PedSetupFragment.OnPedSetupItemClickListener listener){ + setupArray = new PedSetupEntity[3]; + int[] valueArray = new int[]{ + SPUtils.getPedHeightSP(context), + SPUtils.getPedWighttSP(context), + SPUtils.getPedTargetSP(context) + }; + + for (int i=0; i { + bloodBinding.setIsShowTips(false); + bloodBinding.setHighValue(value[0]); + bloodBinding.setLowValue(value[1]); + bloodBinding.setHeartValue(value[2]); + }); + + bloodModel.getObsTipsInfo().observe(getViewLifecycleOwner(),tips ->{ + bloodBinding.setIsShowTips(true); + bloodBinding.setTopTips(tips[0]); + bloodBinding.setBottomTips(tips[1]); + }); + + bloodModel.getObsCheckEnd().observe(getViewLifecycleOwner(),end ->{ + switch (end){ + case 1: + IcLog.i(TAG,"Release WakeLock"); + releaseWakeLock(); + break; + case 2: + ((BloodActivity)mContext).finish(); + break; + } + }); + } + + @SuppressLint("InvalidWakeLockTag") + private void initWakeLock(Context context) { + PowerManager powerManager = (PowerManager) context.getSystemService(POWER_SERVICE); + if (powerManager != null) { + mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "BloodWakeLock"); + } + } + + private void releaseWakeLock() { + if (mWakeLock != null) { + mWakeLock.release(); + } + mWakeLock = null; + } + + private void setGifDrawable() { + GifImageView gifImageView = bloodBinding.icHeartGif; + gifImageView.setScaleType(ImageView.ScaleType.CENTER); + try { + gifFromAssets = new GifDrawable(mContext.getAssets(), "only_hr_check.gif"); + gifImageView.setImageDrawable(gifFromAssets); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + IcLog.i(TAG,"onDestroy"); + + bloodModel.unregisterScreenReceiver(); + bloodModel = null; + + if (gifFromAssets != null) { + gifFromAssets.recycle(); + } + } +} diff --git a/app/src/main/java/com/ic/hardware/fragment/WeatherFragment.java b/app/src/main/java/com/ic/hardware/fragment/WeatherFragment.java new file mode 100644 index 0000000..ee38dd3 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/fragment/WeatherFragment.java @@ -0,0 +1,159 @@ +package com.ic.hardware.fragment; + + +import android.content.Context; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; + +import android.util.SparseArray; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.ic.hardware.HardwareApp; +import com.ic.hardware.R; +import com.ic.hardware.databinding.FragmentWeatherBinding; +import com.ic.hardware.model.WeatherModel; + +import org.threeten.bp.OffsetDateTime; + +/** + * A simple {@link Fragment} subclass. + */ +public class WeatherFragment extends Fragment { + + private Context mContext; + private HardwareApp mApp; + + private FragmentWeatherBinding weatherBinding; + private WeatherModel weatherModel; + + public static WeatherFragment newInstance() { + return new WeatherFragment(); + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + this.mContext = context; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mApp = (HardwareApp) mContext.getApplicationContext(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + weatherBinding = FragmentWeatherBinding.inflate(inflater, container, false); + initWeatherModel(); + return weatherBinding.getRoot(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + weatherModel.onUnBindService(); + } + + private void initWeatherModel() { + WeatherModel.Factory factory = new WeatherModel.Factory(mApp); + weatherModel = new ViewModelProvider(this, factory).get(WeatherModel.class); + + + weatherModel.getObsWeatherParcelable().observe(getViewLifecycleOwner(), parcelable -> { + + if (parcelable == null) { + weatherBinding.setIsShowTips(true); + weatherBinding.setIsErrorTips(getString(R.string.tips_error_weather_no_data)); + return; + } + + OffsetDateTime time = OffsetDateTime.now(); + + boolean inNight = time.getHour() > 18; + weatherBinding.setWeatherCity(parcelable.getCity()); + weatherBinding.setWeatherSection( + String.format(getString(R.string.weather_temp_space_degree), + parcelable.getTemperatureDay(), + parcelable.getTemperatureNight())); + + String degree = getString(R.string.weather_temp_degree); + + if (inNight) { + weatherBinding.setWeatherState(parcelable.getStatusNight()); + weatherBinding.setWeatherTemp(String.format(degree, parcelable.getTemperatureNight())); + weatherBinding.setWeatherIcon(ContextCompat.getDrawable(mContext, getStatusImage(parcelable.getStatusNight()))); + } else { + weatherBinding.setWeatherState(parcelable.getStatusDay()); + weatherBinding.setWeatherTemp(String.format(degree, parcelable.getTemperatureDay())); + weatherBinding.setWeatherIcon(ContextCompat.getDrawable(mContext, getStatusImage(parcelable.getStatusDay()))); + } + }); + + weatherModel.onBindService(); + } + + public static int getStatusImage(String stuats) { + int imageId = R.mipmap.weather_status_none; + if (stuats != null) { + if (stuats.contains("多云") || stuats.contains("晴")) { + imageId = R.mipmap.weather_status_qingyun; + } else if (stuats.contains("多云") && stuats.contains("阴")) { + imageId = R.mipmap.weather_status_yinduoyun; + } else if (stuats.contains("阴") && stuats.contains("雨")) { + imageId = R.mipmap.weather_status_yinyu; + } else if (stuats.contains("晴") && stuats.contains("雨")) { + imageId = R.mipmap.weather_status_qingyu; + } else if (stuats.contains("晴") && stuats.contains("雾")) { + imageId = R.mipmap.weather_status_qingwu; + } else if (stuats.contains("晴")) { + imageId = R.mipmap.weather_status_qing; + } else if (stuats.contains("多云")) { + imageId = R.mipmap.weather_status_duoyun; + } else if (stuats.contains("雷阵雨")) { + imageId = R.mipmap.weather_status_leizhenyu; + } else if (stuats.contains("阵雨")) { + imageId = R.mipmap.weather_status_zhenyu; + } else if (stuats.contains("小雨")) { + imageId = R.mipmap.weather_status_xiaoyu; + } else if (stuats.contains("中雨")) { + imageId = R.mipmap.weather_status_zhongyu; + } else if (stuats.contains("大雨")) { + imageId = R.mipmap.weather_status_dayu; + } else if (stuats.contains("暴雨")) { + imageId = R.mipmap.weather_status_baoyu; + } else if (stuats.contains("冰雹")) { + imageId = R.mipmap.weather_status_bingbao; + } else if (stuats.contains("小雪")) { + imageId = R.mipmap.weather_status_xiaoxue; + } else if (stuats.contains("中雪")) { + imageId = R.mipmap.weather_status_zhongxue; + } else if (stuats.contains("大雪")) { + imageId = R.mipmap.weather_status_daxue; + } else if (stuats.contains("暴雪")) { + imageId = R.mipmap.weather_status_baoxue; + } else if (stuats.contains("扬沙")) { + imageId = R.mipmap.weather_status_yangsha; + } else if (stuats.contains("沙尘")) { + imageId = R.mipmap.weather_status_shachenbao; + } else if (stuats.contains("雾")) { + imageId = R.mipmap.weather_status_wu; + + // PARRY 2017.04.27 + } else if (stuats.contains("阴")) { + imageId = R.mipmap.weather_status_yin; + } + } + + return imageId; + } +} diff --git a/app/src/main/java/com/ic/hardware/fragment/pedometer/PedMainFragment.java b/app/src/main/java/com/ic/hardware/fragment/pedometer/PedMainFragment.java new file mode 100644 index 0000000..d396c28 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/fragment/pedometer/PedMainFragment.java @@ -0,0 +1,115 @@ +package com.ic.hardware.fragment.pedometer; + + +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.core.view.GestureDetectorCompat; +import androidx.fragment.app.Fragment; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.ic.hardware.HardwareApp; +import com.ic.hardware.MainClockGestureDetectorImpl; +import com.ic.hardware.databinding.FragmentPedMainBinding; +import com.ic.hardware.util.SPUtils; +import com.ic.hardware.widget.ring.Ring; +import com.ic.hardware.widget.ring.RingProgress; + +import java.util.ArrayList; +import java.util.List; + +/** + * A simple {@link Fragment} subclass. + */ +public class PedMainFragment extends Fragment { + + public interface QueryPedometerCountListener { + void onQueryCount(); + } + + private Context mContext; + private HardwareApp mApp; + + private FragmentPedMainBinding pedMainBinding; + + private QueryPedometerCountListener queryListner; + + public static PedMainFragment newInstance() { + return new PedMainFragment(); + } + + private int targetValue; + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + this.mContext = context; + + try { + queryListner = (QueryPedometerCountListener) context; + } catch (ClassCastException e) { + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mApp = (HardwareApp) mContext.getApplicationContext(); + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + pedMainBinding = FragmentPedMainBinding.inflate(inflater, container, false); + updatePedNumber(0); + targetValue = SPUtils.getPedTargetSP(mApp.getApplicationContext()); + pedMainBinding.setPedTarget(String.valueOf(targetValue)); + return pedMainBinding.getRoot(); + } + + @Override + public void onResume() { + super.onResume(); + queryListner.onQueryCount(); + } + + public void updatePedNumber(int number) { + int value = (int) (number * 0.01); + if (value < 1) { + value = 1; + } + setupRingProgress(value); + setupRingProgressNumberTv(number); + } + + private void setupRingProgress(int number) { + RingProgress mRingProgress = pedMainBinding.ringProgress; + + Ring r = new Ring(number, "", "", Color.GREEN, Color.YELLOW); + List mlistRing = new ArrayList<>(); + mlistRing.add(r); + mRingProgress.setData(mlistRing, 5000); + } + + private void setupRingProgressNumberTv(int number) { + TextView pedNumber = pedMainBinding.pedNumberTv; + Typeface typeFace = Typeface.createFromAsset(mContext.getAssets(), "fonts/Baloo2-SemiBold.ttf"); + pedNumber.setTypeface(typeFace); + + ValueAnimator animator = ValueAnimator.ofInt(0, number); + animator.setDuration(5000); + animator.addUpdateListener(animation -> pedMainBinding.setPedNumber(animation.getAnimatedValue().toString())); + animator.start(); + } +} diff --git a/app/src/main/java/com/ic/hardware/fragment/pedometer/PedRecordFragment.java b/app/src/main/java/com/ic/hardware/fragment/pedometer/PedRecordFragment.java new file mode 100644 index 0000000..70d0b98 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/fragment/pedometer/PedRecordFragment.java @@ -0,0 +1,78 @@ +package com.ic.hardware.fragment.pedometer; + +import android.content.Context; +import android.os.Bundle; + +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.ic.aidl.ped.RecordParcelable; +import com.ic.hardware.R; +import com.ic.hardware.adapter.PedRecordAdapter; + +import java.util.List; + +public class PedRecordFragment extends Fragment { + + public interface QueryPedometerRecordListener{ + void onQueryRecord(); + } + + public static PedRecordFragment newInstance() { + return new PedRecordFragment(); + } + + private Context mContext; + private RecyclerView mSetupRv; + private PedRecordAdapter setupAdapte; + private QueryPedometerRecordListener queryListner; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + this.mContext=context; + + try { + queryListner = (QueryPedometerRecordListener) context; + } catch (ClassCastException e) { + } + } + + @Override + public void onDetach() { + super.onDetach(); + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_ped_record, container, false); + mSetupRv = view.findViewById(R.id.ped_record_rv); + initRecyclerView(); + queryListner.onQueryRecord(); + return view; + } + + public void updatePedRecord(List records){ + setupAdapte.updatePedRecordList(records); + } + + private void initRecyclerView() { + setupAdapte = new PedRecordAdapter(mContext); + LinearLayoutManager mLayoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false); + mSetupRv.setLayoutManager(mLayoutManager); + mSetupRv.setAdapter(setupAdapte); + } + +} diff --git a/app/src/main/java/com/ic/hardware/fragment/pedometer/PedSetupDialogFragment.java b/app/src/main/java/com/ic/hardware/fragment/pedometer/PedSetupDialogFragment.java new file mode 100644 index 0000000..1d81205 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/fragment/pedometer/PedSetupDialogFragment.java @@ -0,0 +1,118 @@ +package com.ic.hardware.fragment.pedometer; + +import android.annotation.SuppressLint; +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.icu.text.DisplayContext; +import android.os.Bundle; +import android.util.SparseArray; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.ImageButton; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.collection.ArrayMap; +import androidx.fragment.app.DialogFragment; + +import com.ic.hardware.R; +import com.ic.hardware.util.SPUtils; +import com.ic.hardware.widget.picker.NumericWheelAdapter; +import com.ic.hardware.widget.picker.WheelView; + +public class PedSetupDialogFragment extends DialogFragment { + + public interface NoticeDialogListener { + void onDialogUpdate(int type, int value); + } + + public static PedSetupDialogFragment newInstance(int type) { + PedSetupDialogFragment frag = new PedSetupDialogFragment(); + Bundle args = new Bundle(); + args.putInt("type", type); + frag.setArguments(args); + return frag; + } + + private Context mContext; + private int mCurrType; + + private WheelView numberPicker; + + private final ArrayMap limil = new ArrayMap<>(); + + private final String[] UNIT_RES = new String[2]; + private final int[] VALUE_CURR = new int[2]; + + private NoticeDialogListener mListener; + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + this.mContext = context; + try { + mListener = (NoticeDialogListener) context; + } catch (ClassCastException e) { + } + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Bundle bundle = getArguments(); + if (bundle != null) { + mCurrType = bundle.getInt("type"); + } + + VALUE_CURR[0] = SPUtils.getPedHeightSP(mContext); + VALUE_CURR[1] = SPUtils.getPedWighttSP(mContext); + + UNIT_RES[0] = getString(R.string.tips_height_unit); + UNIT_RES[1] = getString(R.string.tips_weight_unit); + + limil.put(0, new int[]{30, 250}); + limil.put(1, new int[]{15, 150}); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + Dialog mDialog = getDialog(); + if (mDialog != null) { + getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE); + } + + View popView = inflater.inflate(R.layout.dialog_ped_setup_layout, container); + numberPicker = (WheelView) popView.findViewById(R.id.dialog_value_picker); + setNumberPicker(limil.get(mCurrType)[0], limil.get(mCurrType)[1], UNIT_RES[mCurrType], VALUE_CURR[mCurrType]); + + ImageButton bt = (ImageButton) popView.findViewById(R.id.dialog_picker_ok); + bt.setOnClickListener(v -> { + mListener.onDialogUpdate(mCurrType,limil.get(mCurrType)[0]+numberPicker.getCurrentItem()); + dismiss(); + }); + ImageButton cancel = (ImageButton) popView.findViewById(R.id.dialog_picker_cancel); + cancel.setOnClickListener(v -> dismiss()); + + return popView; + } + + private void setNumberPicker(final int numberMin, int numberMax, String label, int numberDefault) { + numberPicker.setAdapter(new NumericWheelAdapter(numberMin, numberMax)); + numberPicker.setLabel(label); + numberPicker.setCyclic(true); + numberPicker.TEXT_SIZE = (int) spToPx(65); + numberPicker.ITEM_TEXT_SIZE = (int) spToPx(42); + + numberPicker.setCurrentItem(numberDefault - numberMin); + } + + private float spToPx(float sp) { + return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics()); + } +} diff --git a/app/src/main/java/com/ic/hardware/fragment/pedometer/PedSetupFragment.java b/app/src/main/java/com/ic/hardware/fragment/pedometer/PedSetupFragment.java new file mode 100644 index 0000000..7504e6f --- /dev/null +++ b/app/src/main/java/com/ic/hardware/fragment/pedometer/PedSetupFragment.java @@ -0,0 +1,83 @@ +package com.ic.hardware.fragment.pedometer; + +import android.content.Context; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.ic.hardware.R; +import com.ic.hardware.adapter.PedSetupAdapter; + + +public class PedSetupFragment extends Fragment{ + + private static final String TAG = "PedSetupFragment"; + + public interface OnPedSetupItemClickListener{ + void onPedSetupItem(int pos); + } + + private Context mContext; + private RecyclerView mSetupRv; + private PedSetupAdapter setupAdapte; + + public static PedSetupFragment newInstance() { + return new PedSetupFragment(); + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + this.mContext = context; + } + + @Override + public void onDetach() { + super.onDetach(); + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_ped_setup, container, false); + mSetupRv = view.findViewById(R.id.ped_setup_rv); + initRecyclerView(); + return view; + } + + private void initRecyclerView() { + setupAdapte = new PedSetupAdapter(mContext,listener); + LinearLayoutManager mLayoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false); + mSetupRv.setLayoutManager(mLayoutManager); + mSetupRv.setAdapter(setupAdapte); + } + + private OnPedSetupItemClickListener listener = pos -> { + if(pos == 2){ + return; + } + FragmentManager fm = getChildFragmentManager(); + PedSetupDialogFragment alertDialog = PedSetupDialogFragment.newInstance(pos); + alertDialog.show(fm, "PedSetupDialog"); + }; + + public void updateSetuUpValue(int type,int value){ + setupAdapte.notifyUpdateValue(type,value); + } + +} + diff --git a/app/src/main/java/com/ic/hardware/model/BloodCheckModel.java b/app/src/main/java/com/ic/hardware/model/BloodCheckModel.java new file mode 100644 index 0000000..d4284d8 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/model/BloodCheckModel.java @@ -0,0 +1,74 @@ +package com.ic.hardware.model; + +import android.app.Application; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; + +import com.ic.hardware.presenter.BloodPresenter; + + +public class BloodCheckModel extends AndroidViewModel { + + private final BloodPresenter bloodPresenter; + + private LiveData mObsBloodValue; + private LiveData mObsTipsInfo; + private LiveData mObsCheckEnd; + + private BloodCheckModel(@NonNull Application application) { + super(application); + this.bloodPresenter = new BloodPresenter(application.getApplicationContext()); + mObsBloodValue = bloodPresenter.getObsBloodValue(); + mObsTipsInfo = bloodPresenter.getObsTipsInfo(); + mObsCheckEnd = bloodPresenter.getObsCheckEnd(); + } + + public LiveData getObsBloodValue() { + return mObsBloodValue; + } + + public LiveData getObsTipsInfo() { + return mObsTipsInfo; + } + + public LiveData getObsCheckEnd() { + return mObsCheckEnd; + } + + public void startCheckBlood(){ + bloodPresenter.startCheckBlood(); + } + + public void stopCheckBlood(){ + bloodPresenter.stopCheckBlood(); + } + + public void registerScreenReceiver(){ + bloodPresenter.registerScreenReceiver(); + } + + public void unregisterScreenReceiver(){ + bloodPresenter.unregisterScreenReceiver(); + } + + public static class Factory extends ViewModelProvider.NewInstanceFactory { + + @NonNull + private final Application mApplication; + + public Factory(@NonNull Application application) { + mApplication = application; + } + + @SuppressWarnings("unchecked") + @Override + @NonNull + public T create(@NonNull Class modelClass) { + return (T) new BloodCheckModel(mApplication); + } + } +} diff --git a/app/src/main/java/com/ic/hardware/model/PedometerModel.java b/app/src/main/java/com/ic/hardware/model/PedometerModel.java new file mode 100644 index 0000000..3f9dcc1 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/model/PedometerModel.java @@ -0,0 +1,78 @@ +package com.ic.hardware.model; + +import android.app.Application; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; + +import com.ic.aidl.ped.RecordParcelable; +import com.ic.hardware.presenter.PedometerPresenter; + +import java.util.List; + +public class PedometerModel extends AndroidViewModel { + + private final PedometerPresenter pedometerPresenter; + + private LiveData mObsPedCount; + private LiveData> mObsPedRecord; + + private PedometerModel(@NonNull Application application) { + super(application); + pedometerPresenter = new PedometerPresenter(application.getApplicationContext()); + mObsPedCount = pedometerPresenter.getObsPedCount(); + mObsPedRecord = pedometerPresenter.getObsPedRecord(); + } + + public LiveData getObsPedCount() { + return mObsPedCount; + } + + public LiveData> getObsPedRecord() { + return mObsPedRecord; + } + + public void onBindService(){ + pedometerPresenter.bindService(); + } + + public void onUnBindService(){ + pedometerPresenter.unbindService(); + } + + public void queryPedCount(){ + pedometerPresenter.queryPedCount(); + } + + public void queryPedRecord(){ + pedometerPresenter.queryPedRecord(); + } + + public void syncPedHeightSetting(int height){ + pedometerPresenter.syncPedHeightSetting(height); + } + + public void syncPedWeightSetting(int weight){ + pedometerPresenter.syncPedWeightSetting(weight); + } + + public static class Factory extends ViewModelProvider.NewInstanceFactory { + + @NonNull + private final Application mApplication; + + public Factory(@NonNull Application application) { + mApplication = application; + } + + @SuppressWarnings("unchecked") + @Override + @NonNull + public T create(@NonNull Class modelClass) { + return (T) new PedometerModel(mApplication); + } + } +} diff --git a/app/src/main/java/com/ic/hardware/model/WeatherModel.java b/app/src/main/java/com/ic/hardware/model/WeatherModel.java new file mode 100644 index 0000000..0761933 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/model/WeatherModel.java @@ -0,0 +1,53 @@ +package com.ic.hardware.model; + +import android.app.Application; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; + +import com.ic.aidl.weather.WeatherParcelable; +import com.ic.hardware.presenter.WeatherPresenter; + +public class WeatherModel extends AndroidViewModel { + + private final LiveData weatherParcelable; + private final WeatherPresenter weatherPresenter; + + private WeatherModel(@NonNull Application application) { + super(application); + weatherPresenter = new WeatherPresenter(application.getApplicationContext()); + weatherParcelable = weatherPresenter.getObsWeatherInfo(); + } + + public LiveData getObsWeatherParcelable() { + return weatherParcelable; + } + + public void onBindService(){ + weatherPresenter.bindService(); + } + + public void onUnBindService(){ + weatherPresenter.unbindService(); + } + + public static class Factory extends ViewModelProvider.NewInstanceFactory { + + @NonNull + private final Application mApplication; + + public Factory(@NonNull Application application) { + mApplication = application; + } + + @SuppressWarnings("unchecked") + @Override + @NonNull + public T create(@NonNull Class modelClass) { + return (T) new WeatherModel(mApplication); + } + } +} diff --git a/app/src/main/java/com/ic/hardware/presenter/BloodPresenter.java b/app/src/main/java/com/ic/hardware/presenter/BloodPresenter.java new file mode 100644 index 0000000..9b280eb --- /dev/null +++ b/app/src/main/java/com/ic/hardware/presenter/BloodPresenter.java @@ -0,0 +1,175 @@ +package com.ic.hardware.presenter; + + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.SparseArray; + +import androidx.lifecycle.MutableLiveData; + +import com.ic.aidl.blood.BloodState; +import com.ic.aidl.blood.IBloodAidlInterface; +import com.ic.aidl.blood.IBloodRemoteService; +import com.ic.hardware.R; +import com.ic.hardware.util.IcLog; +import com.ic.hardware.util.ServiceUtil; + +public class BloodPresenter { + + private static final String TAG = "BloodPresenter"; + + private Context mContext; + + private MutableLiveData mObsBloodValue; + private MutableLiveData mObsTipsInfo; + private MutableLiveData mObsCheckEnd; + + private IBloodRemoteService mService; + + private SparseArray mTipsSpares; + + private Handler mHandler; + + public BloodPresenter(Context context) { + this.mContext = context; + mTipsSpares = new SparseArray(); + mTipsSpares.put(BloodState.BLOOD_NULL_TIPS, ""); + mTipsSpares.put(BloodState.BLOOD_NOT_DEVICE, context.getString(R.string.tips_not_device)); + mTipsSpares.put(BloodState.BLOOD_PLEASE_QUIET, context.getString(R.string.tips_quiet_please)); + mTipsSpares.put(BloodState.BLOOD_START_CHECK, context.getString(R.string.tips_start_check)); + mTipsSpares.put(BloodState.BLOOD_NOT_WEAR, context.getString(R.string.tips_not_wear)); + mTipsSpares.put(BloodState.BLOOD_ING_CHECK, context.getString(R.string.tips_ing_check)); + mTipsSpares.put(BloodState.BLOOD_STOP_CHECK, context.getString(R.string.tips_stop_check)); + mTipsSpares.put(BloodState.BLOOD_NOT_DATA_CHECK, context.getString(R.string.tips_not_data_check)); + + mObsBloodValue = new MutableLiveData<>(); + mObsTipsInfo = new MutableLiveData<>(); + mObsCheckEnd = new MutableLiveData<>(); + + mHandler = new Handler(); + } + + public MutableLiveData getObsBloodValue() { + return mObsBloodValue; + } + + public MutableLiveData getObsTipsInfo() { + return mObsTipsInfo; + } + + public MutableLiveData getObsCheckEnd() { + return mObsCheckEnd; + } + + public void registerScreenReceiver() { + + ServiceUtil.bindServiceUtil(mContext, "com.ic.action.WORK_SERVICE", connection, 102); + + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(Intent.ACTION_SCREEN_OFF); + mContext.registerReceiver(screenOnOffReceiver, intentFilter); + } + + public void unregisterScreenReceiver() { + + mContext.unregisterReceiver(screenOnOffReceiver); + + try { + mService.unregisterCallback(bloodInterface); + ServiceUtil.unBindServiceUtil(mContext, connection); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + }finally { + mService=null; + bloodInterface=null; + } + + connection = null; + mHandler = null; + } + + public void startCheckBlood() { + if (mService != null) { + try { + mService.startCheckBlood(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + } + } + } + + public void stopCheckBlood() { + if (mService != null) { + try { + mService.stopCheckBlood(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + } + } + } + + + private void updateTipsInfo(String t, String b) { + if (mObsTipsInfo != null) { + mObsTipsInfo.postValue(new String[]{t, b}); + } + } + + private void updateBoolValue(int lv, int hv, int hh) { + if (mObsBloodValue != null) { + mObsBloodValue.postValue(new String[]{ + String.valueOf(hv), + String.valueOf(lv), + String.valueOf(hh)}); + } + } + + private BroadcastReceiver screenOnOffReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { + IcLog.i(TAG, "灭屏了"); + mObsCheckEnd.setValue(2); + } + } + }; + + + private ServiceConnection connection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + try { + mService = IBloodRemoteService.Stub.asInterface(service); + mService.registerCallback(bloodInterface); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + } + }; + + private IBloodAidlInterface.Stub bloodInterface = new IBloodAidlInterface.Stub() { + @Override + public void updateBloodCheckResult(int high, int low, int heart) throws RemoteException { + updateBoolValue(high, low, heart); + mHandler.postDelayed(() -> mObsCheckEnd.postValue(1), 10 * 1000); + } + + @Override + public void updateBloodCheckTips(int top, int bottom) throws RemoteException { + updateTipsInfo(mTipsSpares.get(top), mTipsSpares.get(bottom)); + } + }; + + +} diff --git a/app/src/main/java/com/ic/hardware/presenter/PedometerPresenter.java b/app/src/main/java/com/ic/hardware/presenter/PedometerPresenter.java new file mode 100644 index 0000000..f71180b --- /dev/null +++ b/app/src/main/java/com/ic/hardware/presenter/PedometerPresenter.java @@ -0,0 +1,127 @@ +package com.ic.hardware.presenter; + +import android.content.ComponentName; +import android.content.Context; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; + +import androidx.lifecycle.MutableLiveData; + +import com.ic.aidl.ped.IPedAidlInterface; +import com.ic.aidl.ped.IPedRemoteService; +import com.ic.aidl.ped.RecordParcelable; +import com.ic.hardware.util.IcLog; +import com.ic.hardware.util.ServiceUtil; + +import java.util.List; + +public class PedometerPresenter { + private static final String TAG = "PedometerPresenter"; + + private Context mContext; + + private IPedRemoteService mService; + private MutableLiveData mObsPedCount; + private MutableLiveData> mObsPedRecord; + + public PedometerPresenter(Context context){ + mContext=context; + mObsPedCount = new MutableLiveData<>(); + mObsPedRecord = new MutableLiveData<>(); + } + + public MutableLiveData getObsPedCount() { + return mObsPedCount; + } + + public MutableLiveData> getObsPedRecord() { + return mObsPedRecord; + } + + public void bindService(){ + ServiceUtil.bindServiceUtil(mContext, "com.ic.action.WORK_SERVICE", connection, 103); + } + + public void unbindService(){ + try { + mService.unregisterCallback(pedInterface); + ServiceUtil.unBindServiceUtil(mContext,connection); + } catch (Exception e) { + IcLog.e(TAG,"unbindService"); + }finally { + mService=null; + pedInterface=null; + } + } + + public void queryPedCount() { + if (mService != null) { + try { + mService.queryPedCount(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + } + } + } + + public void queryPedRecord() { + if (mService != null) { + try { + mService.queryPedRecord(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + } + } + } + + public void syncPedHeightSetting(int height){ + if (mService != null) { + try { + mService.syncPedHeightSetting(height); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + } + } + } + + public void syncPedWeightSetting(int weight){ + if (mService != null) { + try { + mService.syncPedWeightSetting(weight); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + } + } + } + + + private ServiceConnection connection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + try { + mService = IPedRemoteService.Stub.asInterface(service); + mService.registerCallback(pedInterface); + queryPedCount(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + } + }; + + private IPedAidlInterface.Stub pedInterface = new IPedAidlInterface.Stub() { + @Override + public void updatePedCount(int count) throws RemoteException { + mObsPedCount.postValue(count); + } + + @Override + public void updatePedRecord(List record) throws RemoteException { + mObsPedRecord.postValue(record); + } + }; +} diff --git a/app/src/main/java/com/ic/hardware/presenter/WeatherPresenter.java b/app/src/main/java/com/ic/hardware/presenter/WeatherPresenter.java new file mode 100644 index 0000000..a99a265 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/presenter/WeatherPresenter.java @@ -0,0 +1,84 @@ +package com.ic.hardware.presenter; + +import android.content.ComponentName; +import android.content.Context; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; + +import androidx.lifecycle.MutableLiveData; + +import com.ic.aidl.weather.IWeatherAidlInterface; +import com.ic.aidl.weather.IWeatherRemoteService; +import com.ic.aidl.weather.WeatherParcelable; +import com.ic.hardware.util.IcLog; +import com.ic.hardware.util.ServiceUtil; + +public class WeatherPresenter { + private static final String TAG = "WeatherPresenter"; + + private Context mContext; + + private MutableLiveData mObsWeatherInfo; + private IWeatherRemoteService mService; + + public WeatherPresenter(Context context) { + this.mContext =context; + + mObsWeatherInfo = new MutableLiveData<>(); + } + + public MutableLiveData getObsWeatherInfo() { + return mObsWeatherInfo; + } + + public void bindService(){ + ServiceUtil.bindServiceUtil(mContext, "com.ic.action.WORK_SERVICE", connection, 101); + } + + public void unbindService(){ + try { + mService.unregisterCallback(weatherInterface); + ServiceUtil.unBindServiceUtil(mContext,connection); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + }finally { + mService=null; + weatherInterface=null; + } + } + + private void queryWeatherInfo() { + if (mService != null) { + try { + mService.queryWeatherInfo(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + } + } + } + + private ServiceConnection connection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + try { + mService = IWeatherRemoteService.Stub.asInterface(service); + mService.registerCallback(weatherInterface); + queryWeatherInfo(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + } + }; + + private IWeatherAidlInterface.Stub weatherInterface = new IWeatherAidlInterface.Stub() { + @Override + public void updateCurrWeather(WeatherParcelable weather) throws RemoteException { + mObsWeatherInfo.postValue(weather); + } + }; +} diff --git a/app/src/main/java/com/ic/hardware/util/IcLog.java b/app/src/main/java/com/ic/hardware/util/IcLog.java new file mode 100644 index 0000000..5992f07 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/util/IcLog.java @@ -0,0 +1,59 @@ +package com.ic.hardware.util; + +import android.util.Log; + +import com.ic.hardware.BuildConfig; + +/** + * @author RyanLee + * @date 2018/2/2 + */ + +public class IcLog { + + private static final String DOT = "."; + private static boolean isDebug = BuildConfig.DEBUG; + private static String tagHead = ""; + + public static void v(String tag, String msg) { + if (isDebug) { + Log.v(mergeHeadTag(tag), msg); + } + } + + public static void d(String tag, String msg) { + if (isDebug) { + Log.d(mergeHeadTag(tag), msg); + } + } + + public static void i(String tag, String msg) { + if (isDebug) { + Log.i(mergeHeadTag(tag), msg); + } + } + + public static void w(String tag, String msg) { + if (isDebug) { + Log.w(mergeHeadTag(tag), msg); + } + } + + public static void e(String tag, String msg) { + if (isDebug) { + Log.e(mergeHeadTag(tag), msg); + } + } + + public static void setDebug(boolean debug) { + isDebug = debug; + } + + public static void setLogHead(String head) { + tagHead = head + DOT; + } + + private static String mergeHeadTag(final String tag) { + return tagHead + tag; + } +} diff --git a/app/src/main/java/com/ic/hardware/util/SPUtils.java b/app/src/main/java/com/ic/hardware/util/SPUtils.java new file mode 100644 index 0000000..6d5a7bc --- /dev/null +++ b/app/src/main/java/com/ic/hardware/util/SPUtils.java @@ -0,0 +1,52 @@ +package com.ic.hardware.util; + +import android.content.Context; +import android.content.SharedPreferences; + +public class SPUtils { + + private static final String Ped_Height = "Ped_Height"; + private static final String Ped_Weight = "Ped_Weight"; + private static final String Ped_Target = "Ped_Target"; + + + private static SharedPreferences getSp(Context context) { + return context.getSharedPreferences("IcHardwarePed", Context.MODE_PRIVATE); + } + + public static int getPedHeightSP(Context context) { + return getSp(context).getInt(Ped_Height, 170); + } + + public static int getPedWighttSP(Context context) { + return getSp(context).getInt(Ped_Weight, 75); + } + + public static int getPedTargetSP(Context context) { + return getSp(context).getInt(Ped_Target, 10000); + } + + public static void setPedHeightSP(Context context,int height) { + SharedPreferences.Editor editor = getSp(context).edit(); + if (editor != null) { + editor.putInt(Ped_Weight, height); + editor.apply(); + } + } + + public static void setPedWighttSP(Context context,int weight) { + SharedPreferences.Editor editor = getSp(context).edit(); + if (editor != null) { + editor.putInt(Ped_Weight, weight); + editor.apply(); + } + } + + public static void setPedTargetSP(Context context,int target) { + SharedPreferences.Editor editor = getSp(context).edit(); + if (editor != null) { + editor.putInt(Ped_Target, target); + editor.apply(); + } + } +} diff --git a/app/src/main/java/com/ic/hardware/util/ServiceUtil.java b/app/src/main/java/com/ic/hardware/util/ServiceUtil.java new file mode 100644 index 0000000..28bc27d --- /dev/null +++ b/app/src/main/java/com/ic/hardware/util/ServiceUtil.java @@ -0,0 +1,46 @@ +package com.ic.hardware.util; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; + +import java.util.List; + +public class ServiceUtil { + + public static void startServiceUtil(Context context , String serviceAction, String packageName) { + Intent intent = getExplicitIntent(context, new Intent(serviceAction)); + if(intent != null){ + intent.setPackage(packageName); + context.startService(intent); + } + } + + public static void bindServiceUtil(Context context , String action, ServiceConnection connection,int type) { + Intent in = getExplicitIntent(context, new Intent(action)); + if(in != null){ + in.putExtra("REQ_TYPE",type); + context.bindService(in, connection, 0); + } + } + + public static void unBindServiceUtil(Context context ,ServiceConnection connection) { + context.unbindService(connection); + } + + private static Intent getExplicitIntent(Context context, Intent impl) { + List resolveInfo = context.getPackageManager().queryIntentServices(impl, 0); + + if (resolveInfo.size() != 1) return null; + + Intent intent = new Intent(impl); + ServiceInfo info = resolveInfo.get(0).serviceInfo; + if (info == null) return null; + intent.setComponent(new ComponentName(info.packageName, info.name)); + + return intent; + } +} diff --git a/app/src/main/java/com/ic/hardware/widget/WidgetImageTextLayout.java b/app/src/main/java/com/ic/hardware/widget/WidgetImageTextLayout.java new file mode 100644 index 0000000..4a9ef4f --- /dev/null +++ b/app/src/main/java/com/ic/hardware/widget/WidgetImageTextLayout.java @@ -0,0 +1,53 @@ +package com.ic.hardware.widget; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.databinding.BindingAdapter; + +import com.ic.hardware.R; + +public class WidgetImageTextLayout extends LinearLayout { + + private TextView mValueTv; + private TextView mUnitTv; + private ImageView mIconIv; + + public WidgetImageTextLayout(Context context) { + this(context, null); + } + + public WidgetImageTextLayout(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public WidgetImageTextLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + View view = View.inflate(context, R.layout.widget_image_text_layout, this); + + mValueTv = (TextView) view.findViewById(R.id.widget_image_value); + mUnitTv = (TextView) view.findViewById(R.id.widget_image_unit); + mIconIv = (ImageView) view.findViewById(R.id.widget_image_icon); + } + + private void updateWidgetImageText(String value, String unit, int iconResId,int color) { + mValueTv.setText(value); + mUnitTv.setText(unit); + mIconIv.setImageResource(iconResId); + mValueTv.setTextColor(color); + } + + @BindingAdapter(value = {"icApp:widgetImageValue", "icApp:widgetImageUnit", "icApp:widgetImageIcon","icApp:widgetImageColor"}, requireAll = false) + public static void updateTimeText(WidgetImageTextLayout view, String value, String unit, int iconResId,int color) { + if (view != null) { + view.updateWidgetImageText(value, unit, iconResId,color); + } + } +} diff --git a/app/src/main/java/com/ic/hardware/widget/picker/NumericWheelAdapter.java b/app/src/main/java/com/ic/hardware/widget/picker/NumericWheelAdapter.java new file mode 100644 index 0000000..3bee5c5 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/widget/picker/NumericWheelAdapter.java @@ -0,0 +1,96 @@ +/* + * Copyright 2010 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ic.hardware.widget.picker; + +/** + * Numeric Wheel adapter. + */ +public class NumericWheelAdapter implements WheelAdapter { + + /** The default min value */ + public static final int DEFAULT_MAX_VALUE = 9; + + /** The default max value */ + private static final int DEFAULT_MIN_VALUE = 0; + + // Values + private int minValue; + private int maxValue; + + // format + private String format; + + /** + * Default constructor + */ + public NumericWheelAdapter() { + this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE); + } + + /** + * Constructor + * + * @param minValue + * the wheel min value + * @param maxValue + * the wheel max value + */ + public NumericWheelAdapter(int minValue, int maxValue) { + this(minValue, maxValue, null); + } + + /** + * Constructor + * + * @param minValue + * the wheel min value + * @param maxValue + * the wheel max value + * @param format + * the format string + */ + public NumericWheelAdapter(int minValue, int maxValue, String format) { + this.minValue = minValue; + this.maxValue = maxValue; + this.format = format; + } + + @Override + public String getItem(int index) { + if (index >= 0 && index < getItemsCount()) { + int value = minValue + index; + return format != null ? String.format(format, value) : Integer + .toString(value); + } + return null; + } + + @Override + public int getItemsCount() { + return maxValue - minValue + 1; + } + + @Override + public int getMaximumLength() { + int max = Math.max(Math.abs(maxValue), Math.abs(minValue)); + int maxLen = Integer.toString(max).length(); + if (minValue < 0) { + maxLen++; + } + return maxLen; + } +} diff --git a/app/src/main/java/com/ic/hardware/widget/picker/OnWheelChangedListener.java b/app/src/main/java/com/ic/hardware/widget/picker/OnWheelChangedListener.java new file mode 100644 index 0000000..54aaa58 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/widget/picker/OnWheelChangedListener.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ic.hardware.widget.picker; + +/** + * Wheel changed listener interface. + *

+ * The currentItemChanged() method is called whenever current wheel positions is + * changed: + *

  • New Wheel position is set + *
  • Wheel view is scrolled + */ +public interface OnWheelChangedListener { + /** + * Callback method to be invoked when current item changed + * + * @param wheel + * the wheel view whose state has changed + * @param oldValue + * the old value of current item + * @param newValue + * the new value of current item + */ + void onChanged(WheelView wheel, int oldValue, int newValue); +} diff --git a/app/src/main/java/com/ic/hardware/widget/picker/OnWheelScrollListener.java b/app/src/main/java/com/ic/hardware/widget/picker/OnWheelScrollListener.java new file mode 100644 index 0000000..56b5299 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/widget/picker/OnWheelScrollListener.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ic.hardware.widget.picker; + +/** + * Wheel scrolled listener interface. + */ +public interface OnWheelScrollListener { + /** + * Callback method to be invoked when scrolling started. + * + * @param wheel + * the wheel view whose state has changed. + */ + void onScrollingStarted(WheelView wheel); + + /** + * Callback method to be invoked when scrolling ended. + * + * @param wheel + * the wheel view whose state has changed. + */ + void onScrollingFinished(WheelView wheel); +} diff --git a/app/src/main/java/com/ic/hardware/widget/picker/WheelAdapter.java b/app/src/main/java/com/ic/hardware/widget/picker/WheelAdapter.java new file mode 100644 index 0000000..d1e5b7d --- /dev/null +++ b/app/src/main/java/com/ic/hardware/widget/picker/WheelAdapter.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ic.hardware.widget.picker; + +public interface WheelAdapter { + /** + * Gets items count + * + * @return the count of wheel items + */ + int getItemsCount(); + + /** + * Gets a wheel item by index. + * + * @param index + * the item index + * @return the wheel item text or null + */ + String getItem(int index); + + /** + * Gets maximum item length. It is used to determine the wheel width. If -1 + * is returned there will be used the default wheel width. + * + * @return the maximum item length or -1 + */ + int getMaximumLength(); +} diff --git a/app/src/main/java/com/ic/hardware/widget/picker/WheelView.java b/app/src/main/java/com/ic/hardware/widget/picker/WheelView.java new file mode 100644 index 0000000..dcd488f --- /dev/null +++ b/app/src/main/java/com/ic/hardware/widget/picker/WheelView.java @@ -0,0 +1,1041 @@ +/* + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2010 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ic.hardware.widget.picker; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.GradientDrawable.Orientation; +import android.os.Handler; +import android.os.Message; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.GestureDetector.SimpleOnGestureListener; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +import com.ic.hardware.R; + +import java.util.LinkedList; +import java.util.List; + + +/** + * Numeric wheel view. + * + * @author Yuri Kanivets + */ +public class WheelView extends View { + /** + * Scrolling duration + */ + private static final int SCROLLING_DURATION = 400; + + /** + * Minimum delta for scrolling + */ + private static final int MIN_DELTA_FOR_SCROLLING = 1; + + /** + * Current value & label text color + */ +// private static final int VALUE_TEXT_COLOR = 0xF0000000; + private static final int VALUE_TEXT_COLOR = 0xFFFFA70D; + + /** + * Items text color + */ +// private static final int ITEMS_TEXT_COLOR = 0xFF000000; + private static final int ITEMS_TEXT_COLOR = 0xFFA9A9A9; + + /** + * Top and bottom shadows colors + */ + private static final int[] SHADOWS_COLORS = new int[]{0xFF111111, + 0x00AAAAAA, 0x00AAAAAA}; + + /** + * Additional items height (is added to standard text item height) + */ + private static final int ADDITIONAL_ITEM_HEIGHT = 5; + + /** + * Text size + */ + public int TEXT_SIZE; + public int ITEM_TEXT_SIZE; + + /** + * Top and bottom items offset (to hide that) + */ + private final int ITEM_OFFSET = TEXT_SIZE / DEF_VISIBLE_ITEMS; + + /** + * Additional width for items layout + */ + private static final int ADDITIONAL_ITEMS_SPACE = 10; + + /** + * Label offset + */ + private static final int LABEL_OFFSET = 5; + + /** + * Left and right padding value + */ + private static final int PADDING = 10; + + /** + * Default count of visible items + */ + private static final int DEF_VISIBLE_ITEMS = 3; + + // Wheel Values + private WheelAdapter adapter = null; + private int currentItem = 0; + + // Widths + private int itemsWidth = 0; + private int labelWidth = 0; + + // Count of visible items + private int visibleItems = DEF_VISIBLE_ITEMS; + + // Item height + private int itemHeight = 0; + + // Text paints + private TextPaint itemsPaint; + private TextPaint valuePaint; + private TextPaint labelPaint; + + // Layouts + private StaticLayout itemsLayout; + private StaticLayout labelLayout; + private StaticLayout valueLayout; + + // Label & background + private String label; + private Drawable centerDrawable; + + // Shadows drawables + private GradientDrawable topShadow; + private GradientDrawable bottomShadow; + + // Scrolling + private boolean isScrollingPerformed; + private int scrollingOffset; + + // Scrolling animation + private GestureDetector gestureDetector; + private Scroller scroller; + private int lastScrollY; + + // Cyclic + boolean isCyclic = false; + + // Listeners + private List changingListeners = new LinkedList(); + private List scrollingListeners = new LinkedList(); + + /** + * Constructor + */ + public WheelView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initData(context); + } + + /** + * Constructor + */ + public WheelView(Context context, AttributeSet attrs) { + super(context, attrs); + initData(context); + } + + /** + * Constructor + */ + public WheelView(Context context) { + super(context); + initData(context); + } + + /** + * Initializes class data + * + * @param context the context + */ + private void initData(Context context) { + gestureDetector = new GestureDetector(context, gestureListener); + gestureDetector.setIsLongpressEnabled(false); + + scroller = new Scroller(context); + } + + /** + * Gets wheel adapter + * + * @return the adapter + */ + public WheelAdapter getAdapter() { + return adapter; + } + + /** + * Sets wheel adapter + * + * @param adapter the new wheel adapter + */ + public void setAdapter(WheelAdapter adapter) { + this.adapter = adapter; + invalidateLayouts(); + invalidate(); + } + + /** + * Set the the specified scrolling interpolator + * + * @param interpolator the interpolator + */ + public void setInterpolator(Interpolator interpolator) { + scroller.forceFinished(true); + scroller = new Scroller(getContext(), interpolator); + } + + /** + * Gets count of visible items + * + * @return the count of visible items + */ + public int getVisibleItems() { + return visibleItems; + } + + /** + * Sets count of visible items + * + * @param count the new count + */ + public void setVisibleItems(int count) { + visibleItems = count; + invalidate(); + } + + /** + * Gets label + * + * @return the label + */ + public String getLabel() { + return label; + } + + /** + * Sets label + * + * @param newLabel the label to set + */ + public void setLabel(String newLabel) { + if (label == null || !label.equals(newLabel)) { + label = newLabel; + labelLayout = null; + invalidate(); + } + } + + /** + * Adds wheel changing listener + * + * @param listener the listener + */ + public void addChangingListener(OnWheelChangedListener listener) { + changingListeners.add(listener); + } + + /** + * Removes wheel changing listener + * + * @param listener the listener + */ + public void removeChangingListener(OnWheelChangedListener listener) { + changingListeners.remove(listener); + } + + /** + * Notifies changing listeners + * + * @param oldValue the old wheel value + * @param newValue the new wheel value + */ + protected void notifyChangingListeners(int oldValue, int newValue) { + for (OnWheelChangedListener listener : changingListeners) { + listener.onChanged(this, oldValue, newValue); + } + } + + /** + * Adds wheel scrolling listener + * + * @param listener the listener + */ + public void addScrollingListener(OnWheelScrollListener listener) { + scrollingListeners.add(listener); + } + + /** + * Removes wheel scrolling listener + * + * @param listener the listener + */ + public void removeScrollingListener(OnWheelScrollListener listener) { + scrollingListeners.remove(listener); + } + + /** + * Notifies listeners about starting scrolling + */ + protected void notifyScrollingListenersAboutStart() { + for (OnWheelScrollListener listener : scrollingListeners) { + listener.onScrollingStarted(this); + } + } + + /** + * Notifies listeners about ending scrolling + */ + protected void notifyScrollingListenersAboutEnd() { + for (OnWheelScrollListener listener : scrollingListeners) { + listener.onScrollingFinished(this); + } + } + + /** + * Gets current value + * + * @return the current value + */ + public int getCurrentItem() { + return currentItem; + } + + /** + * Sets the current item. Does nothing when index is wrong. + * + * @param index the item index + * @param animated the animation flag + */ + public void setCurrentItem(int index, boolean animated) { + if (adapter == null || adapter.getItemsCount() == 0) { + return; // throw? + } + if (index < 0 || index >= adapter.getItemsCount()) { + if (isCyclic) { + while (index < 0) { + index += adapter.getItemsCount(); + } + index %= adapter.getItemsCount(); + } else { + return; // throw? + } + } + if (index != currentItem) { + if (animated) { + scroll(index - currentItem, SCROLLING_DURATION); + } else { + invalidateLayouts(); + + int old = currentItem; + currentItem = index; + + notifyChangingListeners(old, currentItem); + + invalidate(); + } + } + } + + /** + * Sets the current item w/o animation. Does nothing when index is wrong. + * + * @param index the item index + */ + public void setCurrentItem(int index) { + setCurrentItem(index, false); + } + + /** + * Tests if wheel is cyclic. That means before the 1st item there is shown + * the last one + * + * @return true if wheel is cyclic + */ + public boolean isCyclic() { + return isCyclic; + } + + /** + * Set wheel cyclic flag + * + * @param isCyclic the flag to set + */ + public void setCyclic(boolean isCyclic) { + this.isCyclic = isCyclic; + + invalidate(); + invalidateLayouts(); + } + + /** + * Invalidates layouts + */ + private void invalidateLayouts() { + itemsLayout = null; + valueLayout = null; + scrollingOffset = 0; + } + + /** + * Initializes resources + */ + private void initResourcesIfNecessary() { + if (itemsPaint == null) { + itemsPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG + | Paint.FAKE_BOLD_TEXT_FLAG); + // itemsPaint.density = getResources().getDisplayMetrics().density; + itemsPaint.setTextSize(TEXT_SIZE); +// itemsPaint.setTextSize(ITEM_TEXT_SIZE); + } + + if (labelPaint == null) { + labelPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + // labelPaint.density = getResources().getDisplayMetrics().density; + labelPaint.setTextSize(ITEM_TEXT_SIZE); + } + + if (valuePaint == null) { + valuePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG + | Paint.FAKE_BOLD_TEXT_FLAG | Paint.DITHER_FLAG); + // valuePaint.density = getResources().getDisplayMetrics().density; + valuePaint.setTextSize(TEXT_SIZE); + valuePaint.setShadowLayer(0.1f, 0, 0.1f, 0xFFC0C0C0); + } + + if (centerDrawable == null) { + centerDrawable = getContext().getResources().getDrawable( + R.drawable.wheel_val); + } + + if (topShadow == null) { + topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, + SHADOWS_COLORS); + } + + if (bottomShadow == null) { + bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, + SHADOWS_COLORS); + } + +// setBackgroundResource(R.drawable.wheel_bg); + setBackgroundResource(R.color.transparent); + } + + /** + * Calculates desired height for layout + * + * @param layout the source layout + * @return the desired layout height + */ + private int getDesiredHeight(Layout layout) { + if (layout == null) { + return 0; + } + + int desired = getItemHeight() * visibleItems - ITEM_OFFSET * 2 + - ADDITIONAL_ITEM_HEIGHT; + + // Check against our minimum height + desired = Math.max(desired, getSuggestedMinimumHeight()); + + return desired; + } + + /** + * Returns text item by index + * + * @param index the item index + * @return the item or null + */ + private String getTextItem(int index) { + if (adapter == null || adapter.getItemsCount() == 0) { + return null; + } + int count = adapter.getItemsCount(); + if ((index < 0 || index >= count) && !isCyclic) { + return null; + } else { + while (index < 0) { + index = count + index; + } + } + + index %= count; + return adapter.getItem(index); + } + + /** + * Builds text depending on current value + * + * @param useCurrentValue + * @return the text + */ + private String buildText(boolean useCurrentValue) { + StringBuilder itemsText = new StringBuilder(); + int addItems = visibleItems / 2 + 1; + + for (int i = currentItem - addItems; i <= currentItem + addItems; i++) { + if (useCurrentValue || i != currentItem) { + String text = getTextItem(i); + if (text != null) { + itemsText.append(text); + } + } + if (i < currentItem + addItems) { + itemsText.append("\n"); + } + } + + return itemsText.toString(); + } + + /** + * Returns the max item length that can be present + * + * @return the max length + */ + private int getMaxTextLength() { + WheelAdapter adapter = getAdapter(); + if (adapter == null) { + return 0; + } + + int adapterLength = adapter.getMaximumLength(); + if (adapterLength > 0) { + return adapterLength; + } + + String maxText = null; + int addItems = visibleItems / 2; + for (int i = Math.max(currentItem - addItems, 0); i < Math.min( + currentItem + visibleItems, adapter.getItemsCount()); i++) { + String text = adapter.getItem(i); + if (text != null + && (maxText == null || maxText.length() < text.length())) { + maxText = text; + } + } + + return maxText != null ? maxText.length() : 0; + } + + /** + * Returns height of wheel item + * + * @return the item height + */ + private int getItemHeight() { + if (itemHeight != 0) { + return itemHeight; + } else if (itemsLayout != null && itemsLayout.getLineCount() > 2) { + itemHeight = itemsLayout.getLineTop(2) - itemsLayout.getLineTop(1); + return itemHeight; + } + + return getHeight() / visibleItems; + } + + /** + * Calculates control width and creates text layouts + * + * @param widthSize the input layout width + * @param mode the layout mode + * @return the calculated control width + */ + private int calculateLayoutWidth(int widthSize, int mode) { + initResourcesIfNecessary(); + + int width = widthSize; + + int maxLength = getMaxTextLength(); + if (maxLength > 0) { +// float textWidth = FloatMath.ceil(Layout.getDesiredWidth("0", +// itemsPaint)); + float textWidth = (float) Math.ceil(Layout.getDesiredWidth("0", + itemsPaint)); + itemsWidth = (int) (maxLength * textWidth); + } else { + itemsWidth = 0; + } + itemsWidth += ADDITIONAL_ITEMS_SPACE; // make it some more + + labelWidth = 0; + if (label != null && label.length() > 0) { +// labelWidth = (int) FloatMath.ceil(Layout.getDesiredWidth(label, +// valuePaint)); + labelWidth = (int) Math.ceil(Layout.getDesiredWidth(label, + labelPaint)); + } + + boolean recalculate = false; + if (mode == MeasureSpec.EXACTLY) { + width = widthSize; + recalculate = true; + } else { + width = itemsWidth + labelWidth + 2 * PADDING; + if (labelWidth > 0) { + width += LABEL_OFFSET; + } + + // Check against our minimum width + width = Math.max(width, getSuggestedMinimumWidth()); + + if (mode == MeasureSpec.AT_MOST && widthSize < width) { + width = widthSize; + recalculate = true; + } + } + + if (recalculate) { + // recalculate width + int pureWidth = width - LABEL_OFFSET - 2 * PADDING; + if (pureWidth <= 0) { + itemsWidth = labelWidth = 0; + } + if (labelWidth > 0) { + double newWidthItems = (double) itemsWidth * pureWidth + / (itemsWidth + labelWidth); + itemsWidth = (int) newWidthItems; + labelWidth = pureWidth - itemsWidth; + } else { + itemsWidth = pureWidth + LABEL_OFFSET; // no label + } + } + + if (itemsWidth > 0) { + createLayouts(itemsWidth, labelWidth); + } + + return width; + } + + /** + * Creates layouts + * + * @param widthItems width of items layout + * @param widthLabel width of label layout + */ + private void createLayouts(int widthItems, int widthLabel) { + if (itemsLayout == null || itemsLayout.getWidth() > widthItems) { + itemsLayout = new StaticLayout(buildText(isScrollingPerformed), + itemsPaint, widthItems, + /* widthLabel > 0 ? Layout.Alignment.ALIGN_OPPOSITE :*/ Layout.Alignment.ALIGN_CENTER, + 1, + ADDITIONAL_ITEM_HEIGHT, false); + } else { + itemsLayout.increaseWidthTo(widthItems); + } + + if (!isScrollingPerformed + && (valueLayout == null || valueLayout.getWidth() > widthItems)) { + String text = getAdapter() != null ? getAdapter().getItem( + currentItem) : null; + valueLayout = new StaticLayout(text != null ? text : "", + valuePaint, widthItems, + /* widthLabel > 0 ? Layout.Alignment.ALIGN_OPPOSITE :*/ Layout.Alignment.ALIGN_CENTER, + 1, + ADDITIONAL_ITEM_HEIGHT, false); + } else if (isScrollingPerformed) { + valueLayout = null; + } else { + valueLayout.increaseWidthTo(widthItems); + } + + if (widthLabel > 0) { + if (labelLayout == null || labelLayout.getWidth() > widthLabel) { +// TextPaint labelPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.FAKE_BOLD_TEXT_FLAG); +// // labelPaint.density = getResources().getDisplayMetrics().density; +// labelPaint.setTextSize(ITEM_TEXT_SIZE); + labelLayout = new StaticLayout(label, /* valuePaint */ labelPaint, widthLabel, + Layout.Alignment.ALIGN_NORMAL, 1, + ADDITIONAL_ITEM_HEIGHT, false); + } else { + labelLayout.increaseWidthTo(widthLabel); + } + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + int width = calculateLayoutWidth(widthSize, widthMode); + + int height; + if (heightMode == MeasureSpec.EXACTLY) { + height = heightSize; + } else { + height = getDesiredHeight(itemsLayout); + + if (heightMode == MeasureSpec.AT_MOST) { + height = Math.min(height, heightSize); + } + } + + setMeasuredDimension(width, height); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (itemsLayout == null) { + if (itemsWidth == 0) { + calculateLayoutWidth(getWidth(), MeasureSpec.EXACTLY); + } else { + createLayouts(itemsWidth, labelWidth); + } + } + + if (itemsWidth > 0) { + canvas.save(); + // Skip padding space and hide a part of top and bottom items + canvas.translate(PADDING, -ITEM_OFFSET); + drawItems(canvas); + drawValue(canvas); + canvas.restore(); + } + +// drawCenterRect(canvas); +// drawShadows(canvas); + } + + /** + * Draws shadows on top and bottom of control + * + * @param canvas the canvas for drawing + */ + private void drawShadows(Canvas canvas) { + topShadow.setBounds(0, 0, getWidth(), getHeight() / visibleItems); + topShadow.draw(canvas); + + bottomShadow.setBounds(0, getHeight() - getHeight() / visibleItems, + getWidth(), getHeight()); + bottomShadow.draw(canvas); + } + + /** + * Draws value and label layout + * + * @param canvas the canvas for drawing + */ + private void drawValue(Canvas canvas) { + valuePaint.setColor(VALUE_TEXT_COLOR); + valuePaint.drawableState = getDrawableState(); + + labelPaint.setColor(ITEMS_TEXT_COLOR); + labelPaint.drawableState = getDrawableState(); + + Rect bounds = new Rect(); + int baseLine = itemsLayout.getLineBounds(visibleItems / 2, bounds); + + // draw label + if (labelLayout != null) { + canvas.save(); +// canvas.translate(itemsLayout.getWidth() + LABEL_OFFSET, +// bounds.top + ((bounds.height() - labelLayout.getHeight()) / 2)); + // 确保 Label 与 Value 中线对齐 + canvas.translate(itemsLayout.getWidth() + LABEL_OFFSET, + baseLine - (labelLayout.getHeight()/2)); + labelLayout.draw(canvas); + canvas.restore(); + } + + // draw current value + if (valueLayout != null) { + canvas.save(); + canvas.translate(0, bounds.top + scrollingOffset); + valueLayout.draw(canvas); + canvas.restore(); + } + } + + /** + * Draws items + * + * @param canvas the canvas for drawing + */ + private void drawItems(Canvas canvas) { + canvas.save(); + + int top = itemsLayout.getLineTop(1); + canvas.translate(0, -top + scrollingOffset); + + itemsPaint.setColor(ITEMS_TEXT_COLOR); + itemsPaint.setTextSize(ITEM_TEXT_SIZE); + itemsPaint.drawableState = getDrawableState(); + itemsLayout.draw(canvas); + itemsPaint.setTextSize(TEXT_SIZE); + + canvas.restore(); + } + + /** + * Draws rect for current value + * + * @param canvas the canvas for drawing + */ + private void drawCenterRect(Canvas canvas) { + int center = getHeight() / 2; + int offset = getItemHeight() / 2; + centerDrawable.setBounds(0, center - offset, getWidth(), center + + offset); + centerDrawable.draw(canvas); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + WheelAdapter adapter = getAdapter(); + if (adapter == null) { + return true; + } + + if (!gestureDetector.onTouchEvent(event) + && event.getAction() == MotionEvent.ACTION_UP) { + justify(); + } + return true; + } + + /** + * Scrolls the wheel + * + * @param delta the scrolling value + */ + private void doScroll(int delta) { + scrollingOffset += delta; + + int count = scrollingOffset / getItemHeight(); + int pos = currentItem - count; + if (isCyclic && adapter.getItemsCount() > 0) { + // fix position by rotating + while (pos < 0) { + pos += adapter.getItemsCount(); + } + pos %= adapter.getItemsCount(); + } else if (isScrollingPerformed) { + // + if (pos < 0) { + count = currentItem; + pos = 0; + } else if (pos >= adapter.getItemsCount()) { + count = currentItem - adapter.getItemsCount() + 1; + pos = adapter.getItemsCount() - 1; + } + } else { + // fix position + pos = Math.max(pos, 0); + pos = Math.min(pos, adapter.getItemsCount() - 1); + } + + int offset = scrollingOffset; + if (pos != currentItem) { + setCurrentItem(pos, false); + } else { + invalidate(); + } + + // update offset + scrollingOffset = offset - count * getItemHeight(); + if (scrollingOffset > getHeight()) { + scrollingOffset = scrollingOffset % getHeight() + getHeight(); + } + } + + // gesture listener + private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() { + public boolean onDown(MotionEvent e) { + if (isScrollingPerformed) { + scroller.forceFinished(true); + clearMessages(); + return true; + } + return false; + } + + public boolean onScroll(MotionEvent e1, MotionEvent e2, + float distanceX, float distanceY) { + startScrolling(); + doScroll((int) -distanceY); + return true; + } + + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, + float velocityY) { + lastScrollY = currentItem * getItemHeight() + scrollingOffset; + int maxY = isCyclic ? 0x7FFFFFFF : adapter.getItemsCount() + * getItemHeight(); + int minY = isCyclic ? -maxY : 0; + scroller.fling(0, lastScrollY, 0, (int) -velocityY / 2, 0, 0, minY, + maxY); + setNextMessage(MESSAGE_SCROLL); + return true; + } + }; + + // Messages + private final int MESSAGE_SCROLL = 0; + private final int MESSAGE_JUSTIFY = 1; + + /** + * Set next message to queue. Clears queue before. + * + * @param message the message to set + */ + private void setNextMessage(int message) { + clearMessages(); + animationHandler.sendEmptyMessage(message); + } + + /** + * Clears messages from queue + */ + private void clearMessages() { + animationHandler.removeMessages(MESSAGE_SCROLL); + animationHandler.removeMessages(MESSAGE_JUSTIFY); + } + + // animation handler + private Handler animationHandler = new Handler() { + public void handleMessage(Message msg) { + scroller.computeScrollOffset(); + int currY = scroller.getCurrY(); + int delta = lastScrollY - currY; + lastScrollY = currY; + if (delta != 0) { + doScroll(delta); + } + + // scrolling is not finished when it comes to final Y + // so, finish it manually + if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) { + currY = scroller.getFinalY(); + scroller.forceFinished(true); + } + if (!scroller.isFinished()) { + animationHandler.sendEmptyMessage(msg.what); + } else if (msg.what == MESSAGE_SCROLL) { + justify(); + } else { + finishScrolling(); + } + } + }; + + /** + * Justifies wheel + */ + private void justify() { + if (adapter == null) { + return; + } + + lastScrollY = 0; + int offset = scrollingOffset; + int itemHeight = getItemHeight(); + boolean needToIncrease = offset > 0 ? currentItem < adapter + .getItemsCount() : currentItem > 0; + if ((isCyclic || needToIncrease) + && Math.abs((float) offset) > (float) itemHeight / 2) { + if (offset < 0) + offset += itemHeight + MIN_DELTA_FOR_SCROLLING; + else + offset -= itemHeight + MIN_DELTA_FOR_SCROLLING; + } + if (Math.abs(offset) > MIN_DELTA_FOR_SCROLLING) { + scroller.startScroll(0, 0, 0, offset, SCROLLING_DURATION); + setNextMessage(MESSAGE_JUSTIFY); + } else { + finishScrolling(); + } + } + + /** + * Starts scrolling + */ + private void startScrolling() { + if (!isScrollingPerformed) { + isScrollingPerformed = true; + notifyScrollingListenersAboutStart(); + } + } + + /** + * Finishes scrolling + */ + void finishScrolling() { + if (isScrollingPerformed) { + notifyScrollingListenersAboutEnd(); + isScrollingPerformed = false; + } + invalidateLayouts(); + invalidate(); + } + + /** + * Scroll the wheel + * + * @param itemsToScroll items to scroll + * @param time scrolling duration + */ + public void scroll(int itemsToScroll, int time) { + scroller.forceFinished(true); + + lastScrollY = scrollingOffset; + int offset = itemsToScroll * getItemHeight(); + + scroller.startScroll(0, lastScrollY, 0, offset - lastScrollY, time); + setNextMessage(MESSAGE_SCROLL); + + startScrolling(); + } + +} diff --git a/app/src/main/java/com/ic/hardware/widget/ring/OnSelectRing.java b/app/src/main/java/com/ic/hardware/widget/ring/OnSelectRing.java new file mode 100644 index 0000000..eda60ca --- /dev/null +++ b/app/src/main/java/com/ic/hardware/widget/ring/OnSelectRing.java @@ -0,0 +1,5 @@ +package com.ic.hardware.widget.ring; + +public interface OnSelectRing { + void Selected(Ring r); +} diff --git a/app/src/main/java/com/ic/hardware/widget/ring/Ring.java b/app/src/main/java/com/ic/hardware/widget/ring/Ring.java new file mode 100644 index 0000000..e510c17 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/widget/ring/Ring.java @@ -0,0 +1,75 @@ +package com.ic.hardware.widget.ring; + +import android.graphics.RectF; + +public class Ring { + private int progress; + private String name; + private String value; + private RectF rectFRing; + private int startColor; + private int endColor; + + + public Ring(int p, String value, String name,int startColor, int endColor) { + this.progress = p; + this.name = name; + this.value = value; + this.startColor = startColor; + this.endColor = endColor; + + } + + public Ring() { + } + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getProgress() { + return progress; + } + + public void setProgress(int progress) { + this.progress = progress; + } + + public RectF getRectFRing() { + return rectFRing; + } + + public void setRectFRing(RectF rectFRing) { + this.rectFRing = rectFRing; + } + + + public int getStartColor() { + return startColor; + } + + public void setStartColor(int startColor) { + this.startColor = startColor; + } + + public int getEndColor() { + return endColor; + } + + public void setEndColor(int endColor) { + this.endColor = endColor; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/app/src/main/java/com/ic/hardware/widget/ring/RingProgress.java b/app/src/main/java/com/ic/hardware/widget/ring/RingProgress.java new file mode 100644 index 0000000..6c8fa30 --- /dev/null +++ b/app/src/main/java/com/ic/hardware/widget/ring/RingProgress.java @@ -0,0 +1,647 @@ +package com.ic.hardware.widget.ring; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.LinearInterpolator; + +import com.ic.hardware.R; + +import java.util.ArrayList; +import java.util.List; + +public class RingProgress extends View { + + private Paint mPaint; + private Bitmap mBitmapBg; + private Paint mPaintText; + private int SweepAngle = 180; + private int mPadding; + private int mWidth; + + private int ringWidth = 0; + + + private int rotateAngle = 270; + + private int bgShadowColor = Color.argb(100, 0, 0, 0); + private int bgColor = Color.rgb(141, 141, 141); + + private List mListRing = new ArrayList<>(); + private RectF rectFBg = new RectF(); + private boolean isCorner = true; + private boolean isDrawBg = true; + private boolean isDrawBgShadow = true; + private float ringWidthScale = 0f; + private boolean bgChange = false; + + public int getSweepAngle() { + return SweepAngle; + } + + public void setSweepAngle(int sweepAngle) { + + if (sweepAngle < 0) + sweepAngle = 0; + else if (sweepAngle > 360) + sweepAngle = 360; + SweepAngle = sweepAngle; + bgChange = true; + invalidate(); + } + + public int getRotateAngle() { + return rotateAngle; + } + + public void setRotateAngle(int rotateAngle) { + + if (rotateAngle < 0) + rotateAngle = 0; + else if (rotateAngle > 360) + rotateAngle = 360; + + + this.rotateAngle = rotateAngle; + invalidate(); + } + + public boolean isCorner() { + return isCorner; + } + + public void setCorner(boolean corner) { + isCorner = corner; + bgChange = true; + invalidate(); + } + + public boolean isDrawBgShadow() { + return isDrawBgShadow; + } + + public void setDrawBgShadow(boolean drawBgShadow) { + isDrawBgShadow = drawBgShadow; + bgChange = true; + invalidate(); + } + + public void setDrawBgShadow(boolean drawBgShadow, int color) { + isDrawBgShadow = drawBgShadow; + this.bgShadowColor = color; + bgChange = true; + invalidate(); + } + + + public boolean isDrawBg() { + return isDrawBg; + } + + public void setDrawBg(boolean drawBg) { + isDrawBg = drawBg; + bgChange = true; + invalidate(); + } + + public void setDrawBg(boolean drawBg, int color) { + isDrawBg = drawBg; + this.bgColor = color; + bgChange = true; + invalidate(); + } + + public List getmListRing() { + return mListRing; + } + + public void setmListRing(List mListRing) { + this.mListRing = mListRing; + } + + + public float getRingWidthScale() { + return ringWidthScale; + } + + public void setRingWidthScale(float ringWidthScale) { + this.ringWidthScale = ringWidthScale; + bgChange = true; + invalidate(); + } + + + public void setData(List mListRing, int time) { + this.mListRing.clear(); + for (int i = 0; i < mListRing.size(); i++) { + + RectF r = new RectF(); + r.top = rectFBg.top + ringWidth * i; + r.bottom = rectFBg.bottom - ringWidth * i; + r.left = rectFBg.left + ringWidth * i; + r.right = rectFBg.right - ringWidth * i; + mListRing.get(i).setRectFRing(r); + } + + for (int i = 0; i < mListRing.size(); i++) { + this.mListRing.add(mListRing.get(i)); + } + if (time > 0) + startAnim(time); + else + invalidate(); + } + + + public RingProgress(Context context) { + this(context, null); + } + + public RingProgress(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public RingProgress(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(attrs); + } + + + private void init(AttributeSet attrs) { + TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.RingProgress); + isCorner = typedArray.getBoolean(R.styleable.RingProgress_showRingCorner, false); + isDrawBg = typedArray.getBoolean(R.styleable.RingProgress_showBackground, false); + isDrawBgShadow = typedArray.getBoolean(R.styleable.RingProgress_showBackgroundShadow, false); + rotateAngle = typedArray.getInt(R.styleable.RingProgress_rotate, 270); + ringWidthScale = typedArray.getFloat(R.styleable.RingProgress_ringWidthScale, 0.5f); + bgShadowColor = typedArray.getColor(R.styleable.RingProgress_bgShadowColor, bgShadowColor); + bgColor = typedArray.getColor(R.styleable.RingProgress_bgColor, bgColor); + SweepAngle = typedArray.getInt(R.styleable.RingProgress_ringSweepAngle, 180); + typedArray.recycle(); + + + initPaint(); + } + + + private void initPaint() { + mPaint = new Paint(); + + mPaintText = new Paint(); + mPaintText.setAntiAlias(true); + mPaintText.setStyle(Paint.Style.FILL); + mPaintText.setColor(Color.WHITE); + + } + + + private void setmBitmapBg(Paint paint, Bitmap mBitmapBg) { + Canvas canvas = null; + canvas = new Canvas(mBitmapBg); + + for (int i = 0; i < mListRing.size(); i++) { + paint.reset(); + paint.setAntiAlias(true); + paint.setStrokeWidth(ringWidth); + paint.setStyle(Paint.Style.STROKE); + if (isCorner) { + paint.setStrokeCap(Paint.Cap.ROUND); + paint.setStrokeJoin(Paint.Join.ROUND); + } + + int red = (bgColor & 0xff0000) >> 16; + int green = (bgColor & 0x00ff00) >> 8; + int blue = (bgColor & 0x0000ff); + int colorvaluer = red + (255 - red) / mListRing.size() * i; + int colorvalueg = green + (255 - green) / mListRing.size() * i; + int colorvalueb = blue + (255 - blue) / mListRing.size() * i; + + paint.setColor(Color.rgb(colorvaluer, colorvalueg, colorvalueb)); + + + Path pathBg = new Path(); + RectF r = new RectF(); + r.top = rectFBg.top + ringWidth * i; + r.bottom = rectFBg.bottom - ringWidth * i; + r.left = rectFBg.left + ringWidth * i; + r.right = rectFBg.right - ringWidth * i; + mListRing.get(i).setRectFRing(r); + + pathBg.addArc(r, 0, SweepAngle); + + if (i == 0 && isDrawBgShadow) { + paint.setShadowLayer(ringWidth / 3, + 0 - ringWidth / 4, + 0, bgShadowColor); + } + if (isDrawBg) + canvas.drawPath(pathBg, paint); + + } + bgChange = false; + + } + + + private Bitmap getmBitmapBg(Paint paint) { + + if (mBitmapBg == null) { + mBitmapBg = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); + setmBitmapBg(paint, mBitmapBg); + + } + + if (bgChange) { + mBitmapBg = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); + setmBitmapBg(paint, mBitmapBg); + } + + + return mBitmapBg; + + } + + + private void drawBg(Canvas canvas, Paint paint) { + paint.setAntiAlias(true); + canvas.drawBitmap(getmBitmapBg(paint), 0 + , 0, paint); + } + + + private void drawProgress(Canvas canvas, Paint paint) { + + + for (int i = 0; i < mListRing.size(); i++) { + + paint.reset(); + paint.setAntiAlias(true); + paint.setStrokeWidth(ringWidth); + paint.setStyle(Paint.Style.STROKE); + Path pathProgress = new Path(); + pathProgress.addArc(mListRing.get(i).getRectFRing(), 0, + + (int) (SweepAngle / 100f * mListRing.get(i).getProgress() * mAnimatedValue) + + ); + + Shader mShader = new LinearGradient(mListRing.get(i).getRectFRing().left, mListRing.get(i).getRectFRing().top, + mListRing.get(i).getRectFRing().left, mListRing.get(i).getRectFRing().bottom, + new int[]{ + mListRing.get(i).getStartColor(), + mListRing.get(i).getEndColor() + + }, new float[]{0f, 1f}, + Shader.TileMode.CLAMP); + + paint.setShader(mShader); + if (isCorner) { + paint.setStrokeCap(Paint.Cap.ROUND); + paint.setStrokeJoin(Paint.Join.ROUND); + } + canvas.drawPath(pathProgress, paint); + paint.setShader(null); + + + mPaintText.setTextSize(mPaint.getStrokeWidth() / 2); + + + String textvalue = String.valueOf(mListRing.get(i).getValue()); + + float arc_length = (float) (Math.PI * mListRing.get(i).getRectFRing().width() + * (mListRing.get(i).getProgress() / 100f)) + * (SweepAngle / 360f); + + float textvalue_length = getFontlength(mPaintText, textvalue); + + if (mAnimatedValue == 1) { + + + if (arc_length - textvalue_length * 1.5f <= 0) { + + + float textvalue_length_one = textvalue_length * 1.0f / textvalue.length(); + + + int textvalue_size = (int) (arc_length / textvalue_length_one); + + if (textvalue_size >= textvalue.length()) { + canvas.drawTextOnPath(textvalue + , + pathProgress, + 10, + getFontHeight(mPaintText) / 3, + mPaintText); + } else { + String text = textvalue.substring(0, 1); + for (int j = 0; j < textvalue_size; j++) { + text = text + "."; + } + + canvas.drawTextOnPath(text + , + pathProgress, + 10, + getFontHeight(mPaintText) / 3, + mPaintText); + + + } + } else { + + canvas.drawTextOnPath(textvalue + , + pathProgress, + (float) (arc_length + - textvalue_length * 1.5f), + getFontHeight(mPaintText) / 3, + mPaintText + + ); + } + } + + + String text = String.valueOf(mListRing.get(i).getName()); + + + float textlength = getFontlength(mPaintText, text); + + float textlength_one = textlength * 1.0f / text.length(); + + float showtextlength = (float) (arc_length + - textvalue_length * 1.8f); + if (showtextlength < 0) + showtextlength = 0; + + float textsize = showtextlength / textlength_one; + + if (textsize > text.length()) { + textsize = text.length(); + } else if (textsize < 1) { + textsize = 0; + } + + canvas.drawTextOnPath(text.substring(0, (int) textsize) + , + pathProgress, + + 10, getFontHeight(mPaintText) / 3, + mPaintText + + ); + + + } + + } + + + @SuppressLint("DrawAllocation") + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + + canvas.rotate(rotateAngle, getMeasuredWidth() / 2f, getMeasuredHeight() / 2f); + canvas.save(); + + if (mListRing.size() > 0) + ringWidth = (int) ( + mWidth / 2f / (mListRing.size() + 0.5f) * (1 - ringWidthScale)); + mPadding = ringWidth; + rectFBg = new RectF(getMeasuredWidth() / 2 - mWidth / 2 + mPadding + , getMeasuredHeight() / 2 - mWidth / 2 + mPadding + , getMeasuredWidth() / 2 + mWidth / 2 - mPadding + , getMeasuredHeight() / 2 + mWidth / 2 - mPadding); + + drawBg(canvas, mPaint); + drawProgress(canvas, mPaint); + canvas.restore(); + + } + + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); + int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); + int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); + if (widthSpecMode == MeasureSpec.AT_MOST + && heightSpecMode == MeasureSpec.AT_MOST) { + setMeasuredDimension(dip2px(30), dip2px(30)); + } else if (widthSpecMode == MeasureSpec.AT_MOST) { + setMeasuredDimension(heightSpecSize, heightSpecSize); + } else if (heightSpecMode == MeasureSpec.AT_MOST) { + setMeasuredDimension(widthSpecSize, widthSpecSize); + } + if (getMeasuredWidth() > getHeight()) + mWidth = getMeasuredHeight(); + else + mWidth = getMeasuredWidth(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + if (w > h) + mWidth = h; + else + mWidth = w; + + + } + + + public float getFontlength(Paint paint, String str) { + return paint.measureText(str); + } + + public float getFontHeight(Paint paint) { + Paint.FontMetrics fm = paint.getFontMetrics(); + return fm.descent - fm.ascent; + } + + public int dip2px(float dpValue) { + final float scale = getContext().getResources().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } + + + public void startAnim(int time) { + stopAnim(); + startViewAnim(0f, 1f, time); + } + + private ValueAnimator valueAnimator; + private float mAnimatedValue = 1f; + + public void stopAnim() { + if (valueAnimator != null) { + clearAnimation(); + valueAnimator.setRepeatCount(0); + valueAnimator.cancel(); + mAnimatedValue = 0f; + postInvalidate(); + } + } + + + private ValueAnimator startViewAnim(float startF, final float endF, long time) { + valueAnimator = ValueAnimator.ofFloat(startF, endF); + valueAnimator.setDuration(time); + valueAnimator.setInterpolator(new LinearInterpolator()); + valueAnimator.setRepeatCount(0); + valueAnimator.setRepeatMode(ValueAnimator.RESTART); + valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + + mAnimatedValue = (float) valueAnimator.getAnimatedValue(); + invalidate(); + + + } + }); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + + } + + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + } + + @Override + public void onAnimationRepeat(Animator animation) { + super.onAnimationRepeat(animation); + } + }); + if (!valueAnimator.isRunning()) { + valueAnimator.start(); + + } + + return valueAnimator; + } + + + float startX = 0; + float startY = 0; + + @Override + public boolean onTouchEvent(MotionEvent event) { + + if (MotionEvent.ACTION_DOWN == event.getAction()) { + startX = event.getX(); + startY = event.getY(); + return true; + } else if (MotionEvent.ACTION_UP == event.getAction()) { + if (Math.abs(event.getX() - startX) < 5 && + Math.abs(event.getY() - startY) < 5) { + + + float distance = (float) Math.sqrt(Math.pow(Math.abs((event.getX() - rectFBg.centerX())), 2) + + Math.pow(Math.abs((event.getY() - rectFBg.centerY())), 2)); + + for (int i = mListRing.size() - 1; i >= 0; i--) { + + if (mListRing.get(i).getRectFRing().width() / 2 + ringWidth / 2 > distance + && mListRing.get(i).getRectFRing().width() / 2 - ringWidth / 2 < distance + ) { + + float angle = + Math.round((float) + (Math.asin( + Math.abs((event.getY() - rectFBg.centerY())) / distance) / Math.PI * 180)); + + if (event.getY() - rectFBg.centerY() >= 0 && + event.getX() - rectFBg.centerX() >= 0) { + angle = angle + 0; + + } else if (event.getY() - rectFBg.centerY() <= 0 && + event.getX() - rectFBg.centerX() >= 0) { + angle = 360 - angle; + } else if (event.getY() - rectFBg.centerY() <= 0 && + event.getX() - rectFBg.centerX() <= 0) { + angle = 180 + angle; + } else if (event.getY() - rectFBg.centerY() >= 0 && + event.getX() - rectFBg.centerX() <= 0) { + angle = 180 - angle; + + } + + + if (mListRing.get(i).getProgress() / 100f * 360f + rotateAngle <= 360 && rotateAngle <= 360) { + + if (angle >= rotateAngle && angle <= mListRing.get(i).getProgress() / 100f * 360f + rotateAngle) { + if (mOnSelectRing != null) { + mOnSelectRing.Selected(mListRing.get(i)); + } + } + + + } else if (mListRing.get(i).getProgress() / 100f * 360f + rotateAngle >= 360 && rotateAngle <= 360) { + + + if (angle >= rotateAngle && angle <= 360) { + if (mOnSelectRing != null) { + mOnSelectRing.Selected(mListRing.get(i)); + } + } else if (angle >= 0 && mListRing.get(i).getProgress() / 100f * 360f + rotateAngle - 360 >= angle) { + if (mOnSelectRing != null) { + mOnSelectRing.Selected(mListRing.get(i)); + } + } + + + } + + + return true; + + } + + } + + + return true; + + } + + + } + + return false; + } + + + private OnSelectRing mOnSelectRing; + + public OnSelectRing getmOnSelectRing() { + return mOnSelectRing; + } + + public void setOnSelectRing(OnSelectRing mOnSelectRing) { + this.mOnSelectRing = mOnSelectRing; + } +} diff --git a/app/src/main/res/anim/slide_left_in.xml b/app/src/main/res/anim/slide_left_in.xml new file mode 100644 index 0000000..363aa32 --- /dev/null +++ b/app/src/main/res/anim/slide_left_in.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_left_out.xml b/app/src/main/res/anim/slide_left_out.xml new file mode 100644 index 0000000..8ceff44 --- /dev/null +++ b/app/src/main/res/anim/slide_left_out.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_right_in.xml b/app/src/main/res/anim/slide_right_in.xml new file mode 100644 index 0000000..c8c45b6 --- /dev/null +++ b/app/src/main/res/anim/slide_right_in.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_right_out.xml b/app/src/main/res/anim/slide_right_out.xml new file mode 100644 index 0000000..5687d63 --- /dev/null +++ b/app/src/main/res/anim/slide_right_out.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0d025f9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_ped_calories.xml b/app/src/main/res/drawable/ic_ped_calories.xml new file mode 100644 index 0000000..b063cb6 --- /dev/null +++ b/app/src/main/res/drawable/ic_ped_calories.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_ped_distance.xml b/app/src/main/res/drawable/ic_ped_distance.xml new file mode 100644 index 0000000..0dac9b6 --- /dev/null +++ b/app/src/main/res/drawable/ic_ped_distance.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_ped_height.xml b/app/src/main/res/drawable/ic_ped_height.xml new file mode 100644 index 0000000..7a68699 --- /dev/null +++ b/app/src/main/res/drawable/ic_ped_height.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_ped_taking.xml b/app/src/main/res/drawable/ic_ped_taking.xml new file mode 100644 index 0000000..50a8cd8 --- /dev/null +++ b/app/src/main/res/drawable/ic_ped_taking.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_ped_task.xml b/app/src/main/res/drawable/ic_ped_task.xml new file mode 100644 index 0000000..0c0d57d --- /dev/null +++ b/app/src/main/res/drawable/ic_ped_task.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_ped_weight.xml b/app/src/main/res/drawable/ic_ped_weight.xml new file mode 100644 index 0000000..f0613d5 --- /dev/null +++ b/app/src/main/res/drawable/ic_ped_weight.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_red_flag.xml b/app/src/main/res/drawable/ic_red_flag.xml new file mode 100644 index 0000000..c22e389 --- /dev/null +++ b/app/src/main/res/drawable/ic_red_flag.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_transparent_circle.xml b/app/src/main/res/drawable/ic_transparent_circle.xml new file mode 100644 index 0000000..7fd130f --- /dev/null +++ b/app/src/main/res/drawable/ic_transparent_circle.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_white_circle.xml b/app/src/main/res/drawable/ic_white_circle.xml new file mode 100644 index 0000000..a032825 --- /dev/null +++ b/app/src/main/res/drawable/ic_white_circle.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/wheel_val.xml b/app/src/main/res/drawable/wheel_val.xml new file mode 100644 index 0000000..ea38cf2 --- /dev/null +++ b/app/src/main/res/drawable/wheel_val.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/app/src/main/res/layout/activity_blood.xml b/app/src/main/res/layout/activity_blood.xml new file mode 100644 index 0000000..1f5824c --- /dev/null +++ b/app/src/main/res/layout/activity_blood.xml @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_pedometer.xml b/app/src/main/res/layout/activity_pedometer.xml new file mode 100644 index 0000000..235addf --- /dev/null +++ b/app/src/main/res/layout/activity_pedometer.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_weather.xml b/app/src/main/res/layout/activity_weather.xml new file mode 100644 index 0000000..632aa96 --- /dev/null +++ b/app/src/main/res/layout/activity_weather.xml @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_ped_setup_layout.xml b/app/src/main/res/layout/dialog_ped_setup_layout.xml new file mode 100644 index 0000000..471f82c --- /dev/null +++ b/app/src/main/res/layout/dialog_ped_setup_layout.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_blood.xml b/app/src/main/res/layout/fragment_blood.xml new file mode 100644 index 0000000..75747d8 --- /dev/null +++ b/app/src/main/res/layout/fragment_blood.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_ped_main.xml b/app/src/main/res/layout/fragment_ped_main.xml new file mode 100644 index 0000000..476d431 --- /dev/null +++ b/app/src/main/res/layout/fragment_ped_main.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_ped_record.xml b/app/src/main/res/layout/fragment_ped_record.xml new file mode 100644 index 0000000..cdff5c3 --- /dev/null +++ b/app/src/main/res/layout/fragment_ped_record.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_ped_setup.xml b/app/src/main/res/layout/fragment_ped_setup.xml new file mode 100644 index 0000000..384fdfa --- /dev/null +++ b/app/src/main/res/layout/fragment_ped_setup.xml @@ -0,0 +1,25 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_weather.xml b/app/src/main/res/layout/fragment_weather.xml new file mode 100644 index 0000000..8121684 --- /dev/null +++ b/app/src/main/res/layout/fragment_weather.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_indicator_layout.xml b/app/src/main/res/layout/item_indicator_layout.xml new file mode 100644 index 0000000..8ca6c6d --- /dev/null +++ b/app/src/main/res/layout/item_indicator_layout.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_ped_record.xml b/app/src/main/res/layout/item_ped_record.xml new file mode 100644 index 0000000..d0e1cd9 --- /dev/null +++ b/app/src/main/res/layout/item_ped_record.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_ped_setup.xml b/app/src/main/res/layout/item_ped_setup.xml new file mode 100644 index 0000000..d66053f --- /dev/null +++ b/app/src/main/res/layout/item_ped_setup.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/widget_image_text_layout.xml b/app/src/main/res/layout/widget_image_text_layout.xml new file mode 100644 index 0000000..cab81c0 --- /dev/null +++ b/app/src/main/res/layout/widget_image_text_layout.xml @@ -0,0 +1,22 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..898f3ed Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..dffca36 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_cancel.png b/app/src/main/res/mipmap-mdpi/ic_cancel.png new file mode 100644 index 0000000..29a4bc8 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_cancel.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..64ba76f Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..dae5e08 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_ok.png b/app/src/main/res/mipmap-mdpi/ic_ok.png new file mode 100644 index 0000000..5001e57 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_ok.png differ diff --git a/app/src/main/res/mipmap-mdpi/qs_background.png b/app/src/main/res/mipmap-mdpi/qs_background.png new file mode 100644 index 0000000..1bc9fbd Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/qs_background.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_baoxue.png b/app/src/main/res/mipmap-mdpi/weather_status_baoxue.png new file mode 100644 index 0000000..4257a7b Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_baoxue.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_baoyu.png b/app/src/main/res/mipmap-mdpi/weather_status_baoyu.png new file mode 100644 index 0000000..ad1d7e7 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_baoyu.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_bingbao.png b/app/src/main/res/mipmap-mdpi/weather_status_bingbao.png new file mode 100644 index 0000000..91005e2 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_bingbao.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_daxue.png b/app/src/main/res/mipmap-mdpi/weather_status_daxue.png new file mode 100644 index 0000000..f9748b8 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_daxue.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_dayu.png b/app/src/main/res/mipmap-mdpi/weather_status_dayu.png new file mode 100644 index 0000000..ea95f73 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_dayu.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_duoyun.png b/app/src/main/res/mipmap-mdpi/weather_status_duoyun.png new file mode 100644 index 0000000..73c5477 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_duoyun.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_leizhenyu.png b/app/src/main/res/mipmap-mdpi/weather_status_leizhenyu.png new file mode 100644 index 0000000..7a22ef5 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_leizhenyu.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_none.png b/app/src/main/res/mipmap-mdpi/weather_status_none.png new file mode 100644 index 0000000..e2805a8 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_none.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_qing.png b/app/src/main/res/mipmap-mdpi/weather_status_qing.png new file mode 100644 index 0000000..cbc167d Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_qing.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_qingwu.png b/app/src/main/res/mipmap-mdpi/weather_status_qingwu.png new file mode 100644 index 0000000..db48257 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_qingwu.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_qingyu.png b/app/src/main/res/mipmap-mdpi/weather_status_qingyu.png new file mode 100644 index 0000000..50edb91 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_qingyu.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_qingyun.png b/app/src/main/res/mipmap-mdpi/weather_status_qingyun.png new file mode 100644 index 0000000..925d672 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_qingyun.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_shachenbao.png b/app/src/main/res/mipmap-mdpi/weather_status_shachenbao.png new file mode 100644 index 0000000..76dae87 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_shachenbao.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_wu.png b/app/src/main/res/mipmap-mdpi/weather_status_wu.png new file mode 100644 index 0000000..6294853 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_wu.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_xiaoxue.png b/app/src/main/res/mipmap-mdpi/weather_status_xiaoxue.png new file mode 100644 index 0000000..2e5f312 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_xiaoxue.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_xiaoyu.png b/app/src/main/res/mipmap-mdpi/weather_status_xiaoyu.png new file mode 100644 index 0000000..f0b6e1d Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_xiaoyu.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_yangsha.png b/app/src/main/res/mipmap-mdpi/weather_status_yangsha.png new file mode 100644 index 0000000..22c5b41 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_yangsha.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_yin.png b/app/src/main/res/mipmap-mdpi/weather_status_yin.png new file mode 100644 index 0000000..09bbd4d Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_yin.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_yinduoyun.png b/app/src/main/res/mipmap-mdpi/weather_status_yinduoyun.png new file mode 100644 index 0000000..7a97d25 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_yinduoyun.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_yinyu.png b/app/src/main/res/mipmap-mdpi/weather_status_yinyu.png new file mode 100644 index 0000000..e90d876 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_yinyu.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_zhenyu.png b/app/src/main/res/mipmap-mdpi/weather_status_zhenyu.png new file mode 100644 index 0000000..526af7f Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_zhenyu.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_zhongxue.png b/app/src/main/res/mipmap-mdpi/weather_status_zhongxue.png new file mode 100644 index 0000000..54fd365 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_zhongxue.png differ diff --git a/app/src/main/res/mipmap-mdpi/weather_status_zhongyu.png b/app/src/main/res/mipmap-mdpi/weather_status_zhongyu.png new file mode 100644 index 0000000..d8009a3 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/weather_status_zhongyu.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..e5ed465 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..14ed0af Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..b0907ca Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..d8ae031 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..2c18de9 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..beed3cd Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 0000000..822d36a --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..4cf8613 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #008577 + #00574B + #D81B60 + + + #00000000 + #000000 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..0b6bcc9 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,40 @@ + + IcHardware + + + Hello blank fragment + + 高压 + 低压 + 心率 + + 未检测到设备 + 未正确佩戴 + + 请保持安静 + 准备测量 + 正在测量中 + 已停止测量 + 未测量到数据 + + 个人设置 + 身高 + 体重 + 目标 + + 厘米 + 千克 + æ­¥ + + 最近记录 + 大卡 + 公里 + + 未获取到天气 + + %1$s℃ + %1$s~%2$s℃ + + 今日 + æ­¥ + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..daefc08 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/app/src/test/java/com/ic/hardware/ExampleUnitTest.java b/app/src/test/java/com/ic/hardware/ExampleUnitTest.java new file mode 100644 index 0000000..7086040 --- /dev/null +++ b/app/src/test/java/com/ic/hardware/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.ic.hardware; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..fb516be --- /dev/null +++ b/build.gradle @@ -0,0 +1,27 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + google() + jcenter() + + } + dependencies { + classpath 'com.android.tools.build:gradle:3.5.2' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + jcenter() + + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..199d16e --- /dev/null +++ b/gradle.properties @@ -0,0 +1,20 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..f6b961f Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..b349785 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Mar 17 17:06:55 CST 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..31300e9 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +include ':app' +rootProject.name='IcHardware'