Dream settings refactor.
We will be re-using the grid UI for the dream complication picker, so this change refactors some of that logic so it can be re-used in the complication controller. We also update some of the UI here to match the most recent UX decisions. http://screen/BxhAwZwQSVoxUmN.png Test: locally on device Test: make -j64 RunSettingsRoboTests ROBOTEST_FILTER="com.android.settings.dream.DreamPickerControllerTest" Bug: 214250590 Bug: 215703483 Change-Id: I9fbfa0f0cd31ae3d119c7cd1a9562d4cdb203d6c
This commit is contained in:
@@ -17,6 +17,6 @@
|
|||||||
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
|
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
|
||||||
<item android:state_activated="true" android:color="?androidprv:attr/colorSurfaceHighlight"/>
|
<item android:state_activated="true" android:color="?androidprv:attr/colorSurfaceVariant"/>
|
||||||
<item android:color="?androidprv:attr/colorSurface"/>
|
<item android:color="?androidprv:attr/colorSurfaceHighlight"/>
|
||||||
</selector>
|
</selector>
|
24
res/drawable/ic_dream_check_circle.xml
Normal file
24
res/drawable/ic_dream_check_circle.xml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (C) 2022 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.
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="@dimen/dream_item_icon_size"
|
||||||
|
android:height="@dimen/dream_item_icon_size"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M12.0,2.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0zm-2.0,15.0l-5.0,-5.0 1.41,-1.41L10.0,14.17l7.59,-7.59L19.0,8.0l-9.0,9.0z"/>
|
||||||
|
</vector>
|
@@ -15,28 +15,43 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
android:padding="@dimen/dream_picker_padding">
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.cardview.widget.CardView
|
||||||
android:id="@+id/dream_list"
|
android:id="@+id/dream_picker_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:clipToPadding="true"
|
style="@style/DreamPickerBackgroundStyle">
|
||||||
android:nestedScrollingEnabled="false"/>
|
|
||||||
|
|
||||||
<Button
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/preview_button"
|
android:layout_width="match_parent"
|
||||||
style="@style/ActionPrimaryButton"
|
android:layout_height="wrap_content">
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dream_preview_button_title"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/dream_list"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/dream_list"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipToPadding="true"
|
||||||
|
android:nestedScrollingEnabled="false"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/preview_button"
|
||||||
|
style="@style/ActionPrimaryButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:text="@string/dream_preview_button_title"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/dream_list"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
</LinearLayout>
|
||||||
|
@@ -17,18 +17,17 @@
|
|||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/container"
|
android:id="@+id/container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="10dp"
|
|
||||||
style="@style/DreamCardStyle"
|
style="@style/DreamCardStyle"
|
||||||
android:clickable="true">
|
android:clickable="true">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight">
|
android:minHeight="?android:attr/listPreferredItemHeight">
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
@@ -37,16 +36,14 @@
|
|||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:cardCornerRadius="@dimen/dream_item_corner_radius"
|
app:cardCornerRadius="@dimen/dream_item_corner_radius"
|
||||||
app:cardElevation="0dp"
|
app:cardElevation="0dp"
|
||||||
app:layout_constraintDimensionRatio="3:2"
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent">
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/preview"
|
android:id="@+id/preview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"/>
|
android:scaleType="centerCrop"/>
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@@ -63,12 +60,14 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/icon"
|
android:id="@+id/icon"
|
||||||
android:layout_width="18dp"
|
android:layout_width="@dimen/dream_item_icon_size"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="18dp"
|
android:layout_marginTop="@dimen/dream_item_title_margin_top"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="@dimen/dream_item_icon_margin_start"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="@dimen/dream_item_title_margin_bottom"
|
||||||
|
android:gravity="center_vertical"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
|
app:layout_constraintHorizontal_chainStyle="packed"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/preview_container"
|
app:layout_constraintTop_toBottomOf="@+id/preview_container"
|
||||||
app_layout_constraintEnd_toStartOf="@+id/title_text"
|
app_layout_constraintEnd_toStartOf="@+id/title_text"
|
||||||
app:layout_constraintStart_toStartOf="parent"/>
|
app:layout_constraintStart_toStartOf="parent"/>
|
||||||
@@ -77,9 +76,10 @@
|
|||||||
android:id="@+id/title_text"
|
android:id="@+id/title_text"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="18dp"
|
android:layout_marginTop="@dimen/dream_item_title_margin_top"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginStart="@dimen/dream_item_title_margin_start"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="@dimen/dream_item_title_margin_bottom"
|
||||||
|
android:gravity="center_vertical"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:textAppearance="?android:attr/textAppearanceListItemSmall"
|
android:textAppearance="?android:attr/textAppearanceListItemSmall"
|
||||||
@@ -87,18 +87,5 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/icon"/>
|
app:layout_constraintStart_toEndOf="@+id/icon"/>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/summary_text"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/title_text"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"/>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
@@ -441,11 +441,17 @@
|
|||||||
<dimen name="chartview_trapezoid_margin_bottom">2dp</dimen>
|
<dimen name="chartview_trapezoid_margin_bottom">2dp</dimen>
|
||||||
|
|
||||||
<!-- Dimensions for Dream settings cards -->
|
<!-- Dimensions for Dream settings cards -->
|
||||||
<dimen name="dream_item_min_column_width">230dp</dimen>
|
<dimen name="dream_item_min_column_width">210dp</dimen>
|
||||||
<dimen name="dream_item_corner_radius">@*android:dimen/config_dialogCornerRadius</dimen>
|
<dimen name="dream_item_corner_radius">28dp</dimen>
|
||||||
<dimen name="dream_preference_margin_horizontal">4dp</dimen>
|
<dimen name="dream_item_content_padding">8dp</dimen>
|
||||||
<dimen name="dream_preference_margin_bottom">8dp</dimen>
|
<dimen name="dream_item_icon_size">20dp</dimen>
|
||||||
<dimen name="dream_picker_padding">40dp</dimen>
|
<dimen name="dream_item_title_margin_top">18dp</dimen>
|
||||||
|
<dimen name="dream_item_title_margin_bottom">8dp</dimen>
|
||||||
|
<dimen name="dream_item_title_margin_start">18dp</dimen>
|
||||||
|
<dimen name="dream_item_icon_margin_start">10dp</dimen>
|
||||||
|
<dimen name="dream_preference_margin_horizontal">10dp</dimen>
|
||||||
|
<dimen name="dream_preference_margin_bottom">20dp</dimen>
|
||||||
|
<dimen name="dream_picker_margin_horizontal">48dp</dimen>
|
||||||
|
|
||||||
<!-- Sims/Data mobile/Calls/SMS select dialog-->
|
<!-- Sims/Data mobile/Calls/SMS select dialog-->
|
||||||
<dimen name="sims_select_margin_bottom">24dp</dimen>
|
<dimen name="sims_select_margin_bottom">24dp</dimen>
|
||||||
|
@@ -951,5 +951,16 @@
|
|||||||
<item name="cardCornerRadius">@dimen/dream_item_corner_radius</item>
|
<item name="cardCornerRadius">@dimen/dream_item_corner_radius</item>
|
||||||
<item name="cardElevation">0dp</item>
|
<item name="cardElevation">0dp</item>
|
||||||
<item name="rippleColor">?android:attr/colorControlHighlight</item>
|
<item name="rippleColor">?android:attr/colorControlHighlight</item>
|
||||||
|
<item name="contentPadding">@dimen/dream_item_content_padding</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="DreamPickerBackgroundStyle">
|
||||||
|
<item name="android:layout_marginBottom">48dp</item>
|
||||||
|
<item name="android:layout_marginStart">@dimen/dream_picker_margin_horizontal</item>
|
||||||
|
<item name="android:layout_marginEnd">@dimen/dream_picker_margin_horizontal</item>
|
||||||
|
<item name="cardBackgroundColor">?androidprv:attr/colorSurface</item>
|
||||||
|
<item name="cardCornerRadius">24dp</item>
|
||||||
|
<item name="cardElevation">0dp</item>
|
||||||
|
<item name="contentPadding">32dp</item>
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
44
src/com/android/settings/dream/AutoFitGridLayoutManager.java
Normal file
44
src/com/android/settings/dream/AutoFitGridLayoutManager.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.settings.dream;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
/** Grid layout manager that calculates the number of columns for the screen size. */
|
||||||
|
final class AutoFitGridLayoutManager extends GridLayoutManager {
|
||||||
|
private final float mColumnWidth;
|
||||||
|
|
||||||
|
AutoFitGridLayoutManager(Context context) {
|
||||||
|
super(context, /* spanCount= */ 1);
|
||||||
|
this.mColumnWidth = context
|
||||||
|
.getResources()
|
||||||
|
.getDimensionPixelSize(R.dimen.dream_item_min_column_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||||
|
final int totalSpace = getWidth() - getPaddingRight() - getPaddingLeft();
|
||||||
|
final int spanCount = Math.max(1, (int) (totalSpace / mColumnWidth));
|
||||||
|
setSpanCount(spanCount);
|
||||||
|
super.onLayoutChildren(recycler, state);
|
||||||
|
}
|
||||||
|
}
|
107
src/com/android/settings/dream/DreamAdapter.java
Normal file
107
src/com/android/settings/dream/DreamAdapter.java
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.settings.dream;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.VectorDrawable;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settingslib.Utils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RecyclerView adapter which displays list of items for the user to select.
|
||||||
|
*/
|
||||||
|
class DreamAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
|
private final List<IDreamItem> mItemList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View holder for each {@link IDreamItem}.
|
||||||
|
*/
|
||||||
|
private static class DreamViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private final ImageView mIconView;
|
||||||
|
private final TextView mTitleView;
|
||||||
|
private final ImageView mPreviewView;
|
||||||
|
private final Button mCustomizeButton;
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
|
DreamViewHolder(View view, Context context) {
|
||||||
|
super(view);
|
||||||
|
mContext = context;
|
||||||
|
mPreviewView = view.findViewById(R.id.preview);
|
||||||
|
mIconView = view.findViewById(R.id.icon);
|
||||||
|
mTitleView = view.findViewById(R.id.title_text);
|
||||||
|
mCustomizeButton = view.findViewById(R.id.customize_button);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind the view at the given position, populating the view with the provided data.
|
||||||
|
*/
|
||||||
|
public void bindView(IDreamItem item) {
|
||||||
|
mTitleView.setText(item.getTitle());
|
||||||
|
mPreviewView.setImageDrawable(item.getPreviewImage());
|
||||||
|
|
||||||
|
final Drawable icon = item.getIcon();
|
||||||
|
if (icon instanceof VectorDrawable) {
|
||||||
|
icon.setTint(Utils.getColorAttrDefaultColor(mContext,
|
||||||
|
com.android.internal.R.attr.colorAccentPrimaryVariant));
|
||||||
|
}
|
||||||
|
mIconView.setImageDrawable(icon);
|
||||||
|
if (item.allowCustomization()) {
|
||||||
|
mCustomizeButton.setVisibility(View.VISIBLE);
|
||||||
|
mCustomizeButton.setOnClickListener(v -> item.onCustomizeClicked());
|
||||||
|
} else {
|
||||||
|
mCustomizeButton.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
itemView.setOnClickListener(v -> item.onItemClicked());
|
||||||
|
itemView.setActivated(item.isActive());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DreamAdapter(List<IDreamItem> itemList) {
|
||||||
|
mItemList = itemList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
|
||||||
|
View view = LayoutInflater.from(viewGroup.getContext())
|
||||||
|
.inflate(R.layout.dream_preference_layout, viewGroup, false);
|
||||||
|
return new DreamViewHolder(view, viewGroup.getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
|
||||||
|
((DreamViewHolder) viewHolder).bindView(mItemList.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mItemList.size();
|
||||||
|
}
|
||||||
|
}
|
@@ -1,129 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2022 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.settings.dream;
|
|
||||||
|
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.android.settings.R;
|
|
||||||
import com.android.settingslib.dream.DreamBackend.DreamInfo;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RecyclerView adapter which displays list of available dreams for the user to select.
|
|
||||||
*/
|
|
||||||
class DreamPickerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
|
||||||
private final List<DreamInfo> mDreamInfoList;
|
|
||||||
private final OnItemClickListener mItemClickListener;
|
|
||||||
private final OnItemClickListener mOnDreamSelected = new OnItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemClicked(DreamInfo dreamInfo) {
|
|
||||||
if (mItemClickListener != null) {
|
|
||||||
mItemClickListener.onItemClicked(dreamInfo);
|
|
||||||
}
|
|
||||||
mDreamInfoList.forEach(dream -> {
|
|
||||||
if (dream != null) {
|
|
||||||
dream.isActive = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
dreamInfo.isActive = true;
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private final OnItemClickListener mOnCustomizeListener;
|
|
||||||
|
|
||||||
interface OnItemClickListener {
|
|
||||||
void onItemClicked(DreamInfo dreamInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* View holder for each Dream service.
|
|
||||||
*/
|
|
||||||
private static class DreamViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
private final ImageView mIconView;
|
|
||||||
private final TextView mTitleView;
|
|
||||||
private final TextView mSummaryView;
|
|
||||||
private final ImageView mPreviewView;
|
|
||||||
private final Button mCustomizeButton;
|
|
||||||
|
|
||||||
DreamViewHolder(View view) {
|
|
||||||
super(view);
|
|
||||||
mPreviewView = view.findViewById(R.id.preview);
|
|
||||||
mIconView = view.findViewById(R.id.icon);
|
|
||||||
mTitleView = view.findViewById(R.id.title_text);
|
|
||||||
mSummaryView = view.findViewById(R.id.summary_text);
|
|
||||||
mCustomizeButton = view.findViewById(R.id.customize_button);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind the dream service view at the given position. Add details on the
|
|
||||||
* dream's icon, name and description.
|
|
||||||
*/
|
|
||||||
public void bindView(DreamInfo dreamInfo, OnItemClickListener clickListener,
|
|
||||||
OnItemClickListener customizeListener) {
|
|
||||||
mIconView.setImageDrawable(dreamInfo.icon);
|
|
||||||
mTitleView.setText(dreamInfo.caption);
|
|
||||||
mPreviewView.setImageDrawable(dreamInfo.previewImage);
|
|
||||||
mSummaryView.setText(dreamInfo.description);
|
|
||||||
itemView.setActivated(dreamInfo.isActive);
|
|
||||||
if (dreamInfo.isActive && dreamInfo.settingsComponentName != null) {
|
|
||||||
mCustomizeButton.setVisibility(View.VISIBLE);
|
|
||||||
mCustomizeButton.setOnClickListener(
|
|
||||||
v -> customizeListener.onItemClicked(dreamInfo));
|
|
||||||
} else {
|
|
||||||
mCustomizeButton.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
itemView.setOnClickListener(v -> clickListener.onItemClicked(dreamInfo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DreamPickerAdapter(List<DreamInfo> dreamInfos, OnItemClickListener clickListener,
|
|
||||||
OnItemClickListener onCustomizeListener) {
|
|
||||||
mDreamInfoList = dreamInfos;
|
|
||||||
mItemClickListener = clickListener;
|
|
||||||
mOnCustomizeListener = onCustomizeListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
|
|
||||||
View view = LayoutInflater.from(viewGroup.getContext())
|
|
||||||
.inflate(R.layout.dream_preference_layout, viewGroup, false);
|
|
||||||
return new DreamViewHolder(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
|
|
||||||
((DreamViewHolder) viewHolder).bindView(mDreamInfoList.get(i), mOnDreamSelected,
|
|
||||||
mOnCustomizeListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return mDreamInfoList.size();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -18,22 +18,23 @@ package com.android.settings.dream;
|
|||||||
|
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.BasePreferenceController;
|
import com.android.settings.core.BasePreferenceController;
|
||||||
import com.android.settings.dream.DreamPickerAdapter.OnItemClickListener;
|
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||||
import com.android.settingslib.dream.DreamBackend;
|
import com.android.settingslib.dream.DreamBackend;
|
||||||
import com.android.settingslib.widget.LayoutPreference;
|
import com.android.settingslib.widget.LayoutPreference;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for the dream picker where the user can select a screensaver.
|
* Controller for the dream picker where the user can select a screensaver.
|
||||||
@@ -44,32 +45,11 @@ public class DreamPickerController extends BasePreferenceController {
|
|||||||
private final DreamBackend mBackend;
|
private final DreamBackend mBackend;
|
||||||
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
||||||
private final List<DreamBackend.DreamInfo> mDreamInfos;
|
private final List<DreamBackend.DreamInfo> mDreamInfos;
|
||||||
|
private final Drawable mActiveDrawable;
|
||||||
private Button mPreviewButton;
|
private Button mPreviewButton;
|
||||||
@Nullable
|
@Nullable
|
||||||
private DreamBackend.DreamInfo mActiveDream;
|
private DreamBackend.DreamInfo mActiveDream;
|
||||||
|
private DreamAdapter mAdapter;
|
||||||
private final OnItemClickListener mItemClickListener =
|
|
||||||
new OnItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemClicked(DreamBackend.DreamInfo dreamInfo) {
|
|
||||||
mActiveDream = dreamInfo;
|
|
||||||
mMetricsFeatureProvider.action(
|
|
||||||
mContext,
|
|
||||||
SettingsEnums.ACTION_DREAM_SELECT_TYPE,
|
|
||||||
mActiveDream == null ? null
|
|
||||||
: mActiveDream.componentName.flattenToString());
|
|
||||||
mBackend.setActiveDream(
|
|
||||||
mActiveDream == null ? null : mActiveDream.componentName);
|
|
||||||
updatePreviewButtonState();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final OnItemClickListener mCustomizeListener = new OnItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemClicked(DreamBackend.DreamInfo dreamInfo) {
|
|
||||||
mBackend.launchSettings(mContext, dreamInfo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public DreamPickerController(Context context, String preferenceKey) {
|
public DreamPickerController(Context context, String preferenceKey) {
|
||||||
this(context, preferenceKey, DreamBackend.getInstance(context));
|
this(context, preferenceKey, DreamBackend.getInstance(context));
|
||||||
@@ -79,6 +59,7 @@ public class DreamPickerController extends BasePreferenceController {
|
|||||||
super(context, preferenceKey);
|
super(context, preferenceKey);
|
||||||
mBackend = backend;
|
mBackend = backend;
|
||||||
mDreamInfos = mBackend.getDreamInfos();
|
mDreamInfos = mBackend.getDreamInfos();
|
||||||
|
mActiveDrawable = context.getDrawable(R.drawable.ic_dream_check_circle);
|
||||||
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,15 +79,17 @@ public class DreamPickerController extends BasePreferenceController {
|
|||||||
|
|
||||||
mActiveDream = getActiveDreamInfo();
|
mActiveDream = getActiveDreamInfo();
|
||||||
|
|
||||||
final DreamPickerAdapter adapter =
|
mAdapter = new DreamAdapter(mDreamInfos.stream()
|
||||||
new DreamPickerAdapter(mDreamInfos, mItemClickListener, mCustomizeListener);
|
.map(DreamItem::new)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
|
||||||
final RecyclerView recyclerView =
|
final RecyclerView recyclerView =
|
||||||
((LayoutPreference) preference).findViewById(R.id.dream_list);
|
((LayoutPreference) preference).findViewById(R.id.dream_list);
|
||||||
recyclerView.setLayoutManager(new AutoFitGridLayoutManager(mContext));
|
recyclerView.setLayoutManager(new AutoFitGridLayoutManager(mContext));
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(mAdapter);
|
||||||
|
|
||||||
mPreviewButton = ((LayoutPreference) preference).findViewById(R.id.preview_button);
|
mPreviewButton = ((LayoutPreference) preference).findViewById(R.id.preview_button);
|
||||||
|
mPreviewButton.setVisibility(View.VISIBLE);
|
||||||
mPreviewButton.setOnClickListener(v -> mBackend.preview(mActiveDream));
|
mPreviewButton.setOnClickListener(v -> mBackend.preview(mActiveDream));
|
||||||
updatePreviewButtonState();
|
updatePreviewButtonState();
|
||||||
}
|
}
|
||||||
@@ -126,23 +109,56 @@ public class DreamPickerController extends BasePreferenceController {
|
|||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Grid layout manager that calculates the number of columns for the screen size. */
|
private class DreamItem implements IDreamItem {
|
||||||
private static final class AutoFitGridLayoutManager extends GridLayoutManager {
|
DreamBackend.DreamInfo mDreamInfo;
|
||||||
private final float mColumnWidth;
|
|
||||||
|
|
||||||
AutoFitGridLayoutManager(Context context) {
|
DreamItem(DreamBackend.DreamInfo dreamInfo) {
|
||||||
super(context, /* spanCount= */ 1);
|
mDreamInfo = dreamInfo;
|
||||||
this.mColumnWidth = context
|
|
||||||
.getResources()
|
|
||||||
.getDimensionPixelSize(R.dimen.dream_item_min_column_width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
public CharSequence getTitle() {
|
||||||
final int totalSpace = getWidth() - getPaddingRight() - getPaddingLeft();
|
return mDreamInfo.caption;
|
||||||
final int spanCount = Math.max(1, (int) (totalSpace / mColumnWidth));
|
}
|
||||||
setSpanCount(spanCount);
|
|
||||||
super.onLayoutChildren(recycler, state);
|
@Override
|
||||||
|
public Drawable getIcon() {
|
||||||
|
return isActive() ? mActiveDrawable : mDreamInfo.icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemClicked() {
|
||||||
|
mActiveDream = mDreamInfo;
|
||||||
|
mBackend.setActiveDream(mDreamInfo.componentName);
|
||||||
|
mAdapter.notifyDataSetChanged();
|
||||||
|
updatePreviewButtonState();
|
||||||
|
mMetricsFeatureProvider.action(
|
||||||
|
mContext,
|
||||||
|
SettingsEnums.ACTION_DREAM_SELECT_TYPE,
|
||||||
|
mDreamInfo.componentName.flattenToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCustomizeClicked() {
|
||||||
|
mBackend.launchSettings(mContext, mDreamInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Drawable getPreviewImage() {
|
||||||
|
return mDreamInfo.previewImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
if (mActiveDream == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return mDreamInfo.componentName.equals(mActiveDream.componentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowCustomization() {
|
||||||
|
return isActive() && mDreamInfo.settingsComponentName != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
35
src/com/android/settings/dream/IDreamItem.java
Normal file
35
src/com/android/settings/dream/IDreamItem.java
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.settings.dream;
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
interface IDreamItem {
|
||||||
|
CharSequence getTitle();
|
||||||
|
|
||||||
|
Drawable getIcon();
|
||||||
|
|
||||||
|
void onItemClicked();
|
||||||
|
|
||||||
|
void onCustomizeClicked();
|
||||||
|
|
||||||
|
Drawable getPreviewImage();
|
||||||
|
|
||||||
|
boolean isActive();
|
||||||
|
|
||||||
|
boolean allowCustomization();
|
||||||
|
}
|
Reference in New Issue
Block a user