--- /dev/null
+*.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
--- /dev/null
+IcLauncher
\ No newline at end of file
--- /dev/null
+<component name="ProjectCodeStyleConfiguration">
+ <code_scheme name="Project" version="173">
+ <codeStyleSettings language="XML">
+ <indentOptions>
+ <option name="CONTINUATION_INDENT_SIZE" value="4" />
+ </indentOptions>
+ <arrangement>
+ <rules>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>xmlns:android</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>xmlns:.*</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:id</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:name</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>name</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>style</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>ANDROID_ATTRIBUTE_ORDER</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>.*</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ </rules>
+ </arrangement>
+ </codeStyleSettings>
+ </code_scheme>
+</component>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="GradleSettings">
+ <option name="linkedExternalProjectsSettings">
+ <GradleProjectSettings>
+ <compositeConfiguration>
+ <compositeBuild compositeDefinitionSource="SCRIPT" />
+ </compositeConfiguration>
+ <option name="distributionType" value="DEFAULT_WRAPPED" />
+ <option name="externalProjectPath" value="$PROJECT_DIR$" />
+ <option name="resolveModulePerSourceSet" value="false" />
+ <option name="testRunner" value="PLATFORM" />
+ </GradleProjectSettings>
+ </option>
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="NullableNotNullManager">
+ <option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
+ <option name="myDefaultNotNull" value="androidx.annotation.NonNull" />
+ <option name="myNullables">
+ <value>
+ <list size="12">
+ <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+ <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+ <item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
+ <item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+ <item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+ <item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
+ <item index="6" class="java.lang.String" itemvalue="android.annotation.Nullable" />
+ <item index="7" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
+ <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
+ <item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
+ <item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
+ <item index="11" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
+ </list>
+ </value>
+ </option>
+ <option name="myNotNulls">
+ <value>
+ <list size="11">
+ <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+ <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+ <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+ <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+ <item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
+ <item index="5" class="java.lang.String" itemvalue="android.annotation.NonNull" />
+ <item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
+ <item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
+ <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
+ <item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
+ <item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
+ </list>
+ </value>
+ </option>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/build/classes" />
+ </component>
+ <component name="ProjectType">
+ <option name="id" value="Android" />
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="RunConfigurationProducerService">
+ <option name="ignoredProducers">
+ <set>
+ <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+ <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+ <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+ </set>
+ </option>
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 29
+ buildToolsVersion "29.0.2"
+ defaultConfig {
+ applicationId "com.ic.launcher"
+ minSdkVersion 19
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+ }
+
+ dataBinding {
+ enabled = true
+ }
+
+ //使用JDK1.8
+ compileOptions {
+ targetCompatibility JavaVersion.VERSION_1_8
+ sourceCompatibility JavaVersion.VERSION_1_8
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+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"
+
+ //recyclerview
+ implementation "androidx.recyclerview:recyclerview:1.1.0"
+ implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0'
+
+ //1.2.0-alpha05
+ implementation "com.google.android.material:material:1.2.0-alpha05"
+}
--- /dev/null
+# 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
--- /dev/null
+package com.ic.launcher;
+
+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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ assertEquals("com.ic.launcher", appContext.getPackageName());
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.ic.launcher">
+
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+
+ <application
+ android:name=".IcLauncherApplication"
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:supportsRtl="true"
+ android:theme="@style/AppTheme">
+
+ <activity android:name=".MainActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.HOME" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.MONKEY" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
\ No newline at end of file
--- /dev/null
+package com.ic.launcher;
+
+import android.app.Application;
+
+import com.ic.launcher.presenter.AppListPresenter;
+import com.ic.launcher.presenter.BatteryPresenter;
+import com.ic.launcher.presenter.PhoneStatePresenter;
+import com.ic.launcher.presenter.TimeDatePresenter;
+import com.ic.launcher.util.IcLog;
+
+public class IcLauncherApplication extends Application {
+
+ private PhoneStatePresenter mPhoneState;
+ private BatteryPresenter mBatteryPresenter;
+ private TimeDatePresenter timeDatePresenter;
+ private AppListPresenter appListPresenter;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ IcLog.setLogHead("IcLauncher");
+
+ mPhoneState = new PhoneStatePresenter(this);
+ mBatteryPresenter = new BatteryPresenter(this);
+ timeDatePresenter = new TimeDatePresenter(this);
+ appListPresenter = new AppListPresenter(this);
+ }
+
+ public PhoneStatePresenter getPhoneStatePresenter() {
+ return mPhoneState;
+ }
+ public BatteryPresenter getBatterPresenter() {
+ return mBatteryPresenter;
+ }
+ public TimeDatePresenter getTimeDatePresenter() {
+ return timeDatePresenter;
+ }
+ public AppListPresenter getAppListPresenter() {
+ return appListPresenter;
+ }
+}
--- /dev/null
+package com.ic.launcher;
+
+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.launcher.fragment.AppListFragment;
+import com.ic.launcher.fragment.L02MainFragment;
+import com.ic.launcher.listener.IChangeMainFragmentListener;
+import com.ic.launcher.listener.MainClockGestureDetectorImpl;
+import com.ic.launcher.util.ServiceUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class MainActivity extends AppCompatActivity implements
+ MainClockGestureDetectorImpl.OnClockGestureFlingListener,
+ IChangeMainFragmentListener {
+
+ private FragmentManager fragmentManager;
+
+ private List<Fragment> mAddFt;
+
+ private L02MainFragment l02MainFt;
+ private AppListFragment appListFt;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ mAddFt = new ArrayList<>();
+ fragmentManager = getSupportFragmentManager();
+
+ crateFragment();
+ commitFragment(l02MainFt);
+
+ ServiceUtil.startServiceUtil(getApplicationContext(),
+ "com.ic.action.WORK_SERVICE",
+ getPackageName());
+ }
+
+ @Override
+ public void onDirection(int flag) {
+ switch (flag) {
+ case 1:
+ //左滑
+ commitFragment(appListFt);
+ break;
+ case 2:
+ //右滑
+ break;
+ }
+ }
+
+ @Override
+ public void onChangeMain() {
+ //app列表已滑动到第一个或者第二个,需要切换到主main
+ commitFragment(l02MainFt);
+ }
+
+ private void crateFragment() {
+ l02MainFt = L02MainFragment.newInstance();
+ appListFt = AppListFragment.newInstance();
+ }
+
+ private void commitFragment(Fragment fragment) {
+ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+
+ for (int i = 0; i < mAddFt.size(); i++) {
+ fragmentTransaction.hide(mAddFt.get(i));
+ }
+
+ if (fragment.isAdded()) {
+ fragmentTransaction.show(fragment);
+ } else {
+ mAddFt.add(fragment);
+ fragmentTransaction.add(R.id.main_content_fl, fragment);
+ }
+
+ fragmentTransaction.commit();
+ }
+}
--- /dev/null
+package com.ic.launcher.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.ic.launcher.databinding.ItemAppLayoutBinding;
+import com.ic.launcher.entity.AppInfoEntity;
+import com.ic.launcher.listener.ICheckAppItemListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AppInfoAdapter extends RecyclerView.Adapter<AppInfoAdapter.AppHolder> {
+ private static final String TAG = "AppInfoAdapter";
+
+ private Context mContext;
+ private List<AppInfoEntity> appArray;
+ private ICheckAppItemListener mListener;
+
+ public AppInfoAdapter(Context context,ICheckAppItemListener listener) {
+ this.mContext = context;
+ appArray = new ArrayList<>();
+ this.mListener = listener;
+ }
+
+ public void updateAppInfoList(List<AppInfoEntity> list){
+ appArray.clear();
+ appArray.addAll(list);
+ notifyDataSetChanged();
+ }
+
+ @NonNull
+ @Override
+ public AppHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new AppHolder(ItemAppLayoutBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull AppHolder holder, int position) {
+ holder.bindAppInfo(mContext, appArray.get(position),mListener,position);
+ }
+
+ @Override
+ public int getItemCount() {
+ return appArray.size();
+ }
+
+ static class AppHolder extends RecyclerView.ViewHolder {
+ private ItemAppLayoutBinding binding = null;
+
+ public AppHolder(@NonNull ItemAppLayoutBinding itemView) {
+ super(itemView.getRoot());
+ binding = itemView;
+ }
+
+
+ public void bindAppInfo(Context context, AppInfoEntity entity, ICheckAppItemListener listener,int pos) {
+ if (binding == null || entity == null) {
+ return;
+ }
+ binding.setClick(listener);
+ binding.setPos(pos);
+ binding.appIconIv.setImageResource(entity.getAppIconResId());
+ binding.setAppTitle(context.getString(entity.getAppTitleResId()));
+ binding.executePendingBindings();
+ }
+ }
+}
--- /dev/null
+package com.ic.launcher.configure.l02;
+
+import android.graphics.Color;
+
+import com.ic.launcher.R;
+import com.ic.launcher.entity.AppInfoEntity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class L02AppInfo {
+
+ private static final int BACK_COLOUR = Color.parseColor("#000000");
+
+ public static final List<AppInfoEntity> mL02DefaultAppList = new ArrayList<AppInfoEntity>() {
+ {
+ //联系人
+ add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_contacts_l02, R.string.app_name_contacts,
+ "com.enqualcomm.imessage", "com.enqualcomm.imessage.ui.PhoneDirectoryActivity"));
+ //拨号
+ add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_dialer_l02, R.string.app_name_dialer,
+ "com.ic.dial", "com.ic.dial.MainActivity"));
+ //运动
+ add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_pedometer_l02, R.string.app_name_motion,
+ "com.ic.hardware", "com.ic.hardware.PedometerActivity"));
+ //微聊
+ add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_talk_l02, R.string.app_name_talk,
+ "", ""));
+ //天气
+ add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_weather_l02, R.string.app_name_weather,
+ "com.ic.hardware", "com.ic.hardware.WeatherActivity"));
+ //心率
+ add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_heartrate_l02, R.string.app_name_heart,
+ "com.ic.hardware", "com.ic.hardware.BloodActivity"));
+ //支付包
+ add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_alipay_l02, R.string.app_name_alipay,
+ "com.eg.android.AlipayGphone", "com.alipay.watch.ui.MainActivity"));
+ //相机
+ add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_camera_l02, R.string.app_name_camera,
+ "com.eqc.camera", "com.eqc.camera.TakePictureActivity"));
+ //相册
+ add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_albumn_l02, R.string.app_name_album,
+ "com.eqc.gallery", "com.eqc.gallery.ui.LocalAlbumDetail"));
+ //短信
+ add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_sms_l02, R.string.app_name_short_message,
+ "com.zmapp.sms", "com.zmapp.sms.MainActivity"));
+ //设置
+ add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_settings_l02, R.string.app_name_setting,
+ "com.eqc.settings", "com.eqc.settings.MainActivity"));
+ }
+ };
+}
--- /dev/null
+package com.ic.launcher.configure.l02;
+
+import com.ic.launcher.R;
+
+public class L02Icon {
+
+ //L02 信号图片
+ public static int[] l02SignalResId = new int[]{
+ R.mipmap.l02_signal_nosim,
+ R.drawable.ic_sim_locking,
+ R.mipmap.l02_signal_x,
+ R.mipmap.l02_signal_1,
+ R.mipmap.l02_signal_2,
+ R.mipmap.l02_signal_3,
+ R.mipmap.l02_signal_4
+ };
+
+ //L02 信号图片
+ public static int[] l02PhoneTypeResId = new int[]{
+ R.mipmap.l02_phone_type_4g
+ };
+
+ //L02 信号图片
+ public static int[] l02TransportResId = new int[]{
+ R.mipmap.l02_data_transport_0,
+ R.mipmap.l02_data_transport_1,
+ R.mipmap.l02_data_transport_2,
+ R.mipmap.l02_data_transport_3
+ };
+
+ //L02 信号图片
+ public static int[] l02BatteryResId = new int[]{
+ R.mipmap.l02_battery_0,
+ R.mipmap.l02_battery_1,
+ R.mipmap.l02_battery_2,
+ R.mipmap.l02_battery_3,
+ R.mipmap.l02_battery_4,
+ R.mipmap.l02_battery_5
+ };
+
+ public static int[] l02TimeHourImage = new int[]{
+ R.mipmap.clockl02_hour_0,
+ R.mipmap.clockl02_hour_1,
+ R.mipmap.clockl02_hour_2,
+ R.mipmap.clockl02_hour_3,
+ R.mipmap.clockl02_hour_4,
+ R.mipmap.clockl02_hour_5,
+ R.mipmap.clockl02_hour_6,
+ R.mipmap.clockl02_hour_7,
+ R.mipmap.clockl02_hour_8,
+ R.mipmap.clockl02_hour_9
+ };
+
+ public static int[] l02TimeMinutesImage = new int[]{
+ R.mipmap.clockl02_minutes_0,
+ R.mipmap.clockl02_minutes_1,
+ R.mipmap.clockl02_minutes_2,
+ R.mipmap.clockl02_minutes_3,
+ R.mipmap.clockl02_minutes_4,
+ R.mipmap.clockl02_minutes_5,
+ R.mipmap.clockl02_minutes_6,
+ R.mipmap.clockl02_minutes_7,
+ R.mipmap.clockl02_minutes_8,
+ R.mipmap.clockl02_minutes_9
+ };
+}
--- /dev/null
+package com.ic.launcher.entity;
+
+public class AppInfoEntity {
+ private int bgColor;
+ private int appIconResId;
+ private int appTitleResId;
+ private String packageName;
+ private String activityName;
+
+ public AppInfoEntity() {
+ this.appIconResId = 0;
+ this.appTitleResId = 0;
+ this.packageName = null;
+ this.activityName = null;
+ }
+
+ public AppInfoEntity(int bgColor,int resid, int titleResId, String pckName, String activityName) {
+ this.bgColor =bgColor;
+ this.appIconResId = resid;
+ this.appTitleResId = titleResId;
+ this.packageName = pckName;
+ this.activityName = activityName;
+ }
+
+ public int getAppIconResId() {
+ return appIconResId;
+ }
+
+ public void setAppIconResId(int appIconResId) {
+ this.appIconResId = appIconResId;
+ }
+
+ public String getPackageName() {
+ return packageName;
+ }
+
+ public void setPackageName(String packageName) {
+ this.packageName = packageName;
+ }
+
+ public String getActivityName() {
+ return activityName;
+ }
+
+ public void setActivityName(String activityName) {
+ this.activityName = activityName;
+ }
+
+ public int getBgColor() {
+ return bgColor;
+ }
+
+ public void setBgColor(int bgColor) {
+ this.bgColor = bgColor;
+ }
+
+ public int getAppTitleResId() {
+ return appTitleResId;
+ }
+
+ public void setAppTitleResId(int appTitleResId) {
+ this.appTitleResId = appTitleResId;
+ }
+}
--- /dev/null
+package com.ic.launcher.fragment;
+
+
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.LinearSmoothScroller;
+import androidx.recyclerview.widget.PagerSnapHelper;
+import androidx.recyclerview.widget.RecyclerView;
+
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.ic.launcher.IcLauncherApplication;
+import com.ic.launcher.R;
+import com.ic.launcher.adapter.AppInfoAdapter;
+import com.ic.launcher.entity.AppInfoEntity;
+import com.ic.launcher.listener.IChangeMainFragmentListener;
+import com.ic.launcher.listener.ICheckAppItemListener;
+import com.ic.launcher.mode.AppListModel;
+import com.ic.launcher.util.IcLog;
+
+import static android.widget.AbsListView.OnScrollListener.SCROLL_STATE_IDLE;
+
+
+public class AppListFragment extends Fragment {
+ private static final String TAG = "AppListFragment";
+
+ private Context mContext;
+ private RecyclerView mAppRv;
+
+ private IcLauncherApplication mApp;
+
+ private TopSmoothScroller mScroller;
+ private LinearLayoutManager mLayoutManager;
+ private IChangeMainFragmentListener changeMainFragmentListener;
+ private AppInfoAdapter appAdapter;
+
+ private AppListModel appListModel;
+
+ @Override
+ public void onAttach(@NonNull Context context) {
+ super.onAttach(context);
+ this.mContext = context;
+
+ if (context instanceof IChangeMainFragmentListener) {
+ changeMainFragmentListener = (IChangeMainFragmentListener) context;
+ } else {
+ throw new RuntimeException(context.toString()
+ + " must implement MainClockGestureDetectorImpl.OnClockGestureFlingListener");
+ }
+ }
+
+ public static AppListFragment newInstance() {
+ return new AppListFragment();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mApp = (IcLauncherApplication) mContext.getApplicationContext();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.fragment_app_list, container, false);
+ mAppRv = view.findViewById(R.id.app_list);
+ initRecyclerView();
+ initAppListModel();
+ return view;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mScroller.setTargetPosition(0);
+ mLayoutManager.startSmoothScroll(mScroller);
+ }
+
+ private void initRecyclerView(){
+ appAdapter = new AppInfoAdapter(mContext,itemListener);
+ mLayoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false);
+
+ mAppRv.setLayoutManager(mLayoutManager);
+ mAppRv.setAdapter(appAdapter);
+
+ new PagerSnapHelper().attachToRecyclerView(mAppRv);
+
+ mAppRv.addOnScrollListener(scrollListener);
+
+ mScroller = new TopSmoothScroller(mContext);
+ }
+
+ private void initAppListModel() {
+
+ AppListModel.Factory factory = new AppListModel.Factory(mApp,mApp.getAppListPresenter());
+ appListModel = new ViewModelProvider(this, factory).get(AppListModel.class);
+
+ appListModel.getObsAppInfoList().observe(getViewLifecycleOwner(), appList -> {
+ appAdapter.updateAppInfoList(appList);
+ });
+
+ appListModel.updateAppInfoList();
+ }
+
+ private RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {
+
+ private boolean isAllowLeft = false;
+ private boolean isAllowRight = false;
+
+ @Override
+ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
+ super.onScrollStateChanged(recyclerView, newState);
+ if (newState == SCROLL_STATE_IDLE) {
+ if (!isAllowLeft || !isAllowRight) {
+ //此处返回主界面
+ IcLog.i(TAG, "Change To Main Fragment");
+ changeMainFragmentListener.onChangeMain();
+ }
+ }
+ }
+
+ @Override
+ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+ super.onScrolled(recyclerView, dx, dy);
+ isAllowLeft = mAppRv.canScrollHorizontally(-1);
+ isAllowRight = mAppRv.canScrollHorizontally(1);
+ }
+ };
+
+ private class TopSmoothScroller extends LinearSmoothScroller{
+ public TopSmoothScroller(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected int getHorizontalSnapPreference() {
+ return SNAP_TO_START;//具体见源码注释
+ }
+ }
+
+ private ICheckAppItemListener itemListener = new ICheckAppItemListener() {
+ @Override
+ public void onAppItem(int pos) {
+ appListModel.onStartAppActivity(pos);
+ }
+ };
+}
--- /dev/null
+package com.ic.launcher.fragment;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.core.view.GestureDetectorCompat;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentTransaction;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.ic.launcher.R;
+import com.ic.launcher.fragment.l02.L02WatchFragment;
+import com.ic.launcher.fragment.l02.L02StatusBarFragment;
+import com.ic.launcher.listener.MainClockGestureDetectorImpl;
+
+
+public class L02MainFragment extends Fragment {
+
+ private Context mContext;
+
+ private L02StatusBarFragment statusBarFt;
+ private L02WatchFragment watchFt;
+
+ private GestureDetectorCompat gesture;
+
+ private MainClockGestureDetectorImpl.OnClockGestureFlingListener flingListener;
+
+ public static L02MainFragment newInstance() {
+ return new L02MainFragment();
+ }
+
+ @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_l02_main, container, false);
+ statusBarFt = (L02StatusBarFragment) getChildFragmentManager().findFragmentById(R.id.l02_status_fl);
+ watchFt = (L02WatchFragment) getChildFragmentManager().findFragmentById(R.id.l02_watch_fl);
+ //监听事件
+ initOnTouchListener(view);
+ return view;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ controlStatusBar(true);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ controlStatusBar(false);
+ }
+
+ @Override
+ public void onAttach(@NonNull Context context) {
+ super.onAttach(context);
+ this.mContext = context;
+ if (context instanceof MainClockGestureDetectorImpl.OnClockGestureFlingListener) {
+ flingListener = (MainClockGestureDetectorImpl.OnClockGestureFlingListener) context;
+ } else {
+ throw new RuntimeException(context.toString()
+ + " must implement MainClockGestureDetectorImpl.OnClockGestureFlingListener");
+ }
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ }
+
+
+ /**
+ * 状态显示与隐藏
+ *
+ * @param isShow true 显示 false 隐藏 在 onResume 与 onPause 控制
+ */
+ private void controlStatusBar(boolean isShow) {
+ FragmentTransaction ft = getChildFragmentManager().beginTransaction();
+ if (isShow && !statusBarFt.isVisible()) {
+ ft.show(statusBarFt).commit();
+ } else {
+ ft.hide(statusBarFt).commit();
+ }
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ private void initOnTouchListener(View view) {
+ gesture = new GestureDetectorCompat(mContext,new MainClockGestureDetectorImpl(flingListener));
+ view.setOnTouchListener((v, event) -> {
+ if (gesture.onTouchEvent(event)) {
+ return true;
+ }
+ return true;
+ });
+ }
+}
--- /dev/null
+package com.ic.launcher.fragment.l02;
+
+
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.ic.launcher.IcLauncherApplication;
+import com.ic.launcher.databinding.FragmentL02StatusBarBinding;
+import com.ic.launcher.mode.StateBarModel;
+
+
+public class L02StatusBarFragment extends Fragment {
+ private static final String TAG = "L02StatusBarFt";
+
+ private Context mContext;
+ private IcLauncherApplication mApp;
+ private FragmentL02StatusBarBinding mStateBarBinding;
+
+ private StateBarModel phoneModel;
+
+ @Override
+ public void onAttach(@NonNull Context context) {
+ super.onAttach(context);
+ mContext = context;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mApp = (IcLauncherApplication) mContext.getApplicationContext();
+ }
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ mStateBarBinding = FragmentL02StatusBarBinding.inflate(inflater, container, false);
+ initStateBarModel();
+ return mStateBarBinding.getRoot();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ phoneModel.onResumeView();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ phoneModel.onPauseView();
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ phoneModel.onDestroyView();
+ }
+
+ private void initStateBarModel() {
+
+ StateBarModel.Factory factory = new StateBarModel.Factory(mApp, mApp.getPhoneStatePresenter(), mApp.getBatterPresenter());
+ phoneModel = new ViewModelProvider(this, factory).get(StateBarModel.class);
+ phoneModel.getObsPhoneSignalID().observe(getViewLifecycleOwner(), resID -> {
+ mStateBarBinding.setPhoneSignal(resID);
+ });
+
+ phoneModel.getObsPhoneTransportID().observe(getViewLifecycleOwner(), resID -> {
+ mStateBarBinding.setPhoneTransport(resID);
+ });
+
+ phoneModel.getObsPhoneTypeID().observe(getViewLifecycleOwner(), resID -> {
+ mStateBarBinding.setPhoneNetType(resID);
+ });
+
+ phoneModel.getObsBatteryCharging().observe(getViewLifecycleOwner(), charging -> {
+ mStateBarBinding.setBatteryCharge(charging);
+ });
+
+ phoneModel.getObsBatteryResID().observe(getViewLifecycleOwner(),resID ->{
+ mStateBarBinding.setBatteryDrawable(resID);
+ });
+
+ phoneModel.getObsBatteryValue().observe(getViewLifecycleOwner(),value ->{
+ mStateBarBinding.setBatteryValue(value);
+ });
+
+ phoneModel.querySimCardState();
+ }
+}
--- /dev/null
+package com.ic.launcher.fragment.l02;
+
+
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.ic.launcher.IcLauncherApplication;
+import com.ic.launcher.databinding.FragmentL02WatchBinding;
+import com.ic.launcher.mode.WatchFaceModel;
+
+public class L02WatchFragment extends Fragment {
+
+ private Context mContext;
+ private IcLauncherApplication mApp;
+
+ private WatchFaceModel watchFaceModel;
+
+ private FragmentL02WatchBinding watchBinding;
+
+ @Override
+ public void onAttach(@NonNull Context context) {
+ super.onAttach(context);
+ mContext = context;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mApp = (IcLauncherApplication) mContext.getApplicationContext();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ watchBinding = FragmentL02WatchBinding.inflate(inflater, container, false);
+ initWatchFaceModel();
+
+ watchBinding.setHeartValue("100");
+ watchBinding.setStepValue("100000");
+ return watchBinding.getRoot();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ watchFaceModel.onResumeView();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ watchFaceModel.onPauseView();
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ watchFaceModel.onDestroyView();
+ }
+
+ private void initWatchFaceModel() {
+ WatchFaceModel.Factory factory = new WatchFaceModel.Factory(mApp, mApp.getTimeDatePresenter());
+ watchFaceModel = new ViewModelProvider(this, factory).get(WatchFaceModel.class);
+
+ watchFaceModel.getObsTime().observe(getViewLifecycleOwner(), timeList -> {
+ watchBinding.setTimeText(timeList);
+ });
+
+ watchFaceModel.getObsWeek().observe(getViewLifecycleOwner(), week -> {
+ watchBinding.setWatchWeek(week);
+ });
+
+ watchFaceModel.getObsYear().observe(getViewLifecycleOwner(), year -> {
+ watchBinding.setWatchDate(year);
+ });
+ }
+}
--- /dev/null
+package com.ic.launcher.listener;
+
+public interface IChangeMainFragmentListener {
+ void onChangeMain();
+}
--- /dev/null
+package com.ic.launcher.listener;
+
+public interface ICheckAppItemListener {
+ void onAppItem(int pos);
+}
--- /dev/null
+package com.ic.launcher.listener;
+
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+
+import com.ic.launcher.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);
+ }
+ }
+}
--- /dev/null
+package com.ic.launcher.mode;
+
+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.launcher.entity.AppInfoEntity;
+import com.ic.launcher.presenter.AppListPresenter;
+
+import java.util.List;
+
+
+public class AppListModel extends AndroidViewModel {
+
+ private final AppListPresenter appListPresenter;
+
+ private final LiveData<List<AppInfoEntity>> mObsAppInfoList;
+
+ public AppListModel(@NonNull Application application,
+ @NonNull AppListPresenter appListPresenter) {
+ super(application);
+ this.appListPresenter = appListPresenter;
+ mObsAppInfoList = appListPresenter.getObsAppInfoList();
+ }
+
+ public LiveData<List<AppInfoEntity>> getObsAppInfoList() {
+ return mObsAppInfoList;
+ }
+
+ public void updateAppInfoList() {
+ appListPresenter.updateSystemApp();
+ }
+
+ public void onStartAppActivity(int pos) {
+ appListPresenter.startAppActivity(pos);
+ }
+
+ public static class Factory extends ViewModelProvider.NewInstanceFactory {
+
+ @NonNull
+ private final Application mApplication;
+
+ @NonNull
+ private final AppListPresenter appListPresenter;
+
+
+ public Factory(@NonNull Application application,
+ @NonNull AppListPresenter appListPresenter) {
+ mApplication = application;
+ this.appListPresenter = appListPresenter;
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ @NonNull
+ public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
+ return (T) new AppListModel(mApplication, appListPresenter);
+ }
+ }
+}
--- /dev/null
+package com.ic.launcher.mode;
+
+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.launcher.presenter.BatteryPresenter;
+import com.ic.launcher.presenter.PhoneStatePresenter;
+
+public class StateBarModel extends AndroidViewModel {
+
+ private final LiveData<Integer> mObsPhoneTypeID;
+ private final LiveData<Integer> mObsPhoneSignalID;
+ private final LiveData<Integer> mObsPhoneTransportID;
+
+ private final LiveData<String> mObsBatteryValue;
+ private final LiveData<Boolean> mObsBatteryCharging;
+ private final LiveData<Integer> mObsBatteryResID;
+
+ private PhoneStatePresenter mPhonePresenter;
+ private BatteryPresenter mBatteryPresenter;
+
+ public StateBarModel(@NonNull Application application,
+ @NonNull PhoneStatePresenter phonePresenter,
+ @NonNull BatteryPresenter batteryPresenter) {
+ super(application);
+ mPhonePresenter = phonePresenter;
+ mBatteryPresenter = batteryPresenter;
+
+ mObsPhoneSignalID = mPhonePresenter.getPhoneSignalObservable();
+ mObsPhoneTypeID = mPhonePresenter.getPhoneTypeObservable();
+ mObsPhoneTransportID = mPhonePresenter.getPhoneTransportObservable();
+
+ mObsBatteryCharging = mBatteryPresenter.getObsBatteryCharging();
+ mObsBatteryResID = mBatteryPresenter.getObsBatteryResID();
+ mObsBatteryValue = mBatteryPresenter.getObsBatteryValue();
+ }
+
+ public LiveData<Integer> getObsPhoneTypeID() {
+ return mObsPhoneTypeID;
+ }
+
+ public LiveData<Integer> getObsPhoneSignalID() {
+ return mObsPhoneSignalID;
+ }
+
+ public LiveData<Integer> getObsPhoneTransportID() {
+ return mObsPhoneTransportID;
+ }
+
+ public LiveData<String> getObsBatteryValue() {
+ return mObsBatteryValue;
+ }
+
+ public LiveData<Boolean> getObsBatteryCharging() {
+ return mObsBatteryCharging;
+ }
+
+ public LiveData<Integer> getObsBatteryResID() {
+ return mObsBatteryResID;
+ }
+
+ public void querySimCardState(){
+ mPhonePresenter.querySimCardState();
+ }
+
+ public void onResumeView(){
+ mPhonePresenter.onResumePresenter();
+ mBatteryPresenter.registerBatteryReceiver();
+ }
+
+ public void onPauseView(){
+ mPhonePresenter.onPausePresenter();
+ mBatteryPresenter.unRegisterBatteryReceiver();
+ }
+
+ public void onDestroyView(){
+ mPhonePresenter.onDestroyPresenter();
+ }
+
+ public static class Factory extends ViewModelProvider.NewInstanceFactory {
+
+ @NonNull
+ private final Application mApplication;
+
+ @NonNull
+ private final PhoneStatePresenter phonePresenter;
+
+ @NonNull
+ private final BatteryPresenter batteryPresenter;
+
+ public Factory(@NonNull Application application,
+ @NonNull PhoneStatePresenter phonePresenter,
+ @NonNull BatteryPresenter batteryPresenter) {
+ mApplication = application;
+ this.phonePresenter = phonePresenter;
+ this.batteryPresenter = batteryPresenter;
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ @NonNull
+ public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
+ return (T) new StateBarModel(mApplication, phonePresenter,batteryPresenter);
+ }
+ }
+
+}
--- /dev/null
+package com.ic.launcher.mode;
+
+import android.app.Application;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MediatorLiveData;
+import androidx.lifecycle.ViewModel;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.ic.launcher.presenter.TimeDatePresenter;
+
+import java.util.ArrayList;
+
+
+public class WatchFaceModel extends AndroidViewModel {
+
+ private TimeDatePresenter timeDatePresenter;
+
+ private final LiveData<ArrayList<Integer>> mObsTime;
+ private final LiveData<String> mObsYear;
+ private final LiveData<String> mObsWeek;
+
+
+ public WatchFaceModel(@NonNull Application application,
+ @NonNull TimeDatePresenter timeDatePresenter) {
+ super(application);
+ this.timeDatePresenter = timeDatePresenter;
+ mObsTime = timeDatePresenter.getObsTime();
+ mObsYear = timeDatePresenter.getObsYear();
+ mObsWeek = timeDatePresenter.getmObsWeek();
+ }
+
+ public LiveData<ArrayList<Integer>> getObsTime() {
+ return mObsTime;
+ }
+
+ public LiveData<String> getObsYear() {
+ return mObsYear;
+ }
+
+ public LiveData<String> getObsWeek() {
+ return mObsWeek;
+ }
+
+ public void onResumeView() {
+ timeDatePresenter.onResumePresenter();
+ }
+
+ public void onPauseView() {
+ timeDatePresenter.onPausePresenter();
+ }
+
+ public void onDestroyView() {
+ timeDatePresenter.unRegisterTimeDateReceiver();
+ }
+
+ public static class Factory extends ViewModelProvider.NewInstanceFactory {
+
+ @NonNull
+ private final Application mApplication;
+
+ @NonNull
+ private final TimeDatePresenter timeDatePresenter;
+
+
+ public Factory(@NonNull Application application,
+ @NonNull TimeDatePresenter timeDatePresenter) {
+ mApplication = application;
+ this.timeDatePresenter = timeDatePresenter;
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ @NonNull
+ public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
+ return (T) new WatchFaceModel(mApplication, timeDatePresenter);
+ }
+ }
+}
--- /dev/null
+package com.ic.launcher.presenter;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+
+import androidx.lifecycle.MutableLiveData;
+
+import com.ic.launcher.R;
+import com.ic.launcher.configure.l02.L02AppInfo;
+import com.ic.launcher.entity.AppInfoEntity;
+
+import java.util.List;
+
+public class AppListPresenter {
+
+ private Context context;
+ private MutableLiveData<List<AppInfoEntity>> mObsAppInfoList;
+ private MutableLiveData<String> mObsActivityError;
+
+ private String mErrorInfo;
+
+ public AppListPresenter(Context context){
+ this.context=context;
+ mObsAppInfoList = new MutableLiveData<>();
+ mObsActivityError = new MutableLiveData<>();
+
+ mErrorInfo = context.getString(R.string.error_start_activity);
+ }
+
+ public MutableLiveData<List<AppInfoEntity>> getObsAppInfoList() {
+ return mObsAppInfoList;
+ }
+
+ public MutableLiveData<String> getObsActivityError() {
+ return mObsActivityError;
+ }
+
+ public void updateSystemApp(){
+ mObsAppInfoList.setValue(L02AppInfo.mL02DefaultAppList);
+ }
+
+ public void startAppActivity(int index){
+ if(index <0 || index > L02AppInfo.mL02DefaultAppList.size()){
+ mObsActivityError.setValue(mErrorInfo);
+ return;
+ }
+
+ AppInfoEntity entity = L02AppInfo.mL02DefaultAppList.get(index);
+ String pck = entity.getPackageName();
+ String activity = entity.getActivityName();
+
+ if(TextUtils.isEmpty(pck) || TextUtils.isEmpty(activity)){
+ mObsActivityError.setValue(mErrorInfo);
+ return;
+ }
+
+ try {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setComponent(new ComponentName(pck, activity));
+ context.startActivity(intent);
+ } catch (Exception e ) {
+ mObsActivityError.setValue(mErrorInfo);
+ }
+ }
+}
--- /dev/null
+package com.ic.launcher.presenter;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.text.TextUtils;
+
+import androidx.lifecycle.MediatorLiveData;
+
+import com.ic.launcher.configure.l02.L02Icon;
+
+public class BatteryPresenter {
+
+ private Context mContext;
+
+ private MediatorLiveData<String> mObsBatteryValue;
+ private MediatorLiveData<Boolean> mObsBatteryCharging;
+ private MediatorLiveData<Integer> mObsBatteryResID;
+
+ public MediatorLiveData<String> getObsBatteryValue() {
+ return mObsBatteryValue;
+ }
+
+ public MediatorLiveData<Boolean> getObsBatteryCharging() {
+ return mObsBatteryCharging;
+ }
+
+ public MediatorLiveData<Integer> getObsBatteryResID() {
+ return mObsBatteryResID;
+ }
+
+ public BatteryPresenter(Context context) {
+ mContext = context;
+
+ mObsBatteryValue = new MediatorLiveData<>();
+ mObsBatteryCharging = new MediatorLiveData<>();
+ mObsBatteryResID = new MediatorLiveData<>();
+ }
+
+ public void registerBatteryReceiver() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ mContext.registerReceiver(mIntentReceiver, filter);
+ }
+
+ public void unRegisterBatteryReceiver() {
+ mContext.unregisterReceiver(mIntentReceiver);
+ }
+
+ private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent != null) {
+ String acyion = intent.getAction();
+
+ if (TextUtils.isEmpty(acyion)) {
+ return;
+ }
+
+ if (Intent.ACTION_BATTERY_CHANGED.equals(acyion)) {
+ int status = intent.getIntExtra("status", -1);
+ int rawlevel = intent.getIntExtra("level", -1);
+ int scale = intent.getIntExtra("scale", -1);
+ updateBatteryValue(rawlevel, scale);
+ updateBatteryCharging(status);
+ }
+ }
+ }
+ };
+
+ private void updateBatteryValue(int rawlevel, int scale) {
+ int level = -1; // percentage, or -1 for unknown
+ if (rawlevel >= 0 && scale > 0) {
+ level = (rawlevel * 100) / scale;
+ }
+ mObsBatteryResID.setValue(L02Icon.l02BatteryResId[getBatteryLevel(level)]);
+ mObsBatteryValue.setValue(level + "%");
+ }
+
+ private void updateBatteryCharging(int state) {
+ if (BatteryManager.BATTERY_STATUS_CHARGING == state) {
+ mObsBatteryCharging.setValue(true);
+ }else {
+ mObsBatteryCharging.setValue(false);
+ }
+ }
+
+ private int getBatteryLevel(int level) {
+ int index = 0;
+ if (level > 85) {
+ index = 5;
+ } else if (level > 65) {
+ index = 4;
+ } else if (level > 40) {
+ index = 3;
+ } else if (level > 15) {
+ index = 2;
+ } else if (level > 7) {
+ index = 1;
+ }
+
+ return index;
+ }
+}
--- /dev/null
+package com.ic.launcher.presenter;
+
+import android.content.Context;
+import android.telephony.PhoneStateListener;
+import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
+
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MediatorLiveData;
+
+import com.ic.launcher.util.IcLog;
+
+
+import static com.ic.launcher.configure.l02.L02Icon.l02PhoneTypeResId;
+import static com.ic.launcher.configure.l02.L02Icon.l02SignalResId;
+
+public class PhoneStatePresenter {
+ private static final String TAG = "PhoneStatePresenter";
+
+ private MediatorLiveData<Integer> mObsPhoneTypeID;
+ private MediatorLiveData<Integer> mObsPhoneSignalID;
+ private MediatorLiveData<Integer> mObsPhoneTransportID;
+
+ private QueryTrafficPooler trafficPooler;
+
+ private TelephonyManager mTM;
+
+ private Thread mThread;
+
+ private boolean isSimCard = false;
+
+ public PhoneStatePresenter(Context context) {
+ mTM = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ mObsPhoneTypeID = new MediatorLiveData<>();
+ mObsPhoneSignalID = new MediatorLiveData<>();
+ mObsPhoneTransportID = new MediatorLiveData<>();
+
+ trafficPooler = new QueryTrafficPooler(mObsPhoneTransportID);
+ }
+
+ public LiveData<Integer> getPhoneTypeObservable() {
+ return mObsPhoneTypeID;
+ }
+
+ public LiveData<Integer> getPhoneSignalObservable() {
+ return mObsPhoneSignalID;
+ }
+
+ public LiveData<Integer> getPhoneTransportObservable() {
+ return mObsPhoneTransportID;
+ }
+
+ public void querySimCardState() {
+ int resIdIndex = 0;
+ if (mTM == null) {
+ return;
+ }
+
+ int simState = mTM.getSimState();
+ switch (simState) {
+ case TelephonyManager.SIM_STATE_READY:
+ resIdIndex = 2;
+ break;
+ case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
+ case TelephonyManager.SIM_STATE_PUK_REQUIRED:
+ case TelephonyManager.SIM_STATE_PIN_REQUIRED:
+ resIdIndex = 1;
+ break;
+ }
+
+ if (resIdIndex == 2) {
+ mObsPhoneTypeID.setValue(queryPhoneNetworkTypeResId(mTM));
+ mObsPhoneSignalID.setValue(l02SignalResId[6]);
+ startQueryTraffic();
+ isSimCard = true;
+ } else if (resIdIndex == 1) {
+ mObsPhoneSignalID.setValue(l02SignalResId[1]);
+ } else {
+ mObsPhoneSignalID.setValue(l02SignalResId[0]);
+ }
+ }
+
+ public void onResumePresenter() {
+ if (isSimCard) {
+ resumeQueryTraffic();
+ listenPhoneState();
+ }
+ }
+
+ public void onPausePresenter() {
+ pauseQueryTraffic();
+ stopListenPhoneState();
+ }
+
+ public void onDestroyPresenter() {
+ stopQueryTraffic();
+ mTM=null;
+ }
+
+ private void startQueryTraffic() {
+ mThread = new Thread(trafficPooler);
+ mThread.start();
+ }
+
+ private void stopQueryTraffic() {
+ if (mThread != null) {
+ mThread.interrupt();
+ }
+
+ mThread = null;
+ }
+
+ public void resumeQueryTraffic() {
+ if (mThread != null && trafficPooler != null) {
+ trafficPooler.resumeQueryThread();
+ }
+ }
+
+ public void pauseQueryTraffic() {
+ if (mThread != null && trafficPooler != null) {
+ trafficPooler.pauseQueryThread();
+ }
+ }
+
+ private void listenPhoneState() {
+ if (mTM != null) {
+ mTM.listen(mPhoneListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
+ }
+ }
+
+ private void stopListenPhoneState() {
+ if (mTM != null) {
+ mTM.listen(mPhoneListener, PhoneStateListener.LISTEN_NONE);
+ }
+ }
+
+ private PhoneStateListener mPhoneListener = new PhoneStateListener() {
+ private int lastSignal = 0;
+
+ @Override
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ String ssignal = signalStrength.toString();
+ String[] parts = ssignal.split(" ");
+ lastSignal = Integer.parseInt(parts[8])-140;
+ IcLog.i(TAG, "Signal:" + lastSignal);
+ mObsPhoneSignalID.postValue(l02SignalResId[checkSignalLevel(lastSignal)]);
+ super.onSignalStrengthsChanged(signalStrength);
+ }
+ };
+
+ private int queryPhoneNetworkTypeResId(TelephonyManager tm) {
+ if (tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {
+ return l02PhoneTypeResId[0];
+ }
+ return -1;
+ }
+
+ private int checkSignalLevel(int dbm){
+ int index=6;
+ if(dbm <= -120){
+ index=2;
+ }else if(dbm <= -111){
+ index =3;
+ }else if(dbm <= -106){
+ index =4;
+ }else if(dbm <= -91){
+ index=5;
+ }
+ return index;
+ }
+}
--- /dev/null
+package com.ic.launcher.presenter;
+
+import com.ic.launcher.util.IcLog;
+
+public abstract class QueryThread extends Thread {
+ private static final String TAG="QueryThread";
+
+ private final Object lock = new Object();
+ private boolean pause = false;
+
+ abstract void onThreadExecute();
+
+ protected void pauseQueryThread() {
+ pause = true;
+ }
+
+ protected void resumeQueryThread() {
+ pause = false;
+ synchronized (lock) {
+ lock.notifyAll();
+ }
+ }
+
+ private void onPause() {
+ synchronized (lock) {
+ try {
+ IcLog.i(TAG, "Pause Query Phone");
+ lock.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ while (true) {
+ while (pause) {
+ onPause();
+ }
+
+ onThreadExecute();
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ //捕获到异常之后,执行break跳出循环
+ IcLog.i(TAG, "Stop Query Phone State");
+ break;
+ }
+ }
+ }
+}
--- /dev/null
+package com.ic.launcher.presenter;
+
+import android.net.TrafficStats;
+
+import androidx.lifecycle.MediatorLiveData;
+
+import com.ic.launcher.util.IcLog;
+
+import static com.ic.launcher.configure.l02.L02Icon.l02TransportResId;
+
+public class QueryTrafficPooler extends QueryThread {
+
+ private static final String TAG = "QueryTrafficPooler";
+
+ private long receivedWork;
+ private long sendNetWork;
+
+ private MediatorLiveData<Integer> mObsPhoneTransportID;
+
+ public QueryTrafficPooler(MediatorLiveData<Integer> transportID) {
+ mObsPhoneTransportID = transportID;
+ }
+
+ @Override
+ void onThreadExecute() {
+ getTrafficPollerValue();
+ }
+
+ private void getTrafficPollerValue() {
+ long rw = TrafficStats.getMobileRxPackets();
+ long sw = TrafficStats.getMobileTxPackets();
+ int index = 0;
+ if (rw > receivedWork && sw > sendNetWork) {
+ index = 3;
+ } else {
+ if (rw > receivedWork) {
+ index = 1;
+ }
+ if (sw > sendNetWork) {
+ index = 2;
+ }
+ }
+ IcLog.i(TAG, "receivedWork:" + receivedWork + "sendNetWork:" + sendNetWork);
+ receivedWork = rw;
+ sendNetWork = sw;
+ mObsPhoneTransportID.postValue(l02TransportResId[index]);
+ }
+}
--- /dev/null
+package com.ic.launcher.presenter;
+
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.text.format.DateFormat;
+
+import androidx.lifecycle.MediatorLiveData;
+
+import com.ic.launcher.util.IcLog;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import static com.ic.launcher.configure.l02.L02Icon.l02TimeHourImage;
+import static com.ic.launcher.configure.l02.L02Icon.l02TimeMinutesImage;
+public class TimeDatePresenter {
+
+ private static final String TAG = "TimeDatePresenter";
+
+ private static final CharSequence DEFAULT_FORMAT_24_HOUR = "HH:mm";
+ private static final CharSequence DEFAULT_FORMAT_MM_DD = "MM-dd";
+ private static final CharSequence DEFAULT_FORMAT_EEEEE = "EEEE";
+
+ private MediatorLiveData<ArrayList<Integer>> mObsTime;
+ private MediatorLiveData<String> mObsYear;
+ private MediatorLiveData<String> mObsWeek;
+
+
+ private Context mContext;
+ private Calendar mTime;
+ private boolean mShouldRunTicker = false;
+
+ private ArrayList<Integer> timeList;
+
+ public TimeDatePresenter(Context context) {
+ mContext = context;
+ timeList = new ArrayList<>();
+ registerTimeDateReceiver();
+ createTime(null);
+
+ mObsTime = new MediatorLiveData<>();
+ mObsYear = new MediatorLiveData<>();
+ mObsWeek = new MediatorLiveData<>();
+ }
+
+ public MediatorLiveData<ArrayList<Integer>> getObsTime() {
+ return mObsTime;
+ }
+
+ public MediatorLiveData<String> getObsYear() {
+ return mObsYear;
+ }
+
+ public MediatorLiveData<String> getmObsWeek() {
+ return mObsWeek;
+ }
+
+ public void onResumePresenter() {
+ onTimeChanged();
+ mShouldRunTicker = true;
+ }
+
+ public void onPausePresenter() {
+ mShouldRunTicker = false;
+ }
+
+ public void registerTimeDateReceiver() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_TIME_TICK);
+ filter.addAction(Intent.ACTION_TIME_CHANGED);
+ filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+ mContext.registerReceiver(mIntentReceiver, filter);
+ }
+
+ public void unRegisterTimeDateReceiver() {
+ mContext.unregisterReceiver(mIntentReceiver);
+ }
+
+ private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
+ final String timeZone = intent.getStringExtra("time-zone");
+ createTime(timeZone);
+ } else if (!mShouldRunTicker && (Intent.ACTION_TIME_TICK.equals(intent.getAction())
+ || Intent.ACTION_TIME_CHANGED.equals(intent.getAction()))) {
+ return;
+ }
+ onTimeChanged();
+ }
+ };
+
+ private void createTime(String timeZone) {
+ if (timeZone != null) {
+ mTime = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
+ } else {
+ mTime = Calendar.getInstance();
+ }
+ }
+
+ private void onTimeChanged() {
+ mTime.setTimeInMillis(System.currentTimeMillis());
+
+ CharSequence time = DateFormat.format(DEFAULT_FORMAT_24_HOUR, mTime);
+ CharSequence mmdd = DateFormat.format(DEFAULT_FORMAT_MM_DD, mTime);
+ CharSequence week = DateFormat.format(DEFAULT_FORMAT_EEEEE, mTime);
+
+ timeList.clear();
+
+ boolean isHour=true;
+
+ for(int i=0; i<time.length(); i++){
+ if(time.charAt(i) == ':'){
+ isHour=false;
+ continue;
+ }
+
+ if(isHour){
+ timeList.add(l02TimeHourImage[Character.getNumericValue(time.charAt(i))]);
+ }else{
+ timeList.add(l02TimeMinutesImage[Character.getNumericValue(time.charAt(i))]);
+ }
+ }
+
+ mObsTime.setValue(timeList);
+ mObsYear.setValue(mmdd.toString());
+ mObsWeek.setValue(week.toString());
+
+ IcLog.i(TAG, "time" + time.toString() + " mmdd:" + mmdd.toString() + " week" + week.toString());
+ }
+}
--- /dev/null
+package com.ic.launcher.util;
+
+import android.util.Log;
+
+import com.ic.launcher.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;
+ }
+}
--- /dev/null
+package com.ic.launcher.util;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.util.DisplayMetrics;
+
+/**
+ *
+ * @author RyanLee
+ * @date 2017/11/29
+ */
+
+public class OsUtil {
+ public static int dpToPx(int dp) {
+ return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
+ }
+
+ public static int pxToDp(int px) {
+ return (int) (px / Resources.getSystem().getDisplayMetrics().density);
+ }
+
+
+ /**
+ * 获取屏幕宽度
+ *
+ * @return
+ */
+ public static int getScreenWidth() {
+ return Resources.getSystem().getDisplayMetrics().widthPixels;
+ }
+
+ /**
+ * 获取屏幕高度
+ *
+ * @return
+ */
+ public static int getScreenHeigth() {
+ return Resources.getSystem().getDisplayMetrics().heightPixels;
+ }
+
+ /**
+ * 获取屏幕宽度
+ *
+ * @return
+ */
+ public static int getScreenWidth(Activity activity) {
+ DisplayMetrics outMetrics = new DisplayMetrics();
+ activity.getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
+ return outMetrics.widthPixels;
+
+ }
+}
--- /dev/null
+package com.ic.launcher.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);
+ }
+ }
+
+ private static Intent getExplicitIntent(Context context, Intent impl) {
+ List<ResolveInfo> 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;
+ }
+}
--- /dev/null
+package com.ic.launcher.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+public class ClockWatchView extends View {
+
+ private float mRadius; //外圆半径
+
+ private int mColorLong = Color.WHITE; //长线的颜色
+ private int mColorShort = Color.WHITE; //短线的颜色
+
+ //指针末尾的长度
+ private float mPointEndLength;
+
+ private Paint mPaint;
+
+ public ClockWatchView(Context context) {
+ this(context, null);
+ }
+
+ public ClockWatchView(Context context, @Nullable AttributeSet attrs) {
+ this(context, null, 0);
+ }
+
+ public ClockWatchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ //初始化画笔
+ init();
+ }
+
+ private void init() {
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setDither(true);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ canvas.save();
+
+ //移动到中心部分
+ canvas.translate(getWidth() / 2, getHeight() / 2);
+
+ //绘制刻度
+ paintScale(canvas);
+
+ canvas.restore();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+
+ int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+
+
+ if (widthMode == MeasureSpec.AT_MOST
+ || widthMode == MeasureSpec.UNSPECIFIED
+ || heightMeasureSpec == MeasureSpec.AT_MOST
+ || heightMeasureSpec == MeasureSpec.UNSPECIFIED) {
+ //宽度高度至少有一个确定的值,不能同时为wrap_content
+ return;
+ } else { //至少有一个为确定值,要获取其中的最小值
+ if (widthMode == MeasureSpec.EXACTLY) {
+ setMeasuredDimension(widthSize, heightSize);
+ }
+ }
+ }
+
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ mRadius = (Math.min(w, h)) / 2;
+ mPointEndLength = mRadius / 6;
+ }
+
+ private void paintScale(Canvas canvas) {
+ //设置宽度
+ mPaint.setStrokeWidth(dpToPx(1));
+ int lineWidth = 0;
+ for (int i = 0; i < 60; i++) {
+ if (i % 5 == 0) { //整点
+ mPaint.setStrokeWidth(dpToPx(2f));
+ mPaint.setColor(mColorLong);
+ lineWidth = 8;
+ mPaint.setTextSize(spToPx(26));
+ String text = ((i / 5) == 0 ? 12 : (i / 5)) + "";
+ Rect textBound = new Rect();
+ mPaint.getTextBounds(text, 0, text.length(), textBound);
+ mPaint.setColor(Color.WHITE);
+ canvas.save();
+ if (i > 15 && i < 45) {
+ canvas.translate(0, -mRadius + lineWidth - dpToPx(5) + (textBound.bottom - textBound.top));
+ } else if (i == 15 || i == 45) {
+ canvas.translate(0, -mRadius + lineWidth - dpToPx(8) + (textBound.bottom - textBound.top));
+ } else {
+ canvas.translate(0, -mRadius + lineWidth + dpToPx(2) + (textBound.bottom - textBound.top));
+ }
+ canvas.rotate(-6 * i);
+ mPaint.setStyle(Paint.Style.FILL);
+ canvas.drawText(text, -(textBound.right - textBound.left) / 2, textBound.bottom+dpToPx(6) , mPaint);
+ canvas.restore();
+ } else { //非整点
+ lineWidth = 4;
+ mPaint.setColor(mColorShort);
+ mPaint.setStrokeWidth(dpToPx(0.5f));
+ }
+ canvas.drawLine(0, -mRadius, 0, -mRadius + lineWidth, mPaint);
+ canvas.rotate(6);
+ }
+ canvas.restore();
+ }
+
+ private float dpToPx(float dp) {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
+ }
+
+ private float spToPx(float sp) {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
+ }
+}
--- /dev/null
+package com.ic.launcher.widget;
+
+import android.content.Context;
+import android.graphics.drawable.AnimationDrawable;
+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.launcher.R;
+
+public class WidgetBatteryStateView extends LinearLayout {
+
+ private TextView batteryTv;
+ private ImageView batteryIv;
+
+ private AnimationDrawable animationDrawable;
+
+ public WidgetBatteryStateView(Context context) {
+ this(context, null);
+ }
+
+ public WidgetBatteryStateView(Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WidgetBatteryStateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ View view = View.inflate(context, R.layout.widget_battery_state_layout, this);
+ batteryTv = view.findViewById(R.id.battery_tv);
+ batteryIv = view.findViewById(R.id.battery_iv);
+ }
+
+ public void updateBatteryValue(String bv) {
+ batteryTv.setText(bv);
+
+ }
+
+ public void updateBatteryDrawable(int netType) {
+ batteryIv.setImageResource(netType);
+ }
+
+ public void updateBatteryChargeState(boolean charge) {
+ if (charge) {
+ if (animationDrawable == null) {
+ batteryIv.setImageResource(R.drawable.l02_battery_charging_anim);
+ animationDrawable = (AnimationDrawable) batteryIv.getDrawable();
+ animationDrawable.start();
+ }
+ } else {
+ if (animationDrawable != null) {
+ animationDrawable.stop();
+ animationDrawable = null;
+ }
+ }
+ }
+
+
+ @BindingAdapter(value = {"app:batteryValue", "app:batteryDrawable", "app:batteryCharge"}, requireAll = false)
+ public static void updateBatteryState(WidgetBatteryStateView view, String value, int imgRes, boolean charge) {
+ if (view != null) {
+ view.updateBatteryValue(value);
+ view.updateBatteryDrawable(imgRes);
+ view.updateBatteryChargeState(charge);
+ }
+ }
+}
--- /dev/null
+package com.ic.launcher.widget;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import androidx.annotation.Nullable;
+import androidx.databinding.BindingAdapter;
+
+import com.ic.launcher.R;
+
+
+public class WidgetPhoneStateView extends LinearLayout {
+
+ private ImageView signalIv;
+ private ImageView netTypeIv;
+ private ImageView transportIv;
+
+ public WidgetPhoneStateView(Context context) {
+ this(context, null);
+ }
+
+ public WidgetPhoneStateView(Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WidgetPhoneStateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+
+ View view = View.inflate(context, R.layout.widget_phone_state_layout, this);
+ signalIv = view.findViewById(R.id.signal_iv);
+ netTypeIv = view.findViewById(R.id.net_type_iv);
+ transportIv = view.findViewById(R.id.transport_iv);
+ }
+
+ public void updateSinalDrawable(int signal) {
+ signalIv.setImageResource(signal);
+ }
+
+ public void updateNetTypeDrawable(int netType) {
+ netTypeIv.setImageResource(netType);
+ }
+
+ public void updateTransportDrawable(int transport) {
+ transportIv.setImageResource(transport);
+ }
+
+
+ @BindingAdapter(value = {"app:signalDrawable", "app:netTypeDrawable", "app:transportDrawable"}, requireAll = false)
+ public static void updatePhoneState(WidgetPhoneStateView view, int signal, int netType, int transport) {
+ if (view != null) {
+ view.updateSinalDrawable(signal);
+ view.updateNetTypeDrawable(netType);
+ view.updateTransportDrawable(transport);
+ }
+ }
+}
--- /dev/null
+package com.ic.launcher.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.RelativeLayout;
+
+import androidx.databinding.BindingAdapter;
+
+import com.ic.launcher.R;
+
+import java.util.ArrayList;
+
+//TextClock
+public class WidgetTimeImageView extends RelativeLayout {
+
+ private ImageView mColon;
+ private ImageView[] mImageView = new ImageView[4];
+
+ private int[] oldTimeArray = new int[4];
+ private boolean isShowColon = false;
+
+ public WidgetTimeImageView(Context context) {
+ this(context, null);
+ }
+
+ public WidgetTimeImageView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WidgetTimeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ View view = View.inflate(context, R.layout.widget_time_image_layout, this);
+ mImageView[0] = (ImageView) view.findViewById(R.id.time_hour_ten);
+ mImageView[1] = (ImageView) view.findViewById(R.id.time_hour_bit);
+ mColon = (ImageView) view.findViewById(R.id.time_colon);
+ mImageView[2] = (ImageView) view.findViewById(R.id.time_minute_ten);
+ mImageView[3] = (ImageView) view.findViewById(R.id.time_minute_bit);
+ }
+
+ private void updateTime(ArrayList<Integer> timeRes) {
+
+ if (timeRes == null || timeRes.size() == 0 || timeRes.size() != oldTimeArray.length) {
+ return;
+ }
+
+ for (int i = 0; i < timeRes.size(); i++) {
+ if (oldTimeArray[i] != timeRes.get(i)) {
+ mImageView[i].setImageResource(timeRes.get(i));
+ oldTimeArray[i] = timeRes.get(i);
+ }
+ }
+
+ if (!isShowColon) {
+ mColon.setImageResource(R.mipmap.clockl02_time_colon);
+ isShowColon = true;
+ }
+ }
+
+ @BindingAdapter(value = {"app:timeImageResId"}, requireAll = false)
+ public static void updateTimeImge(WidgetTimeImageView view, ArrayList<Integer> timeRes) {
+ if (view != null) {
+ view.updateTime(timeRes);
+ }
+ }
+}
--- /dev/null
+package com.ic.launcher.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import androidx.databinding.BindingAdapter;
+
+import com.ic.launcher.R;
+
+import java.util.ArrayList;
+
+public class WidgetTimeTextView extends RelativeLayout {
+
+ private ImageView mColon;
+ private TextView[] mImageView = new TextView[4];
+
+ private int[] oldTimeArray = new int[]{-1,-1,-1,-1};
+ private boolean isShowColon = false;
+
+ public WidgetTimeTextView(Context context) {
+ this(context, null);
+ }
+
+ public WidgetTimeTextView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WidgetTimeTextView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ View view = View.inflate(context, R.layout.widget_time_text_layout, this);
+ mImageView[0] = (TextView) view.findViewById(R.id.time_hour_ten_tv);
+ mImageView[1] = (TextView) view.findViewById(R.id.time_hour_bit_tv);
+ mColon = (ImageView) view.findViewById(R.id.time_colon_tv);
+ mImageView[2] = (TextView) view.findViewById(R.id.time_minute_ten_tv);
+ mImageView[3] = (TextView) view.findViewById(R.id.time_minute_bit_tv);
+ }
+
+ private void updateTextTime(ArrayList<Integer> value) {
+ if (value == null || value.size() == 0 || value.size() != oldTimeArray.length) {
+ return;
+ }
+
+ for (int i = 0; i < value.size(); i++) {
+ if (oldTimeArray[i] != value.get(i)) {
+ if(i ==0 && value.get(i) ==0){
+ continue;
+ }
+ mImageView[i].setText(String.valueOf(value.get(i)));
+ oldTimeArray[i] = value.get(i);
+ }
+ }
+
+ if (!isShowColon) {
+ mColon.setImageResource(R.mipmap.clockl02_time_colon);
+ isShowColon = true;
+ }
+ }
+
+ @BindingAdapter(value = {"app:timeImageText"}, requireAll = false)
+ public static void updateTimeText(WidgetTimeTextView view, ArrayList<Integer> timeRes) {
+ if (view != null) {
+ view.updateTextTime(timeRes);
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ <path
+ android:fillType="evenOdd"
+ android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
+ android:strokeWidth="1"
+ android:strokeColor="#00000000">
+ <aapt:attr name="android:fillColor">
+ <gradient
+ android:endX="78.5885"
+ android:endY="90.9159"
+ android:startX="48.7653"
+ android:startY="61.0927"
+ android:type="linear">
+ <item
+ android:color="#44000000"
+ android:offset="0.0" />
+ <item
+ android:color="#00000000"
+ android:offset="1.0" />
+ </gradient>
+ </aapt:attr>
+ </path>
+ <path
+ android:fillColor="#FFFFFF"
+ android:fillType="nonZero"
+ android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
+ android:strokeWidth="1"
+ android:strokeColor="#00000000" />
+</vector>
--- /dev/null
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="120dp"
+ android:height="120dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
+</vector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ <path
+ android:fillColor="#008577"
+ android:pathData="M0,0h108v108h-108z" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M9,0L9,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,0L19,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M29,0L29,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M39,0L39,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M49,0L49,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M59,0L59,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M69,0L69,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M79,0L79,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M89,0L89,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M99,0L99,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,9L108,9"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,19L108,19"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,29L108,29"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,39L108,39"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,49L108,49"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,59L108,59"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,69L108,69"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,79L108,79"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,89L108,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,99L108,99"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,29L89,29"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,39L89,39"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,49L89,49"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,59L89,59"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,69L89,69"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,79L89,79"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M29,19L29,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M39,19L39,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M49,19L49,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M59,19L59,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M69,19L69,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M79,19L79,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+</vector>
--- /dev/null
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="1024"
+ android:viewportHeight="1024">
+ <path
+ android:pathData="M889.6,866.99a20.48,20.48 0,0 0,0 -29.87L186.88,134.4a20.48,20.48 0,0 0,-29.87 0l-22.61,22.61a20.48,20.48 0,0 0,0 29.87l73.81,74.24 -55.04,55.04A85.33,85.33 0,0 0,128 376.75L128,853.33a85.33,85.33 0,0 0,85.33 85.33h512a85.33,85.33 0,0 0,85.33 -75.95l27.31,26.88a20.48,20.48 0,0 0,29.87 0zM341.33,789.33a21.33,21.33 0,0 1,-21.33 21.33h-42.67a21.33,21.33 0,0 1,-21.33 -21.33v-85.33a21.33,21.33 0,0 1,21.33 -21.33h42.67a21.33,21.33 0,0 1,21.33 21.33zM341.33,576a21.33,21.33 0,0 1,-21.33 21.33h-42.67a21.33,21.33 0,0 1,-21.33 -21.33v-85.33a21.33,21.33 0,0 1,21.33 -21.33h42.67a21.33,21.33 0,0 1,21.33 21.33zM512,789.33a21.33,21.33 0,0 1,-21.33 21.33h-42.67a21.33,21.33 0,0 1,-21.33 -21.33v-42.67a21.33,21.33 0,0 1,21.33 -21.33h42.67a21.33,21.33 0,0 1,21.33 21.33zM490.67,640h-42.67a21.33,21.33 0,0 1,-21.33 -21.33v-128a19.63,19.63 0,0 1,2.13 -8.96l83.2,85.33v51.63a21.33,21.33 0,0 1,-21.33 21.33zM682.67,789.33a21.33,21.33 0,0 1,-21.33 21.33h-42.67a21.33,21.33 0,0 1,-21.33 -21.33v-85.33a21.33,21.33 0,0 1,21.33 -21.33h11.09L682.67,735.57zM810.67,652.37L810.67,170.67a85.33,85.33 0,0 0,-85.33 -85.33L419.41,85.33a85.33,85.33 0,0 0,-60.59 25.17l-42.67,44.8z"
+ android:fillColor="#d81e06"/>
+</vector>
--- /dev/null
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="32"
+ android:viewportHeight="32">
+ <path
+ android:pathData="M30,24v-2.715c0,-2.615 -1.882,-4.999 -4.484,-5.259C22.523,15.726 20,18.068 20,21v3c-1,0 -2,0.895 -2,2v4c0,1.105 0.894,2 1.999,2h10C31.103,32 32,31.105 32,30v-4C32,24.895 31,24 30,24zM26,29c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1v-2c0,-0.55 0.45,-1 1,-1s1,0.45 1,1V29zM22,24v-3c0,-1.654 1.346,-3 3,-3s3,1.346 3,3v3H22z"
+ android:fillColor="#FF0000"/>
+ <path
+ android:pathData="M0.999,32H16v-2H2V7.414L7.413,2H24v12h2V1c0,-0.263 -0.107,-0.521 -0.294,-0.707C25.52,0.107 25.262,0 24.999,0h-18C6.735,0 6.478,0.107 6.291,0.293l-5.999,6C0.106,6.479 0,6.737 0,7v24c0,0.263 0.106,0.521 0.292,0.707C0.478,31.893 0.735,32 0.999,32z"
+ android:fillColor="#FFFFFF"/>
+ <path
+ android:pathData="M12,9V7c0,-0.552 -0.448,-1 -1,-1s-1,0.448 -1,1v2c0,0.552 0.448,1 1,1S12,9.552 12,9z"
+ android:fillColor="#FFFFFF"/>
+ <path
+ android:pathData="M16,9V7c0,-0.552 -0.448,-1 -1,-1s-1,0.448 -1,1v2c0,0.552 0.448,1 1,1S16,9.552 16,9z"
+ android:fillColor="#FFFFFF"/>
+ <path
+ android:pathData="M19,10c0.552,0 1,-0.448 1,-1V7c0,-0.552 -0.448,-1 -1,-1s-1,0.448 -1,1v2C18,9.552 18.448,10 19,10z"
+ android:fillColor="#FFFFFF"/>
+ <path
+ android:pathData="M7,10c0.552,0 1,-0.448 1,-1V7c0,-0.552 -0.448,-1 -1,-1S6,6.448 6,7v2C6,9.552 6.448,10 7,10z"
+ android:fillColor="#FFFFFF"/>
+ <path
+ android:pathData="M18,18v-2H6.999c-0.263,0 -0.52,0.107 -0.706,0.293C6.106,16.479 6,16.737 6,17v8c0,0.263 0.106,0.521 0.292,0.707C6.478,25.893 6.735,26 6.999,26H16v-2H8v-6H18z"
+ android:fillColor="#FFFFFF"/>
+</vector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+ android:oneshot="false">
+ <item
+ android:drawable="@mipmap/l02_battery_0"
+ android:duration="150" />
+ <item
+ android:drawable="@mipmap/l02_battery_1"
+ android:duration="150" />
+ <item
+ android:drawable="@mipmap/l02_battery_2"
+ android:duration="150" />
+ <item
+ android:drawable="@mipmap/l02_battery_3"
+ android:duration="150" />
+ <item
+ android:drawable="@mipmap/l02_battery_4"
+ android:duration="150" />
+ <item
+ android:drawable="@mipmap/l02_battery_5"
+ android:duration="150" />
+</animation-list>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/main_content_fl"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".MainActivity" />
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".fragment.AppListFragment">
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/app_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+
+</LinearLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".fragment.L02MainFragment"
+ android:orientation="vertical">
+
+ <fragment
+ android:id="@+id/l02_status_fl"
+ android:name="com.ic.launcher.fragment.l02.L02StatusBarFragment"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/status_bar_height_dm"
+ android:layout_marginTop="10dp"/>
+
+ <fragment
+ android:id="@+id/l02_watch_fl"
+ android:name="com.ic.launcher.fragment.l02.L02WatchFragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</LinearLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context=".fragment.l02.L02StatusBarFragment">
+
+ <data>
+ <variable
+ name="phoneSignal"
+ type="int" />
+
+ <variable
+ name="phoneNetType"
+ type="int" />
+
+ <variable
+ name="phoneTransport"
+ type="int" />
+
+ <variable
+ name="batteryDrawable"
+ type="int" />
+
+ <variable
+ name="batteryValue"
+ type="String" />
+
+ <variable
+ name="batteryCharge"
+ type="boolean" />
+ </data>
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+
+ <com.ic.launcher.widget.WidgetPhoneStateView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.118"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:netTypeDrawable="@{phoneNetType}"
+ app:signalDrawable="@{phoneSignal}"
+ app:transportDrawable="@{phoneTransport}" />
+
+ <com.ic.launcher.widget.WidgetBatteryStateView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:batteryCharge="@{batteryCharge}"
+ app:batteryDrawable="@{batteryDrawable}"
+ app:batteryValue="@{batteryValue}"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.938"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"/>
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+</layout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context=".fragment.l02.L02WatchFragment">
+
+ <data>
+
+ <import type="java.util.ArrayList" />
+
+ <variable
+ name="timeText"
+ type="ArrayList<Integer>" />
+
+ <variable
+ name="watchDate"
+ type="String" />
+
+ <variable
+ name="watchWeek"
+ type="String" />
+
+ <variable
+ name="heartValue"
+ type="String" />
+
+ <variable
+ name="stepValue"
+ type="String" />
+ </data>
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.ic.launcher.widget.WidgetTimeImageView
+ android:id="@+id/l02_time_image"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="25dp"
+ app:timeImageResId="@{timeText}"/>
+
+ <View
+ android:id="@+id/l02_time_sp"
+ android:layout_width="1dp"
+ android:layout_height="80dp"
+ android:layout_below="@id/l02_time_image"
+ android:layout_centerHorizontal="true" />
+
+ <TextView
+ android:id="@+id/l02_watch_data"
+ style="@style/watchDateTextStyle"
+ android:layout_below="@id/l02_time_image"
+ android:layout_marginEnd="8dp"
+ android:layout_toStartOf="@id/l02_time_sp"
+ android:text="@{watchDate}" />
+
+ <TextView
+ style="@style/watchDateTextStyle"
+ android:layout_below="@id/l02_time_image"
+ android:layout_marginStart="8dp"
+ android:layout_toEndOf="@id/l02_time_sp"
+ android:text="@{watchWeek}" />
+
+ <TextView
+ style="@style/watchDateIconTextStyle"
+ android:id="@+id/l02_heart_value"
+ android:text="@{heartValue}"
+ android:layout_toStartOf="@id/l02_time_sp"
+ android:layout_marginEnd="10dp"/>
+
+ <ImageView
+ style="@style/watchDateIconStyle"
+ android:id="@+id/l02_heart_img"
+ android:src="@mipmap/clockl02_heartrate_icon"
+ android:layout_toStartOf="@id/l02_heart_value"
+ android:layout_marginEnd="5dp"/>
+
+ <ImageView
+ style="@style/watchDateIconStyle"
+ android:id="@+id/l02_pedometer_img"
+ android:src="@mipmap/clockl02_pedometer"
+ android:layout_toEndOf="@id/l02_time_sp"/>
+
+ <TextView
+ style="@style/watchDateIconTextStyle"
+ android:id="@+id/l02_pedometer_value"
+ android:layout_marginStart="2dp"
+ android:layout_toEndOf="@id/l02_pedometer_img"
+ android:text="@{stepValue}"/>
+
+ </RelativeLayout>
+</layout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <data>
+ <variable
+ name="appTitle"
+ type="String" />
+
+ <variable
+ name="pos"
+ type="int" />
+
+ <variable name="click" type="com.ic.launcher.listener.ICheckAppItemListener"/>
+ </data>
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:onClick="@{() -> click.onAppItem(pos)}">
+
+ <ImageView
+ android:id="@+id/app_icon_iv"
+ android:layout_width="180dp"
+ android:layout_height="180dp"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="30dp" />
+
+ <TextView
+ android:id="@+id/app_title_tv"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/app_icon_iv"
+ android:layout_centerHorizontal="true"
+ android:text="@{appTitle}"
+ android:textColor="#FFFFFF"
+ android:textSize="52sp"
+ android:layout_marginTop="15dp"/>
+ </RelativeLayout>
+
+</layout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_gravity="center_vertical">
+
+ <TextView
+ android:id="@+id/battery_tv"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#FFFFFF"
+ android:textSize="36sp"
+ android:textStyle="bold"
+ android:includeFontPadding="false"/>
+
+ <ImageView
+ android:id="@+id/battery_iv"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="5dp"/>
+
+</LinearLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/signal_iv"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <ImageView
+ android:id="@+id/net_type_iv"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="5dp"/>
+
+ <ImageView
+ android:id="@+id/transport_iv"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="2dp"/>
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:id="@+id/time_colon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true" />
+
+ <ImageView
+ android:id="@+id/time_hour_bit"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toStartOf="@id/time_colon" />
+
+ <ImageView
+ android:id="@+id/time_hour_ten"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toStartOf="@id/time_hour_bit" />
+
+ <ImageView
+ android:id="@+id/time_minute_ten"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toEndOf="@id/time_colon" />
+
+ <ImageView
+ android:id="@+id/time_minute_bit"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toEndOf="@id/time_minute_ten" />
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/time_hour_ten_tv"
+ style="@style/timeTextHourStyle"/>
+
+ <TextView
+ style="@style/timeTextHourStyle"
+ android:id="@+id/time_hour_bit_tv"
+ android:layout_toEndOf="@id/time_hour_ten_tv" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/time_colon_tv"
+ android:layout_toEndOf="@id/time_hour_bit_tv"
+ android:layout_centerVertical="true"/>
+
+ <TextView
+ style="@style/timeTextMinuteStyle"
+ android:id="@+id/time_minute_ten_tv"
+ android:layout_toEndOf="@id/time_colon_tv" />
+
+ <TextView
+ style="@style/timeTextMinuteStyle"
+ android:id="@+id/time_minute_bit_tv"
+ android:layout_toEndOf="@id/time_minute_ten_tv" />
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background" />
+ <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background" />
+ <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <declare-styleable name="GalleryRecyclerView">
+ <attr name="helper" format="string">
+ <enum name="LinearSnapHelper" value="0" />
+ <enum name="PagerSnapHelper" value="1" />
+ </attr>
+
+ </declare-styleable>
+</resources>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="colorPrimary">#008577</color>
+ <color name="colorPrimaryDark">#00574B</color>
+ <color name="colorAccent">#D81B60</color>
+
+ <color name="colorMainBg">#000000</color>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <dimen name="status_bar_height_dm">48dp</dimen>
+</resources>
\ No newline at end of file
--- /dev/null
+<resources>
+ <string name="app_name">IcLauncher</string>
+
+ <string name="hello_blank_fragment">Hello blank fragment</string>
+
+ <string name="app_name_contacts">联系人</string>
+ <string name="app_name_dialer">拨号</string>
+ <string name="app_name_motion">运动</string>
+ <string name="app_name_talk">微聊</string>
+ <string name="app_name_weather">天气</string>
+ <string name="app_name_heart">心率</string>
+ <string name="app_name_alipay">支付宝</string>
+ <string name="app_name_camera">照相</string>
+ <string name="app_name_album">相册</string>
+ <string name="app_name_short_message">短信</string>
+ <string name="app_name_setting">设置</string>
+
+ <string name="error_start_activity">应用程序启动失败</string>
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
+ <!-- Customize your theme here. -->
+ <item name="colorPrimary">@color/colorPrimary</item>
+ <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+ <item name="colorAccent">@color/colorAccent</item>
+ <item name="android:background">@color/colorMainBg</item>
+ </style>
+
+
+ <style name="timeTextHourStyle">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textSize">100sp</item>
+ <item name="android:textColor">#FFFF00</item>
+ <item name="android:includeFontPadding">false</item>
+ <item name="android:typeface">monospace</item>
+ </style>
+
+ <style name="timeTextMinuteStyle">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textSize">100sp</item>
+ <item name="android:textColor">#FFFFFF</item>
+ <item name="android:includeFontPadding">false</item>
+ <item name="android:typeface">monospace</item>
+ </style>
+
+ <style name="watchDateTextStyle">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textSize">42sp</item>
+ <item name="android:textColor">#FFFFFF</item>
+ <item name="android:includeFontPadding">false</item>
+ <item name="android:layout_marginTop">5dp</item>
+ </style>
+
+ <style name="watchDateIconStyle">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_alignParentBottom">true</item>
+ <item name="android:layout_marginBottom">20dp</item>
+ </style>
+
+ <style name="watchDateIconTextStyle" parent="watchDateIconStyle">
+ <item name="android:textSize">32sp</item>
+ <item name="android:textColor">#FFFFFF</item>
+ <item name="android:includeFontPadding">false</item>
+ <item name="android:layout_marginBottom">25dp</item>
+ </style>
+</resources>
--- /dev/null
+package com.ic.launcher;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
--- /dev/null
+// 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
+}
--- /dev/null
+# 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
+
--- /dev/null
+#Fri Mar 06 09:41:21 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
--- /dev/null
+#!/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" "$@"
--- /dev/null
+@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
--- /dev/null
+include ':app'
+rootProject.name='IcLauncher'