Initial commit
This commit is contained in:
commit
10a7f2f520
96 changed files with 5445 additions and 0 deletions
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
.idea
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
*.jks
|
||||
*.keystore
|
||||
keystore.properties
|
111
AndroidManifest.xml
Normal file
111
AndroidManifest.xml
Normal file
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015-2016 The CyanogenMod Project
|
||||
2017-2018 The LineageOS Project
|
||||
2020-2022 Paranoid Android
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="net.typeblog.lunatic"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0"
|
||||
android:sharedUserId="android.uid.system">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="31"
|
||||
android:targetSdkVersion="31"/>
|
||||
|
||||
<application
|
||||
android:label="@string/spotlight_settings_app_name"
|
||||
android:persistent="true"
|
||||
android:defaultToDeviceProtectedStorage="true"
|
||||
android:directBootAware="true">
|
||||
|
||||
<receiver
|
||||
android:name="net.typeblog.lunatic.BootCompletedReceiver"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name="net.typeblog.lunatic.Services.CallReceiverService"
|
||||
android:permission="android.permission.READ_PHONE_STATE">
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="net.typeblog.lunatic.Services.ChargingService">
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="net.typeblog.lunatic.Services.FlashlightService">
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="net.typeblog.lunatic.Services.MusicService">
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="net.typeblog.lunatic.Services.NotificationService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.notification.NotificationListenerService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<activity
|
||||
android:name="net.typeblog.lunatic.Settings.SettingsActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/spotlight_settings_title"
|
||||
android:theme="@style/Theme.SubSettingsBase">
|
||||
<!--<intent-filter>
|
||||
<action android:name="com.android.settings.action.EXTRA_SETTINGS" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="com.android.settings.category"
|
||||
android:value="com.android.settings.category.ia.homepage" />
|
||||
<meta-data
|
||||
android:name="com.android.settings.icon"
|
||||
android:resource="@drawable/ic_spotlights_logo" />
|
||||
<meta-data
|
||||
android:name="com.android.settings.summary"
|
||||
android:value="@string/spotlight_settings_summary" />
|
||||
<meta-data
|
||||
android:name="com.android.settings.order"
|
||||
android:value="-105" />-->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="net.typeblog.lunatic.Settings.NotifsSettingsActivity"
|
||||
android:exported="false"
|
||||
android:theme="@style/Theme.SubSettingsBase">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
</manifest>
|
1
SettingsLib/.gitignore
vendored
Normal file
1
SettingsLib/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
21
SettingsLib/AndroidManifest.xml
Normal file
21
SettingsLib/AndroidManifest.xml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2014 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.settingslib">
|
||||
<uses-sdk android:minSdkVersion="29" />
|
||||
</manifest>
|
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2021 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/content_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/app_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
android:outlineAmbientShadowColor="@android:color/transparent"
|
||||
android:outlineSpotShadowColor="@android:color/transparent"
|
||||
android:background="?android:attr/colorPrimary"
|
||||
android:theme="@style/Theme.CollapsingToolbar.Settings">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:id="@+id/collapsing_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/settingslib_toolbar_layout_height"
|
||||
android:clipToPadding="false"
|
||||
app:forceApplySystemWindowInsetTop="true"
|
||||
app:extraMultilineHeightEnabled="true"
|
||||
app:contentScrim="@color/settingslib_colorSurfaceHeader"
|
||||
app:maxLines="3"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
|
||||
app:scrimAnimationDuration="50"
|
||||
app:scrimVisibleHeightTrigger="@dimen/settingslib_scrim_visible_height_trigger"
|
||||
app:statusBarScrim="@null"
|
||||
app:titleCollapseMode="fade"
|
||||
app:collapsedTitleTextAppearance="@style/CollapsingToolbarTitle.Collapsed"
|
||||
app:expandedTitleTextAppearance="@style/CollapsingToolbarTitle.Expanded"
|
||||
app:expandedTitleMarginStart="@dimen/expanded_title_margin_start"
|
||||
app:expandedTitleMarginEnd="@dimen/expanded_title_margin_end"
|
||||
app:toolbarId="@id/action_bar">
|
||||
|
||||
<Toolbar
|
||||
android:id="@+id/action_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:theme="?android:attr/actionBarTheme"
|
||||
android:transitionName="shared_element_view"
|
||||
app:layout_collapseMode="pin"/>
|
||||
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/content_frame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<!-- The main content view -->
|
||||
<LinearLayout
|
||||
android:id="@+id/content_parent"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:transitionGroup="true"
|
||||
android:orientation="vertical">
|
||||
<Toolbar
|
||||
android:id="@+id/action_bar"
|
||||
style="?android:attr/actionBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="?android:attr/actionBarTheme" />
|
||||
<FrameLayout
|
||||
android:id="@+id/content_frame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<style name="Theme.CollapsingToolbar.Settings" parent="@style/Theme.MaterialComponents.DayNight">
|
||||
<item name="elevationOverlayEnabled">true</item>
|
||||
<item name="elevationOverlayColor">?attr/colorPrimary</item>
|
||||
<item name="colorPrimary">@color/settingslib_primary_dark_device_default_settings</item>
|
||||
<item name="colorAccent">@color/settingslib_accent_device_default_dark</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Collapsing toolbar layout dimensions -->
|
||||
<dimen name="settingslib_toolbar_layout_height">179dp</dimen>
|
||||
<dimen name="settingslib_scrim_visible_height_trigger">137dp</dimen>
|
||||
<dimen name="expanded_title_margin_start">24dp</dimen>
|
||||
<dimen name="expanded_title_margin_end">24dp</dimen>
|
||||
</resources>
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<style name="CollapsingToolbarTitle.Collapsed" parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
|
||||
<item name="android:fontFamily">@string/settingslib_config_headlineFontFamily</item>
|
||||
<item name="android:textSize">20dp</item>
|
||||
<item name="android:textColor">@color/settingslib_text_color_primary_device_default</item>
|
||||
</style>
|
||||
|
||||
<style name="CollapsingToolbarTitle.Expanded" parent="CollapsingToolbarTitle.Collapsed">
|
||||
<item name="android:textSize">36dp</item>
|
||||
<item name="android:textColor">@color/settingslib_text_color_primary_device_default</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<style name="Theme.CollapsingToolbar.Settings" parent="@style/Theme.MaterialComponents.DayNight">
|
||||
<item name="elevationOverlayEnabled">true</item>
|
||||
<item name="elevationOverlayColor">?attr/colorPrimary</item>
|
||||
<item name="colorPrimary">@color/settingslib_primary_device_default_settings_light</item>
|
||||
<item name="colorAccent">@color/settingslib_accent_device_default_light</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settingslib.collapsingtoolbar;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||
import com.google.android.material.resources.TextAppearanceConfig;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
|
||||
/**
|
||||
* A base Activity that has a collapsing toolbar layout is used for the activities intending to
|
||||
* enable the collapsing toolbar function.
|
||||
*/
|
||||
public class CollapsingToolbarBaseActivity extends FragmentActivity {
|
||||
|
||||
private static final float TOOLBAR_LINE_SPACING_MULTIPLIER = 1.1f;
|
||||
|
||||
@Nullable
|
||||
private CollapsingToolbarLayout mCollapsingToolbarLayout;
|
||||
@Nullable
|
||||
private AppBarLayout mAppBarLayout;
|
||||
private int mCustomizeLayoutResId = 0;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (mCustomizeLayoutResId > 0 && !true) {
|
||||
super.setContentView(mCustomizeLayoutResId);
|
||||
return;
|
||||
}
|
||||
// Force loading font synchronously for collapsing toolbar layout
|
||||
TextAppearanceConfig.setShouldLoadFontSynchronously(true);
|
||||
super.setContentView(R.layout.collapsing_toolbar_base_layout);
|
||||
mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
|
||||
mAppBarLayout = findViewById(R.id.app_bar);
|
||||
if (mCollapsingToolbarLayout != null) {
|
||||
mCollapsingToolbarLayout.setLineSpacingMultiplier(TOOLBAR_LINE_SPACING_MULTIPLIER);
|
||||
}
|
||||
disableCollapsingToolbarLayoutScrollingBehavior();
|
||||
|
||||
final Toolbar toolbar = findViewById(R.id.action_bar);
|
||||
setActionBar(toolbar);
|
||||
|
||||
// Enable title and home button by default
|
||||
final ActionBar actionBar = getActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setHomeButtonEnabled(true);
|
||||
actionBar.setDisplayShowTitleEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(int layoutResID) {
|
||||
final ViewGroup parent = findViewById(R.id.content_frame);
|
||||
if (parent != null) {
|
||||
parent.removeAllViews();
|
||||
}
|
||||
LayoutInflater.from(this).inflate(layoutResID, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(View view) {
|
||||
final ViewGroup parent = findViewById(R.id.content_frame);
|
||||
if (parent != null) {
|
||||
parent.addView(view);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(View view, ViewGroup.LayoutParams params) {
|
||||
final ViewGroup parent = findViewById(R.id.content_frame);
|
||||
if (parent != null) {
|
||||
parent.addView(view, params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows an activity to replace the default layout with a customize layout. Notice
|
||||
* that it will no longer apply the features being provided by this class when this method
|
||||
* gets called.
|
||||
*/
|
||||
protected void setCustomizeContentView(int layoutResId) {
|
||||
mCustomizeLayoutResId = layoutResId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(CharSequence title) {
|
||||
if (mCollapsingToolbarLayout != null) {
|
||||
mCollapsingToolbarLayout.setTitle(title);
|
||||
} else {
|
||||
super.setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(int titleId) {
|
||||
if (mCollapsingToolbarLayout != null) {
|
||||
mCollapsingToolbarLayout.setTitle(getText(titleId));
|
||||
} else {
|
||||
super.setTitle(titleId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onNavigateUp() {
|
||||
if (!super.onNavigateUp()) {
|
||||
finishAfterTransition();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of collapsing toolbar.
|
||||
*/
|
||||
@Nullable
|
||||
public CollapsingToolbarLayout getCollapsingToolbarLayout() {
|
||||
return mCollapsingToolbarLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of app bar.
|
||||
*/
|
||||
@Nullable
|
||||
public AppBarLayout getAppBarLayout() {
|
||||
return mAppBarLayout;
|
||||
}
|
||||
|
||||
private void disableCollapsingToolbarLayoutScrollingBehavior() {
|
||||
if (mAppBarLayout == null) {
|
||||
return;
|
||||
}
|
||||
final CoordinatorLayout.LayoutParams params =
|
||||
(CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
|
||||
final AppBarLayout.Behavior behavior = new AppBarLayout.Behavior();
|
||||
behavior.setDragCallback(
|
||||
new AppBarLayout.Behavior.DragCallback() {
|
||||
@Override
|
||||
public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
params.setBehavior(behavior);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settingslib.collapsingtoolbar;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
|
||||
/**
|
||||
* A base fragment that has a collapsing toolbar layout for enabling the collapsing toolbar design.
|
||||
*/
|
||||
public abstract class CollapsingToolbarBaseFragment extends Fragment {
|
||||
|
||||
private static final float TOOLBAR_LINE_SPACING_MULTIPLIER = 1.1f;
|
||||
|
||||
@Nullable
|
||||
private CoordinatorLayout mCoordinatorLayout;
|
||||
@Nullable
|
||||
private CollapsingToolbarLayout mCollapsingToolbarLayout;
|
||||
@Nullable
|
||||
private AppBarLayout mAppBarLayout;
|
||||
@NonNull
|
||||
private Toolbar mToolbar;
|
||||
@NonNull
|
||||
private FrameLayout mContentFrameLayout;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
final View view = inflater.inflate(R.layout.collapsing_toolbar_base_layout, container,
|
||||
false);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
mCoordinatorLayout = view.findViewById(R.id.content_parent);
|
||||
}
|
||||
mCollapsingToolbarLayout = view.findViewById(R.id.collapsing_toolbar);
|
||||
mAppBarLayout = view.findViewById(R.id.app_bar);
|
||||
if (mCollapsingToolbarLayout != null) {
|
||||
mCollapsingToolbarLayout.setLineSpacingMultiplier(TOOLBAR_LINE_SPACING_MULTIPLIER);
|
||||
}
|
||||
disableCollapsingToolbarLayoutScrollingBehavior();
|
||||
mToolbar = view.findViewById(R.id.action_bar);
|
||||
mContentFrameLayout = view.findViewById(R.id.content_frame);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
requireActivity().setActionBar(mToolbar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of CoordinatorLayout.
|
||||
*/
|
||||
@Nullable
|
||||
public CoordinatorLayout getCoordinatorLayout() {
|
||||
return mCoordinatorLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of app bar.
|
||||
*/
|
||||
@Nullable
|
||||
public AppBarLayout getAppBarLayout() {
|
||||
return mAppBarLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the collapsing toolbar layout.
|
||||
*/
|
||||
@Nullable
|
||||
public CollapsingToolbarLayout getCollapsingToolbarLayout() {
|
||||
return mCollapsingToolbarLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content frame layout.
|
||||
*/
|
||||
@NonNull
|
||||
public FrameLayout getContentFrameLayout() {
|
||||
return mContentFrameLayout;
|
||||
}
|
||||
|
||||
private void disableCollapsingToolbarLayoutScrollingBehavior() {
|
||||
if (mAppBarLayout == null) {
|
||||
return;
|
||||
}
|
||||
final CoordinatorLayout.LayoutParams params =
|
||||
(CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
|
||||
final AppBarLayout.Behavior behavior = new AppBarLayout.Behavior();
|
||||
behavior.setDragCallback(
|
||||
new AppBarLayout.Behavior.DragCallback() {
|
||||
@Override
|
||||
public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
params.setBehavior(behavior);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settingslib.collapsingtoolbar;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
/**
|
||||
* A base Activity for Settings-specific page transition. Activities extending it will get
|
||||
* Settings transition applied.
|
||||
*/
|
||||
public abstract class SettingsTransitionActivity extends FragmentActivity {
|
||||
private static final String TAG = "SettingsTransitionActivity";
|
||||
|
||||
protected boolean isSettingsTransitionEnabled() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/settingslib_protection_color"/>
|
||||
<corners android:radius="28dp"/>
|
||||
<size android:width="@dimen/settingslib_illustration_width"
|
||||
android:height="@dimen/settingslib_illustration_height"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:background="?android:attr/colorBackground"
|
||||
android:importantForAccessibility="noHideDescendants"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/illustration_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingHorizontal="@dimen/settingslib_illustration_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/background_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:adjustViewBounds="true"
|
||||
android:src="@drawable/protection_background"/>
|
||||
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/lottie_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:maxWidth="@dimen/settingslib_illustration_width"
|
||||
android:maxHeight="@dimen/settingslib_illustration_height"
|
||||
android:adjustViewBounds="true"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/middleground_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"/>
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<color name="settingslib_protection_color">@android:color/black</color>
|
||||
</resources>
|
62
SettingsLib/IllustrationPreference/res/values/colors.xml
Normal file
62
SettingsLib/IllustrationPreference/res/values/colors.xml
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<color name="settingslib_protection_color">@android:color/white</color>
|
||||
|
||||
<!-- Dynamic colors-->
|
||||
<color name="settingslib_color_blue600">#1a73e8</color>
|
||||
<color name="settingslib_color_blue400">#669df6</color>
|
||||
<color name="settingslib_color_blue300">#8ab4f8</color>
|
||||
<color name="settingslib_color_blue100">#d2e3fc</color>
|
||||
<color name="settingslib_color_blue50">#e8f0fe</color>
|
||||
<color name="settingslib_color_green600">#1e8e3e</color>
|
||||
<color name="settingslib_color_green400">#5bb974</color>
|
||||
<color name="settingslib_color_green100">#ceead6</color>
|
||||
<color name="settingslib_color_green50">#e6f4ea</color>
|
||||
<color name="settingslib_color_red600">#d93025</color>
|
||||
<color name="settingslib_color_red400">#ee675c</color>
|
||||
<color name="settingslib_color_red100">#fad2cf</color>
|
||||
<color name="settingslib_color_red50">#fce8e6</color>
|
||||
<color name="settingslib_color_yellow600">#f9ab00</color>
|
||||
<color name="settingslib_color_yellow400">#fcc934</color>
|
||||
<color name="settingslib_color_yellow100">#feefc3</color>
|
||||
<color name="settingslib_color_yellow50">#fef7e0</color>
|
||||
<color name="settingslib_color_grey900">#202124</color>
|
||||
<color name="settingslib_color_grey800">#3c4043</color>
|
||||
<color name="settingslib_color_grey700">#5f6368</color>
|
||||
<color name="settingslib_color_grey600">#80868b</color>
|
||||
<color name="settingslib_color_grey400">#bdc1c6</color>
|
||||
<color name="settingslib_color_grey300">#dadce0</color>
|
||||
<color name="settingslib_color_grey200">#e8eaed</color>
|
||||
<color name="settingslib_color_orange600">#e8710a</color>
|
||||
<color name="settingslib_color_orange400">#fa903e</color>
|
||||
<color name="settingslib_color_orange300">#fcad70</color>
|
||||
<color name="settingslib_color_orange100">#fedfc8</color>
|
||||
<color name="settingslib_color_pink600">#e52592</color>
|
||||
<color name="settingslib_color_pink400">#ff63b8</color>
|
||||
<color name="settingslib_color_pink300">#ff8bcb</color>
|
||||
<color name="settingslib_color_pink100">#fdcfe8</color>
|
||||
<color name="settingslib_color_purple600">#9334e6</color>
|
||||
<color name="settingslib_color_purple400">#af5cf7</color>
|
||||
<color name="settingslib_color_purple300">#c58af9</color>
|
||||
<color name="settingslib_color_purple100">#e9d2fd</color>
|
||||
<color name="settingslib_color_cyan600">#12b5c8</color>
|
||||
<color name="settingslib_color_cyan400">#4ecde6</color>
|
||||
<color name="settingslib_color_cyan300">#78d9ec</color>
|
||||
<color name="settingslib_color_cyan100">#cbf0f8</color>
|
||||
</resources>
|
24
SettingsLib/IllustrationPreference/res/values/dimens.xml
Normal file
24
SettingsLib/IllustrationPreference/res/values/dimens.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<!-- Padding of illustration -->
|
||||
<dimen name="settingslib_illustration_padding">16dp</dimen>
|
||||
|
||||
<dimen name="settingslib_illustration_width">412dp</dimen>
|
||||
<dimen name="settingslib_illustration_height">300dp</dimen>
|
||||
</resources>
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settingslib.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
import com.airbnb.lottie.LottieProperty;
|
||||
import com.airbnb.lottie.model.KeyPath;
|
||||
import com.airbnb.lottie.value.LottieFrameInfo;
|
||||
import com.airbnb.lottie.value.SimpleLottieValueCallback;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
|
||||
/**
|
||||
* ColorUtils is a util class which help the lottie illustration
|
||||
* changes the color of tags in the json file.
|
||||
*/
|
||||
|
||||
public class ColorUtils {
|
||||
|
||||
private static HashMap<String, Integer> sSysColors;
|
||||
|
||||
private static HashMap<String, Pair<Integer, Integer>> sFixedColors;
|
||||
static {
|
||||
sFixedColors = new HashMap<>();
|
||||
sFixedColors.put(".blue600", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_blue600, R.color.settingslib_color_blue400));
|
||||
sFixedColors.put(".green600", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_green600, R.color.settingslib_color_green400));
|
||||
sFixedColors.put(".red600", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_red600, R.color.settingslib_color_red400));
|
||||
sFixedColors.put(".yellow600", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_yellow600, R.color.settingslib_color_yellow400));
|
||||
sFixedColors.put(".blue400", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_blue400, R.color.settingslib_color_blue100));
|
||||
sFixedColors.put(".green400", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_green400, R.color.settingslib_color_green100));
|
||||
sFixedColors.put(".red400", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_red400, R.color.settingslib_color_red100));
|
||||
sFixedColors.put(".yellow400", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_yellow400, R.color.settingslib_color_yellow100));
|
||||
sFixedColors.put(".blue300", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_blue300, R.color.settingslib_color_blue50));
|
||||
sFixedColors.put(".blue50", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_blue50, R.color.settingslib_color_grey900));
|
||||
sFixedColors.put(".green50", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_green50, R.color.settingslib_color_grey900));
|
||||
sFixedColors.put(".red50", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_red50, R.color.settingslib_color_grey900));
|
||||
sFixedColors.put(".yellow50", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_yellow50, R.color.settingslib_color_grey900));
|
||||
// Secondary colors
|
||||
sFixedColors.put(".orange600", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_orange600, R.color.settingslib_color_orange300));
|
||||
sFixedColors.put(".pink600", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_pink600, R.color.settingslib_color_pink300));
|
||||
sFixedColors.put(".purple600", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_purple600, R.color.settingslib_color_purple300));
|
||||
sFixedColors.put(".cyan600", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_cyan600, R.color.settingslib_color_cyan300));
|
||||
sFixedColors.put(".orange400", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_orange400, R.color.settingslib_color_orange100));
|
||||
sFixedColors.put(".pink400", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_pink400, R.color.settingslib_color_pink100));
|
||||
sFixedColors.put(".purple400", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_purple400, R.color.settingslib_color_purple100));
|
||||
sFixedColors.put(".cyan400", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_cyan400, R.color.settingslib_color_cyan100));
|
||||
sFixedColors.put(".gery400", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_grey400, R.color.settingslib_color_grey700));
|
||||
sFixedColors.put(".gery300", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_grey300, R.color.settingslib_color_grey600));
|
||||
sFixedColors.put(".gery200", new Pair<Integer, Integer>(
|
||||
R.color.settingslib_color_grey200, R.color.settingslib_color_grey800));
|
||||
}
|
||||
|
||||
private static boolean isDarkMode(Context context) {
|
||||
return (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
|
||||
== Configuration.UI_MODE_NIGHT_YES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the color of tags to the animation.
|
||||
*/
|
||||
public static void applyDynamicColors(Context context, LottieAnimationView animationView) {
|
||||
for (String key : sFixedColors.keySet()) {
|
||||
final Pair<Integer, Integer> fixedColorPair = sFixedColors.get(key);
|
||||
final int color = isDarkMode(context) ? fixedColorPair.second : fixedColorPair.first;
|
||||
animationView.addValueCallback(
|
||||
new KeyPath("**", key, "**"),
|
||||
LottieProperty.COLOR_FILTER,
|
||||
new SimpleLottieValueCallback<ColorFilter>() {
|
||||
@Override
|
||||
public ColorFilter getValue(LottieFrameInfo<ColorFilter> frameInfo) {
|
||||
return new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settingslib.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.Animatable2;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.RawRes;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.vectordrawable.graphics.drawable.Animatable2Compat;
|
||||
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
import com.airbnb.lottie.LottieDrawable;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
|
||||
/**
|
||||
* IllustrationPreference is a preference that can play lottie format animation
|
||||
*/
|
||||
public class IllustrationPreference extends Preference {
|
||||
|
||||
private static final String TAG = "IllustrationPreference";
|
||||
|
||||
private static final boolean IS_ENABLED_LOTTIE_ADAPTIVE_COLOR = false;
|
||||
private static final int SIZE_UNSPECIFIED = -1;
|
||||
|
||||
private int mMaxHeight = SIZE_UNSPECIFIED;
|
||||
private int mImageResId;
|
||||
private boolean mIsAutoScale;
|
||||
private Uri mImageUri;
|
||||
private Drawable mImageDrawable;
|
||||
private View mMiddleGroundView;
|
||||
|
||||
private final Animatable2.AnimationCallback mAnimationCallback =
|
||||
new Animatable2.AnimationCallback() {
|
||||
@Override
|
||||
public void onAnimationEnd(Drawable drawable) {
|
||||
((Animatable) drawable).start();
|
||||
}
|
||||
};
|
||||
|
||||
private final Animatable2Compat.AnimationCallback mAnimationCallbackCompat =
|
||||
new Animatable2Compat.AnimationCallback() {
|
||||
@Override
|
||||
public void onAnimationEnd(Drawable drawable) {
|
||||
((Animatable) drawable).start();
|
||||
}
|
||||
};
|
||||
|
||||
public IllustrationPreference(Context context) {
|
||||
super(context);
|
||||
init(context, /* attrs= */ null);
|
||||
}
|
||||
|
||||
public IllustrationPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public IllustrationPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public IllustrationPreference(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
|
||||
final ImageView backgroundView =
|
||||
(ImageView) holder.findViewById(R.id.background_view);
|
||||
final FrameLayout middleGroundLayout =
|
||||
(FrameLayout) holder.findViewById(R.id.middleground_layout);
|
||||
final LottieAnimationView illustrationView =
|
||||
(LottieAnimationView) holder.findViewById(R.id.lottie_view);
|
||||
|
||||
// To solve the problem of non-compliant illustrations, we set the frame height
|
||||
// to 300dp and set the length of the short side of the screen to
|
||||
// the width of the frame.
|
||||
final int screenWidth = getContext().getResources().getDisplayMetrics().widthPixels;
|
||||
final int screenHeight = getContext().getResources().getDisplayMetrics().heightPixels;
|
||||
final FrameLayout illustrationFrame = (FrameLayout) holder.findViewById(
|
||||
R.id.illustration_frame);
|
||||
final LayoutParams lp = (LayoutParams) illustrationFrame.getLayoutParams();
|
||||
lp.width = screenWidth < screenHeight ? screenWidth : screenHeight;
|
||||
illustrationFrame.setLayoutParams(lp);
|
||||
|
||||
handleImageWithAnimation(illustrationView);
|
||||
handleImageFrameMaxHeight(backgroundView, illustrationView);
|
||||
|
||||
if (mIsAutoScale) {
|
||||
illustrationView.setScaleType(mIsAutoScale
|
||||
? ImageView.ScaleType.CENTER_CROP
|
||||
: ImageView.ScaleType.CENTER_INSIDE);
|
||||
}
|
||||
|
||||
handleMiddleGroundView(middleGroundLayout);
|
||||
|
||||
if (IS_ENABLED_LOTTIE_ADAPTIVE_COLOR) {
|
||||
ColorUtils.applyDynamicColors(getContext(), illustrationView);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the middle ground view to preference. The user
|
||||
* can overlay a view on top of the animation.
|
||||
*/
|
||||
public void setMiddleGroundView(View view) {
|
||||
if (view != mMiddleGroundView) {
|
||||
mMiddleGroundView = view;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the middle ground view of preference.
|
||||
*/
|
||||
public void removeMiddleGroundView() {
|
||||
mMiddleGroundView = null;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the auto scale feature of animation view.
|
||||
*/
|
||||
public void enableAnimationAutoScale(boolean enable) {
|
||||
if (enable != mIsAutoScale) {
|
||||
mIsAutoScale = enable;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lottie illustration resource id.
|
||||
*/
|
||||
public void setLottieAnimationResId(int resId) {
|
||||
if (resId != mImageResId) {
|
||||
resetImageResourceCache();
|
||||
mImageResId = resId;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the lottie illustration resource id.
|
||||
*/
|
||||
public int getLottieAnimationResId() {
|
||||
return mImageResId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the image drawable to display image in {@link LottieAnimationView}.
|
||||
*
|
||||
* @param imageDrawable the drawable of an image
|
||||
*/
|
||||
public void setImageDrawable(Drawable imageDrawable) {
|
||||
if (imageDrawable != mImageDrawable) {
|
||||
resetImageResourceCache();
|
||||
mImageDrawable = imageDrawable;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the image drawable from display image in {@link LottieAnimationView}.
|
||||
*
|
||||
* @return the drawable of an image
|
||||
*/
|
||||
public Drawable getImageDrawable() {
|
||||
return mImageDrawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the image uri to display image in {@link LottieAnimationView}.
|
||||
*
|
||||
* @param imageUri the Uri of an image
|
||||
*/
|
||||
public void setImageUri(Uri imageUri) {
|
||||
if (imageUri != mImageUri) {
|
||||
resetImageResourceCache();
|
||||
mImageUri = imageUri;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the image uri from display image in {@link LottieAnimationView}.
|
||||
*
|
||||
* @return the Uri of an image
|
||||
*/
|
||||
public Uri getImageUri() {
|
||||
return mImageUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum height of the views, still use the specific one if the maximum height was
|
||||
* larger than the specific height from XML.
|
||||
*
|
||||
* @param maxHeight the maximum height of the frame views in terms of pixels.
|
||||
*/
|
||||
public void setMaxHeight(int maxHeight) {
|
||||
if (maxHeight != mMaxHeight) {
|
||||
mMaxHeight = maxHeight;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetImageResourceCache() {
|
||||
mImageDrawable = null;
|
||||
mImageUri = null;
|
||||
mImageResId = 0;
|
||||
}
|
||||
|
||||
private void handleMiddleGroundView(ViewGroup middleGroundLayout) {
|
||||
middleGroundLayout.removeAllViews();
|
||||
|
||||
if (mMiddleGroundView != null) {
|
||||
middleGroundLayout.addView(mMiddleGroundView);
|
||||
middleGroundLayout.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
middleGroundLayout.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleImageWithAnimation(LottieAnimationView illustrationView) {
|
||||
if (mImageDrawable != null) {
|
||||
resetAnimations(illustrationView);
|
||||
illustrationView.setImageDrawable(mImageDrawable);
|
||||
final Drawable drawable = illustrationView.getDrawable();
|
||||
if (drawable != null) {
|
||||
startAnimation(drawable);
|
||||
}
|
||||
}
|
||||
|
||||
if (mImageUri != null) {
|
||||
resetAnimations(illustrationView);
|
||||
illustrationView.setImageURI(mImageUri);
|
||||
final Drawable drawable = illustrationView.getDrawable();
|
||||
if (drawable != null) {
|
||||
startAnimation(drawable);
|
||||
} else {
|
||||
// The lottie image from the raw folder also returns null because the ImageView
|
||||
// couldn't handle it now.
|
||||
startLottieAnimationWith(illustrationView, mImageUri);
|
||||
}
|
||||
}
|
||||
|
||||
if (mImageResId > 0) {
|
||||
resetAnimations(illustrationView);
|
||||
illustrationView.setImageResource(mImageResId);
|
||||
final Drawable drawable = illustrationView.getDrawable();
|
||||
if (drawable != null) {
|
||||
startAnimation(drawable);
|
||||
} else {
|
||||
// The lottie image from the raw folder also returns null because the ImageView
|
||||
// couldn't handle it now.
|
||||
startLottieAnimationWith(illustrationView, mImageResId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleImageFrameMaxHeight(ImageView backgroundView, ImageView illustrationView) {
|
||||
if (mMaxHeight == SIZE_UNSPECIFIED) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Resources res = backgroundView.getResources();
|
||||
final int frameWidth = res.getDimensionPixelSize(R.dimen.settingslib_illustration_width);
|
||||
final int frameHeight = res.getDimensionPixelSize(R.dimen.settingslib_illustration_height);
|
||||
final int restrictedMaxHeight = Math.min(mMaxHeight, frameHeight);
|
||||
backgroundView.setMaxHeight(restrictedMaxHeight);
|
||||
illustrationView.setMaxHeight(restrictedMaxHeight);
|
||||
|
||||
// Ensures the illustration view size is smaller than or equal to the background view size.
|
||||
final float aspectRatio = (float) frameWidth / frameHeight;
|
||||
illustrationView.setMaxWidth((int) (restrictedMaxHeight * aspectRatio));
|
||||
}
|
||||
|
||||
private void startAnimation(Drawable drawable) {
|
||||
if (!(drawable instanceof Animatable)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (drawable instanceof Animatable2) {
|
||||
((Animatable2) drawable).registerAnimationCallback(mAnimationCallback);
|
||||
} else if (drawable instanceof Animatable2Compat) {
|
||||
((Animatable2Compat) drawable).registerAnimationCallback(mAnimationCallbackCompat);
|
||||
} else if (drawable instanceof AnimationDrawable) {
|
||||
((AnimationDrawable) drawable).setOneShot(false);
|
||||
}
|
||||
|
||||
((Animatable) drawable).start();
|
||||
}
|
||||
|
||||
private static void startLottieAnimationWith(LottieAnimationView illustrationView,
|
||||
Uri imageUri) {
|
||||
final InputStream inputStream =
|
||||
getInputStreamFromUri(illustrationView.getContext(), imageUri);
|
||||
illustrationView.setFailureListener(
|
||||
result -> Log.w(TAG, "Invalid illustration image uri: " + imageUri, result));
|
||||
illustrationView.setAnimation(inputStream, /* cacheKey= */ null);
|
||||
illustrationView.setRepeatCount(LottieDrawable.INFINITE);
|
||||
illustrationView.playAnimation();
|
||||
}
|
||||
|
||||
private static void startLottieAnimationWith(LottieAnimationView illustrationView,
|
||||
@RawRes int rawRes) {
|
||||
illustrationView.setFailureListener(
|
||||
result -> Log.w(TAG, "Invalid illustration resource id: " + rawRes, result));
|
||||
illustrationView.setAnimation(rawRes);
|
||||
illustrationView.setRepeatCount(LottieDrawable.INFINITE);
|
||||
illustrationView.playAnimation();
|
||||
}
|
||||
|
||||
private static void resetAnimations(LottieAnimationView illustrationView) {
|
||||
resetAnimation(illustrationView.getDrawable());
|
||||
|
||||
illustrationView.cancelAnimation();
|
||||
}
|
||||
|
||||
private static void resetAnimation(Drawable drawable) {
|
||||
if (!(drawable instanceof Animatable |