cfcf2255dc
This causes app pairs to log an error message if creation or icon inflation is attempted with contents != 2. App pairs with wrong numbers of members should not be created anymore. Fixes: 317283244 Fixes: 322892793 Test: Manual Flag: ACONFIG com.android.wm.shell.enable_app_pairs TEAMFOOD Change-Id: I5e454042719bb67187f900c546380bb44cfc34ac
171 lines
5.7 KiB
Java
171 lines
5.7 KiB
Java
/*
|
|
* Copyright (C) 2023 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.launcher3.apppairs;
|
|
|
|
import android.content.Context;
|
|
import android.graphics.Rect;
|
|
import android.util.AttributeSet;
|
|
import android.util.Log;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.FrameLayout;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import com.android.launcher3.BubbleTextView;
|
|
import com.android.launcher3.DeviceProfile;
|
|
import com.android.launcher3.R;
|
|
import com.android.launcher3.Reorderable;
|
|
import com.android.launcher3.dragndrop.DraggableView;
|
|
import com.android.launcher3.model.data.FolderInfo;
|
|
import com.android.launcher3.util.MultiTranslateDelegate;
|
|
import com.android.launcher3.views.ActivityContext;
|
|
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
|
|
/**
|
|
* A {@link android.widget.FrameLayout} used to represent an app pair icon on the workspace.
|
|
* <br>
|
|
* The app pair icon is two parallel background rectangles with rounded corners. Icons of the two
|
|
* member apps are set into these rectangles.
|
|
*/
|
|
public class AppPairIcon extends FrameLayout implements DraggableView, Reorderable {
|
|
private static final String TAG = "AppPairIcon";
|
|
|
|
// A view that holds the app pair icon graphic.
|
|
private AppPairIconGraphic mIconGraphic;
|
|
// A view that holds the app pair's title.
|
|
private BubbleTextView mAppPairName;
|
|
// The underlying ItemInfo that stores info about the app pair members, etc.
|
|
private FolderInfo mInfo;
|
|
|
|
// Required for Reorderable -- handles translation and bouncing movements
|
|
private final MultiTranslateDelegate mTranslateDelegate = new MultiTranslateDelegate(this);
|
|
private float mScaleForReorderBounce = 1f;
|
|
|
|
public AppPairIcon(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
}
|
|
|
|
public AppPairIcon(Context context) {
|
|
super(context);
|
|
}
|
|
|
|
/**
|
|
* Builds an AppPairIcon to be added to the Launcher.
|
|
*/
|
|
public static AppPairIcon inflateIcon(int resId, ActivityContext activity,
|
|
@Nullable ViewGroup group, FolderInfo appPairInfo) {
|
|
DeviceProfile grid = activity.getDeviceProfile();
|
|
LayoutInflater inflater = (group != null)
|
|
? LayoutInflater.from(group.getContext())
|
|
: activity.getLayoutInflater();
|
|
AppPairIcon icon = (AppPairIcon) inflater.inflate(resId, group, false);
|
|
|
|
// Sort contents, so that left-hand app comes first
|
|
Collections.sort(appPairInfo.contents, Comparator.comparingInt(a -> a.rank));
|
|
|
|
icon.setClipToPadding(false);
|
|
icon.setTag(appPairInfo);
|
|
icon.setOnClickListener(activity.getItemOnClickListener());
|
|
icon.mInfo = appPairInfo;
|
|
|
|
// Set up icon drawable area
|
|
icon.mIconGraphic = icon.findViewById(R.id.app_pair_icon_graphic);
|
|
icon.mIconGraphic.init(activity.getDeviceProfile(), icon);
|
|
|
|
// Set up app pair title
|
|
icon.mAppPairName = icon.findViewById(R.id.app_pair_icon_name);
|
|
icon.mAppPairName.setCompoundDrawablePadding(0);
|
|
FrameLayout.LayoutParams lp =
|
|
(FrameLayout.LayoutParams) icon.mAppPairName.getLayoutParams();
|
|
lp.topMargin = grid.iconSizePx + grid.iconDrawablePaddingPx;
|
|
icon.mAppPairName.setText(appPairInfo.title);
|
|
|
|
// Set up accessibility
|
|
icon.setContentDescription(icon.getAccessibilityTitle(appPairInfo));
|
|
icon.setAccessibilityDelegate(activity.getAccessibilityDelegate());
|
|
|
|
return icon;
|
|
}
|
|
|
|
/**
|
|
* Returns a formatted accessibility title for app pairs.
|
|
*/
|
|
public String getAccessibilityTitle(FolderInfo appPairInfo) {
|
|
if (appPairInfo.contents.size() != 2) {
|
|
Log.wtf(TAG, "AppPair contents not 2, size: " + appPairInfo.contents.size());
|
|
return "";
|
|
}
|
|
|
|
CharSequence app1 = appPairInfo.contents.get(0).title;
|
|
CharSequence app2 = appPairInfo.contents.get(1).title;
|
|
return getContext().getString(R.string.app_pair_name_format, app1, app2);
|
|
}
|
|
|
|
// Required for DraggableView
|
|
@Override
|
|
public int getViewType() {
|
|
return DRAGGABLE_ICON;
|
|
}
|
|
|
|
// Required for DraggableView
|
|
@Override
|
|
public void getWorkspaceVisualDragBounds(Rect outBounds) {
|
|
mIconGraphic.getIconBounds(outBounds);
|
|
}
|
|
|
|
/** Sets the visibility of the icon's title text */
|
|
public void setTextVisible(boolean visible) {
|
|
if (visible) {
|
|
mAppPairName.setVisibility(VISIBLE);
|
|
} else {
|
|
mAppPairName.setVisibility(INVISIBLE);
|
|
}
|
|
}
|
|
|
|
// Required for Reorderable
|
|
@Override
|
|
public MultiTranslateDelegate getTranslateDelegate() {
|
|
return mTranslateDelegate;
|
|
}
|
|
|
|
// Required for Reorderable
|
|
@Override
|
|
public void setReorderBounceScale(float scale) {
|
|
mScaleForReorderBounce = scale;
|
|
super.setScaleX(scale);
|
|
super.setScaleY(scale);
|
|
}
|
|
|
|
// Required for Reorderable
|
|
@Override
|
|
public float getReorderBounceScale() {
|
|
return mScaleForReorderBounce;
|
|
}
|
|
|
|
public FolderInfo getInfo() {
|
|
return mInfo;
|
|
}
|
|
|
|
public View getIconDrawableArea() {
|
|
return mIconGraphic;
|
|
}
|
|
}
|