Adding support for launcher preview generation
Creating a utility class which generates a launcher preview for a provided InvariantDeviceProfile Bug: 118758696 Change-Id: I0aebeb6eed37f72edd1cc305e58eece305aae3ff
This commit is contained in:
parent
aa576bce02
commit
ef92b82778
|
@ -132,6 +132,16 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<!-- TODO: Remove -->
|
||||||
|
<activity android:name="com.android.launcher3.util.MyActivity"
|
||||||
|
android:theme="@style/AppTheme">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Should point to the content provider which can be used to dump Launcher3 compatible
|
Should point to the content provider which can be used to dump Launcher3 compatible
|
||||||
worspace configuration to the dump's file descriptor by using launcher_dump.proto
|
worspace configuration to the dump's file descriptor by using launcher_dump.proto
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2018 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.
|
||||||
|
-->
|
||||||
|
<com.android.launcher3.InsettableFrameLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:launcher="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.android.launcher3.CellLayout
|
||||||
|
android:id="@+id/workspace"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="top|left"
|
||||||
|
android:theme="@style/HomeScreenElementTheme"
|
||||||
|
launcher:containerType="workspace"
|
||||||
|
launcher:pageIndicator="@+id/page_indicator"/>
|
||||||
|
|
||||||
|
<com.android.launcher3.Hotseat
|
||||||
|
android:id="@+id/hotseat"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:theme="@style/HomeScreenElementTheme"
|
||||||
|
launcher:containerType="hotseat" />
|
||||||
|
|
||||||
|
<com.android.launcher3.InsettableFrameLayout
|
||||||
|
android:id="@+id/apps_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" >
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@id/search_container_all_apps"
|
||||||
|
layout="@layout/search_container_all_apps"/>
|
||||||
|
|
||||||
|
</com.android.launcher3.InsettableFrameLayout>
|
||||||
|
|
||||||
|
</com.android.launcher3.InsettableFrameLayout>
|
|
@ -148,4 +148,9 @@
|
||||||
<attr name="numMinRows" format="integer" />
|
<attr name="numMinRows" format="integer" />
|
||||||
<attr name="numMinColumns" format="integer" />
|
<attr name="numMinColumns" format="integer" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
|
<declare-styleable name="PreviewFragment">
|
||||||
|
<attr name="android:name" />
|
||||||
|
<attr name="android:id" />
|
||||||
|
</declare-styleable>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -66,6 +66,8 @@
|
||||||
<string name="all_apps_no_search_results">No apps found matching \"<xliff:g id="query" example="Android">%1$s</xliff:g>\"</string>
|
<string name="all_apps_no_search_results">No apps found matching \"<xliff:g id="query" example="Android">%1$s</xliff:g>\"</string>
|
||||||
<!-- Label for the button which allows the user to get app search results. [CHAR_LIMIT=50] -->
|
<!-- Label for the button which allows the user to get app search results. [CHAR_LIMIT=50] -->
|
||||||
<string name="all_apps_search_market_message">Search for more apps</string>
|
<string name="all_apps_search_market_message">Search for more apps</string>
|
||||||
|
<!-- Label for an icon representing any generic app. [CHAR_LIMIT=50] -->
|
||||||
|
<string name="label_application">App</string>
|
||||||
|
|
||||||
<!-- Popup items -->
|
<!-- Popup items -->
|
||||||
<!-- Text to display as the header above notifications. [CHAR_LIMIT=30] -->
|
<!-- Text to display as the header above notifications. [CHAR_LIMIT=30] -->
|
||||||
|
|
|
@ -204,4 +204,13 @@ public class ItemInfo {
|
||||||
public boolean isDisabled() {
|
public boolean isDisabled() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getViewId() {
|
||||||
|
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
|
||||||
|
// This cast is safe as long as the id < 0x00FFFFFF
|
||||||
|
// Since we jail all the dynamically generated views, there should be no clashes
|
||||||
|
// with any other views.
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -460,14 +460,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||||
return !isWorkspaceLoading();
|
return !isWorkspaceLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getViewIdForItem(ItemInfo info) {
|
|
||||||
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
|
|
||||||
// This cast is safe as long as the id < 0x00FFFFFF
|
|
||||||
// Since we jail all the dynamically generated views, there should be no clashes
|
|
||||||
// with any other views.
|
|
||||||
return (int) info.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PopupDataProvider getPopupDataProvider() {
|
public PopupDataProvider getPopupDataProvider() {
|
||||||
return mPopupDataProvider;
|
return mPopupDataProvider;
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,6 @@ import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||||
import com.android.launcher3.pageindicators.WorkspacePageIndicator;
|
import com.android.launcher3.pageindicators.WorkspacePageIndicator;
|
||||||
import com.android.launcher3.popup.PopupContainerWithArrow;
|
import com.android.launcher3.popup.PopupContainerWithArrow;
|
||||||
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
|
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
|
||||||
import com.android.launcher3.touch.ItemLongClickListener;
|
|
||||||
import com.android.launcher3.touch.WorkspaceTouchListener;
|
import com.android.launcher3.touch.WorkspaceTouchListener;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||||
|
@ -107,8 +106,8 @@ import java.util.Set;
|
||||||
*/
|
*/
|
||||||
public class Workspace extends PagedView<WorkspacePageIndicator>
|
public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
implements DropTarget, DragSource, View.OnTouchListener,
|
implements DropTarget, DragSource, View.OnTouchListener,
|
||||||
DragController.DragListener, Insettable, LauncherStateManager.StateHandler {
|
DragController.DragListener, Insettable, LauncherStateManager.StateHandler,
|
||||||
private static final String TAG = "Launcher.Workspace";
|
WorkspaceLayoutManager {
|
||||||
|
|
||||||
/** The value that {@link #mTransitionProgress} must be greater than for
|
/** The value that {@link #mTransitionProgress} must be greater than for
|
||||||
* {@link #transitionStateShouldAllowDrop()} to return true. */
|
* {@link #transitionStateShouldAllowDrop()} to return true. */
|
||||||
|
@ -130,11 +129,6 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
public static final boolean MAP_NO_RECURSE = false;
|
public static final boolean MAP_NO_RECURSE = false;
|
||||||
public static final boolean MAP_RECURSE = true;
|
public static final boolean MAP_RECURSE = true;
|
||||||
|
|
||||||
// The screen id used for the empty screen always present to the right.
|
|
||||||
public static final int EXTRA_EMPTY_SCREEN_ID = -201;
|
|
||||||
// The is the first screen. It is always present, even if its empty.
|
|
||||||
public static final int FIRST_SCREEN_ID = 0;
|
|
||||||
|
|
||||||
private LayoutTransition mLayoutTransition;
|
private LayoutTransition mLayoutTransition;
|
||||||
@Thunk final WallpaperManager mWallpaperManager;
|
@Thunk final WallpaperManager mWallpaperManager;
|
||||||
|
|
||||||
|
@ -740,6 +734,17 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
return newId;
|
return newId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Hotseat getHotseat() {
|
||||||
|
return mLauncher.getHotseat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAddDropTarget(DropTarget target) {
|
||||||
|
mDragController.addDropTarget(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public CellLayout getScreenWithId(int screenId) {
|
public CellLayout getScreenWithId(int screenId) {
|
||||||
return mWorkspaceScreens.get(screenId);
|
return mWorkspaceScreens.get(screenId);
|
||||||
}
|
}
|
||||||
|
@ -835,107 +840,6 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* At bind time, we use the rank (screenId) to compute x and y for hotseat items.
|
|
||||||
* See {@link #addInScreen}.
|
|
||||||
*/
|
|
||||||
public void addInScreenFromBind(View child, ItemInfo info) {
|
|
||||||
int x = info.cellX;
|
|
||||||
int y = info.cellY;
|
|
||||||
if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
|
|
||||||
int screenId = (int) info.screenId;
|
|
||||||
x = mLauncher.getHotseat().getCellXFromOrder(screenId);
|
|
||||||
y = mLauncher.getHotseat().getCellYFromOrder(screenId);
|
|
||||||
}
|
|
||||||
addInScreen(child, info.container, info.screenId, x, y, info.spanX, info.spanY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the specified child in the specified screen based on the {@param info}
|
|
||||||
* See {@link #addInScreen(View, int, int, int, int, int, int)}.
|
|
||||||
*/
|
|
||||||
public void addInScreen(View child, ItemInfo info) {
|
|
||||||
addInScreen(child, info.container, info.screenId, info.cellX, info.cellY,
|
|
||||||
info.spanX, info.spanY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the specified child in the specified screen. The position and dimension of
|
|
||||||
* the child are defined by x, y, spanX and spanY.
|
|
||||||
*
|
|
||||||
* @param child The child to add in one of the workspace's screens.
|
|
||||||
* @param screenId The screen in which to add the child.
|
|
||||||
* @param x The X position of the child in the screen's grid.
|
|
||||||
* @param y The Y position of the child in the screen's grid.
|
|
||||||
* @param spanX The number of cells spanned horizontally by the child.
|
|
||||||
* @param spanY The number of cells spanned vertically by the child.
|
|
||||||
*/
|
|
||||||
private void addInScreen(View child, int container, int screenId, int x, int y,
|
|
||||||
int spanX, int spanY) {
|
|
||||||
if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
|
|
||||||
if (getScreenWithId(screenId) == null) {
|
|
||||||
Log.e(TAG, "Skipping child, screenId " + screenId + " not found");
|
|
||||||
// DEBUGGING - Print out the stack trace to see where we are adding from
|
|
||||||
new Throwable().printStackTrace();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (screenId == EXTRA_EMPTY_SCREEN_ID) {
|
|
||||||
// This should never happen
|
|
||||||
throw new RuntimeException("Screen id should not be EXTRA_EMPTY_SCREEN_ID");
|
|
||||||
}
|
|
||||||
|
|
||||||
final CellLayout layout;
|
|
||||||
if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
|
|
||||||
layout = mLauncher.getHotseat();
|
|
||||||
|
|
||||||
// Hide folder title in the hotseat
|
|
||||||
if (child instanceof FolderIcon) {
|
|
||||||
((FolderIcon) child).setTextVisible(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Show folder title if not in the hotseat
|
|
||||||
if (child instanceof FolderIcon) {
|
|
||||||
((FolderIcon) child).setTextVisible(true);
|
|
||||||
}
|
|
||||||
layout = getScreenWithId(screenId);
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewGroup.LayoutParams genericLp = child.getLayoutParams();
|
|
||||||
CellLayout.LayoutParams lp;
|
|
||||||
if (genericLp == null || !(genericLp instanceof CellLayout.LayoutParams)) {
|
|
||||||
lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
|
|
||||||
} else {
|
|
||||||
lp = (CellLayout.LayoutParams) genericLp;
|
|
||||||
lp.cellX = x;
|
|
||||||
lp.cellY = y;
|
|
||||||
lp.cellHSpan = spanX;
|
|
||||||
lp.cellVSpan = spanY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spanX < 0 && spanY < 0) {
|
|
||||||
lp.isLockedToGrid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the canonical child id to uniquely represent this view in this screen
|
|
||||||
ItemInfo info = (ItemInfo) child.getTag();
|
|
||||||
int childId = mLauncher.getViewIdForItem(info);
|
|
||||||
|
|
||||||
boolean markCellsAsOccupied = !(child instanceof Folder);
|
|
||||||
if (!layout.addViewToCellLayout(child, -1, childId, lp, markCellsAsOccupied)) {
|
|
||||||
// TODO: This branch occurs when the workspace is adding views
|
|
||||||
// outside of the defined grid
|
|
||||||
// maybe we should be deleting these items from the LauncherModel?
|
|
||||||
Log.e(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
|
|
||||||
}
|
|
||||||
|
|
||||||
child.setHapticFeedbackEnabled(false);
|
|
||||||
child.setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE);
|
|
||||||
if (child instanceof DropTarget) {
|
|
||||||
mDragController.addDropTarget((DropTarget) child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called directly from a CellLayout (not by the framework), after we've been added as a
|
* Called directly from a CellLayout (not by the framework), after we've been added as a
|
||||||
* listener via setOnInterceptTouchEventListener(). This allows us to tell the CellLayout
|
* listener via setOnInterceptTouchEventListener(). This allows us to tell the CellLayout
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.android.launcher3.folder.Folder;
|
||||||
|
import com.android.launcher3.folder.FolderIcon;
|
||||||
|
import com.android.launcher3.touch.ItemLongClickListener;
|
||||||
|
|
||||||
|
public interface WorkspaceLayoutManager {
|
||||||
|
|
||||||
|
String TAG = "Launcher.Workspace";
|
||||||
|
|
||||||
|
// The screen id used for the empty screen always present to the right.
|
||||||
|
int EXTRA_EMPTY_SCREEN_ID = -201;
|
||||||
|
// The is the first screen. It is always present, even if its empty.
|
||||||
|
int FIRST_SCREEN_ID = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* At bind time, we use the rank (screenId) to compute x and y for hotseat items.
|
||||||
|
* See {@link #addInScreen}.
|
||||||
|
*/
|
||||||
|
default void addInScreenFromBind(View child, ItemInfo info) {
|
||||||
|
int x = info.cellX;
|
||||||
|
int y = info.cellY;
|
||||||
|
if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
|
||||||
|
int screenId = info.screenId;
|
||||||
|
x = getHotseat().getCellXFromOrder(screenId);
|
||||||
|
y = getHotseat().getCellYFromOrder(screenId);
|
||||||
|
}
|
||||||
|
addInScreen(child, info.container, info.screenId, x, y, info.spanX, info.spanY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the specified child in the specified screen based on the {@param info}
|
||||||
|
* See {@link #addInScreen(View, int, int, int, int, int, int)}.
|
||||||
|
*/
|
||||||
|
default void addInScreen(View child, ItemInfo info) {
|
||||||
|
addInScreen(child, info.container, info.screenId, info.cellX, info.cellY,
|
||||||
|
info.spanX, info.spanY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the specified child in the specified screen. The position and dimension of
|
||||||
|
* the child are defined by x, y, spanX and spanY.
|
||||||
|
*
|
||||||
|
* @param child The child to add in one of the workspace's screens.
|
||||||
|
* @param screenId The screen in which to add the child.
|
||||||
|
* @param x The X position of the child in the screen's grid.
|
||||||
|
* @param y The Y position of the child in the screen's grid.
|
||||||
|
* @param spanX The number of cells spanned horizontally by the child.
|
||||||
|
* @param spanY The number of cells spanned vertically by the child.
|
||||||
|
*/
|
||||||
|
default void addInScreen(View child, int container, int screenId, int x, int y,
|
||||||
|
int spanX, int spanY) {
|
||||||
|
if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
|
||||||
|
if (getScreenWithId(screenId) == null) {
|
||||||
|
Log.e(TAG, "Skipping child, screenId " + screenId + " not found");
|
||||||
|
// DEBUGGING - Print out the stack trace to see where we are adding from
|
||||||
|
new Throwable().printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (screenId == EXTRA_EMPTY_SCREEN_ID) {
|
||||||
|
// This should never happen
|
||||||
|
throw new RuntimeException("Screen id should not be EXTRA_EMPTY_SCREEN_ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
final CellLayout layout;
|
||||||
|
if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
|
||||||
|
layout = getHotseat();
|
||||||
|
|
||||||
|
// Hide folder title in the hotseat
|
||||||
|
if (child instanceof FolderIcon) {
|
||||||
|
((FolderIcon) child).setTextVisible(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Show folder title if not in the hotseat
|
||||||
|
if (child instanceof FolderIcon) {
|
||||||
|
((FolderIcon) child).setTextVisible(true);
|
||||||
|
}
|
||||||
|
layout = getScreenWithId(screenId);
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewGroup.LayoutParams genericLp = child.getLayoutParams();
|
||||||
|
CellLayout.LayoutParams lp;
|
||||||
|
if (genericLp == null || !(genericLp instanceof CellLayout.LayoutParams)) {
|
||||||
|
lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
|
||||||
|
} else {
|
||||||
|
lp = (CellLayout.LayoutParams) genericLp;
|
||||||
|
lp.cellX = x;
|
||||||
|
lp.cellY = y;
|
||||||
|
lp.cellHSpan = spanX;
|
||||||
|
lp.cellVSpan = spanY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spanX < 0 && spanY < 0) {
|
||||||
|
lp.isLockedToGrid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the canonical child id to uniquely represent this view in this screen
|
||||||
|
ItemInfo info = (ItemInfo) child.getTag();
|
||||||
|
int childId = info.getViewId();
|
||||||
|
|
||||||
|
boolean markCellsAsOccupied = !(child instanceof Folder);
|
||||||
|
if (!layout.addViewToCellLayout(child, -1, childId, lp, markCellsAsOccupied)) {
|
||||||
|
// TODO: This branch occurs when the workspace is adding views
|
||||||
|
// outside of the defined grid
|
||||||
|
// maybe we should be deleting these items from the LauncherModel?
|
||||||
|
Log.e(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
|
||||||
|
}
|
||||||
|
|
||||||
|
child.setHapticFeedbackEnabled(false);
|
||||||
|
child.setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE);
|
||||||
|
if (child instanceof DropTarget) {
|
||||||
|
onAddDropTarget((DropTarget) child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Hotseat getHotseat();
|
||||||
|
|
||||||
|
CellLayout getScreenWithId(int screenId);
|
||||||
|
|
||||||
|
default void onAddDropTarget(DropTarget target) { }
|
||||||
|
}
|
|
@ -225,8 +225,7 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
|
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
|
||||||
lp.cellX = item.cellX;
|
lp.cellX = item.cellX;
|
||||||
lp.cellY = item.cellY;
|
lp.cellY = item.cellY;
|
||||||
getPageAt(pageNo).addViewToCellLayout(
|
getPageAt(pageNo).addViewToCellLayout(view, -1, item.getViewId(), lp, true);
|
||||||
view, -1, mFolder.mLauncher.getViewIdForItem(item), lp, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
|
@ -351,8 +350,7 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||||
}
|
}
|
||||||
lp.cellX = info.cellX;
|
lp.cellX = info.cellX;
|
||||||
lp.cellY = info.cellY;
|
lp.cellY = info.cellY;
|
||||||
currentPage.addViewToCellLayout(
|
currentPage.addViewToCellLayout(v, -1, info.getViewId(), lp, true);
|
||||||
v, -1, mFolder.mLauncher.getViewIdForItem(info), lp, true);
|
|
||||||
|
|
||||||
if (verifier.isItemInPreview(rank) && v instanceof BubbleTextView) {
|
if (verifier.isItemInPreview(rank) && v instanceof BubbleTextView) {
|
||||||
((BubbleTextView) v).verifyHighRes();
|
((BubbleTextView) v).verifyHighRes();
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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.graphics;
|
||||||
|
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension of fragment, with support for preview mode.
|
||||||
|
*/
|
||||||
|
public class FragmentWithPreview extends Fragment {
|
||||||
|
|
||||||
|
private Context mPreviewContext;
|
||||||
|
|
||||||
|
public final void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
onInit(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onInit(Bundle savedInstanceState) { }
|
||||||
|
|
||||||
|
|
||||||
|
public Context getContext() {
|
||||||
|
return mPreviewContext != null ? mPreviewContext : getActivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
void enterPreviewMode(Context context) {
|
||||||
|
mPreviewContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInPreviewMode() {
|
||||||
|
return mPreviewContext != null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,292 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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.graphics;
|
||||||
|
|
||||||
|
import static android.view.View.MeasureSpec.EXACTLY;
|
||||||
|
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||||
|
import static android.view.View.VISIBLE;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.drawable.AdaptiveIconDrawable;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.Process;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.ContextThemeWrapper;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextClock;
|
||||||
|
|
||||||
|
import com.android.launcher3.BubbleTextView;
|
||||||
|
import com.android.launcher3.CellLayout;
|
||||||
|
import com.android.launcher3.DeviceProfile;
|
||||||
|
import com.android.launcher3.Hotseat;
|
||||||
|
import com.android.launcher3.InsettableFrameLayout;
|
||||||
|
import com.android.launcher3.InvariantDeviceProfile;
|
||||||
|
import com.android.launcher3.LauncherSettings.Favorites;
|
||||||
|
import com.android.launcher3.R;
|
||||||
|
import com.android.launcher3.ShortcutInfo;
|
||||||
|
import com.android.launcher3.Utilities;
|
||||||
|
import com.android.launcher3.WorkspaceLayoutManager;
|
||||||
|
import com.android.launcher3.allapps.SearchUiManager;
|
||||||
|
import com.android.launcher3.config.FeatureFlags;
|
||||||
|
import com.android.launcher3.icons.BaseIconFactory;
|
||||||
|
import com.android.launcher3.icons.BitmapInfo;
|
||||||
|
import com.android.launcher3.icons.BitmapRenderer;
|
||||||
|
import com.android.launcher3.views.ActivityContext;
|
||||||
|
import com.android.launcher3.views.BaseDragLayer;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for generating the preview of Launcher for a given InvariantDeviceProfile.
|
||||||
|
* Steps:
|
||||||
|
* 1) Create a dummy icon info with just white icon
|
||||||
|
* 2) Inflate a strip down layout definition for Launcher
|
||||||
|
* 3) Place appropriate elements like icons and first-page qsb
|
||||||
|
* 4) Measure and draw the view on a canvas
|
||||||
|
*/
|
||||||
|
@TargetApi(Build.VERSION_CODES.O)
|
||||||
|
public class LauncherPreviewRenderer {
|
||||||
|
|
||||||
|
private static final String TAG = "LauncherPreviewRenderer";
|
||||||
|
|
||||||
|
private final Handler mUiHandler;
|
||||||
|
private final Context mContext;
|
||||||
|
private final InvariantDeviceProfile mIdp;
|
||||||
|
private final DeviceProfile mDp;
|
||||||
|
private final Rect mInsets;
|
||||||
|
|
||||||
|
private final ShortcutInfo mShortcutInfo;
|
||||||
|
|
||||||
|
public LauncherPreviewRenderer(Context context, InvariantDeviceProfile idp) {
|
||||||
|
mUiHandler = new Handler(Looper.getMainLooper());
|
||||||
|
mContext = context;
|
||||||
|
mIdp = idp;
|
||||||
|
mDp = idp.portraitProfile.copy(context);
|
||||||
|
|
||||||
|
// TODO: get correct insets once display cutout API is available.
|
||||||
|
mInsets = new Rect();
|
||||||
|
mInsets.left = mInsets.right = (mDp.widthPx - mDp.availableWidthPx) / 2;
|
||||||
|
mInsets.top = mInsets.bottom = (mDp.heightPx - mDp.availableHeightPx) / 2;
|
||||||
|
mDp.updateInsets(mInsets);
|
||||||
|
|
||||||
|
BaseIconFactory iconFactory =
|
||||||
|
new BaseIconFactory(context, mIdp.fillResIconDpi, mIdp.iconBitmapSize) { };
|
||||||
|
BitmapInfo iconInfo = iconFactory.createBadgedIconBitmap(new AdaptiveIconDrawable(
|
||||||
|
new ColorDrawable(Color.WHITE), new ColorDrawable(Color.WHITE)),
|
||||||
|
Process.myUserHandle(),
|
||||||
|
Build.VERSION.SDK_INT);
|
||||||
|
|
||||||
|
mShortcutInfo = new ShortcutInfo();
|
||||||
|
mShortcutInfo.applyFrom(iconInfo);
|
||||||
|
mShortcutInfo.intent = new Intent();
|
||||||
|
mShortcutInfo.contentDescription = mShortcutInfo.title =
|
||||||
|
context.getString(R.string.label_application);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bitmap createScreenShot() {
|
||||||
|
return BitmapRenderer.createHardwareBitmap(mDp.widthPx, mDp.heightPx, c -> {
|
||||||
|
|
||||||
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||||
|
new MainThreadRenderer(mContext).renderScreenShot(c);
|
||||||
|
} else {
|
||||||
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
Utilities.postAsyncCallback(mUiHandler, () -> {
|
||||||
|
new MainThreadRenderer(mContext).renderScreenShot(c);
|
||||||
|
latch.countDown();
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
latch.await();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error drawing on main thread", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MainThreadRenderer extends ContextThemeWrapper
|
||||||
|
implements ActivityContext, WorkspaceLayoutManager, LayoutInflater.Factory2 {
|
||||||
|
|
||||||
|
private final LayoutInflater mHomeElementInflater;
|
||||||
|
private final InsettableFrameLayout mRootView;
|
||||||
|
|
||||||
|
private final Hotseat mHotseat;
|
||||||
|
private final CellLayout mWorkspace;
|
||||||
|
|
||||||
|
MainThreadRenderer(Context context) {
|
||||||
|
super(context, R.style.AppTheme);
|
||||||
|
|
||||||
|
mHomeElementInflater = LayoutInflater.from(
|
||||||
|
new ContextThemeWrapper(this, R.style.HomeScreenElementTheme));
|
||||||
|
mHomeElementInflater.setFactory2(this);
|
||||||
|
|
||||||
|
mRootView = (InsettableFrameLayout) mHomeElementInflater.inflate(
|
||||||
|
R.layout.launcher_preview_layout, null, false);
|
||||||
|
mRootView.setInsets(mInsets);
|
||||||
|
measureView(mRootView, mDp.widthPx, mDp.heightPx);
|
||||||
|
|
||||||
|
mHotseat = mRootView.findViewById(R.id.hotseat);
|
||||||
|
mHotseat.resetLayout(false);
|
||||||
|
|
||||||
|
mWorkspace = mRootView.findViewById(R.id.workspace);
|
||||||
|
mWorkspace.setPadding(mDp.workspacePadding.left + mDp.cellLayoutPaddingLeftRightPx,
|
||||||
|
mDp.workspacePadding.top,
|
||||||
|
mDp.workspacePadding.right + mDp.cellLayoutPaddingLeftRightPx,
|
||||||
|
mDp.workspacePadding.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
|
||||||
|
if ("TextClock".equals(name)) {
|
||||||
|
// Workaround for TextClock accessing handler for unregistering ticker.
|
||||||
|
return new TextClock(context, attrs) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Handler getHandler() {
|
||||||
|
return mUiHandler;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else if (!"fragment".equals(name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PreviewFragment);
|
||||||
|
FragmentWithPreview f = (FragmentWithPreview) Fragment.instantiate(
|
||||||
|
context, ta.getString(R.styleable.PreviewFragment_android_name));
|
||||||
|
f.enterPreviewMode(context);
|
||||||
|
f.onInit(null);
|
||||||
|
|
||||||
|
View view = f.onCreateView(LayoutInflater.from(context), (ViewGroup) parent, null);
|
||||||
|
view.setId(ta.getInt(R.styleable.PreviewFragment_android_id, View.NO_ID));
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(String name, Context context, AttributeSet attrs) {
|
||||||
|
return onCreateView(null, name, context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseDragLayer getDragLayer() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeviceProfile getDeviceProfile() {
|
||||||
|
return mDp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Hotseat getHotseat() {
|
||||||
|
return mHotseat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CellLayout getScreenWithId(int screenId) {
|
||||||
|
return mWorkspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void inflateAndAddIcon(ShortcutInfo info) {
|
||||||
|
BubbleTextView icon = (BubbleTextView) mHomeElementInflater.inflate(
|
||||||
|
R.layout.app_icon, mWorkspace, false);
|
||||||
|
icon.applyFromShortcutInfo(info);
|
||||||
|
addInScreenFromBind(icon, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dispatchVisibilityAggregated(View view, boolean isVisible) {
|
||||||
|
// Similar to View.dispatchVisibilityAggregated implementation.
|
||||||
|
final boolean thisVisible = view.getVisibility() == VISIBLE;
|
||||||
|
if (thisVisible || !isVisible) {
|
||||||
|
view.onVisibilityAggregated(isVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (view instanceof ViewGroup) {
|
||||||
|
isVisible = thisVisible && isVisible;
|
||||||
|
ViewGroup vg = (ViewGroup) view;
|
||||||
|
int count = vg.getChildCount();
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
dispatchVisibilityAggregated(vg.getChildAt(i), isVisible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderScreenShot(Canvas canvas) {
|
||||||
|
// Add hotseat icons
|
||||||
|
for (int i = 0; i < mIdp.numHotseatIcons; i++) {
|
||||||
|
ShortcutInfo info = new ShortcutInfo(mShortcutInfo);
|
||||||
|
info.container = Favorites.CONTAINER_HOTSEAT;
|
||||||
|
info.screenId = i;
|
||||||
|
inflateAndAddIcon(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add workspace icons
|
||||||
|
for (int i = 0; i < mIdp.numColumns; i++) {
|
||||||
|
ShortcutInfo info = new ShortcutInfo(mShortcutInfo);
|
||||||
|
info.container = Favorites.CONTAINER_DESKTOP;
|
||||||
|
info.screenId = 0;
|
||||||
|
info.cellX = i;
|
||||||
|
info.cellY = mIdp.numRows - 1;
|
||||||
|
inflateAndAddIcon(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add first page QSB
|
||||||
|
if (FeatureFlags.QSB_ON_FIRST_SCREEN.get()) {
|
||||||
|
View qsb = mHomeElementInflater.inflate(
|
||||||
|
R.layout.search_container_workspace, mWorkspace, false);
|
||||||
|
CellLayout.LayoutParams lp =
|
||||||
|
new CellLayout.LayoutParams(0, 0, mWorkspace.getCountX(), 1);
|
||||||
|
lp.canReorder = false;
|
||||||
|
mWorkspace.addViewToCellLayout(qsb, 0, R.id.search_container_workspace, lp, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup search view
|
||||||
|
SearchUiManager searchUiManager =
|
||||||
|
mRootView.findViewById(R.id.search_container_all_apps);
|
||||||
|
mRootView.findViewById(R.id.apps_view).setTranslationY(
|
||||||
|
mDp.heightPx - searchUiManager.getScrollRangeDelta(mInsets));
|
||||||
|
|
||||||
|
measureView(mRootView, mDp.widthPx, mDp.heightPx);
|
||||||
|
dispatchVisibilityAggregated(mRootView, true);
|
||||||
|
measureView(mRootView, mDp.widthPx, mDp.heightPx);
|
||||||
|
// Additional measure for views which use auto text size API
|
||||||
|
measureView(mRootView, mDp.widthPx, mDp.heightPx);
|
||||||
|
|
||||||
|
canvas.drawColor(Color.GRAY);
|
||||||
|
mRootView.draw(canvas);
|
||||||
|
dispatchVisibilityAggregated(mRootView, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void measureView(View view, int width, int height) {
|
||||||
|
view.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY));
|
||||||
|
view.layout(0, 0, width, height);
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,6 +44,7 @@ import com.android.launcher3.LauncherAppState;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.config.FeatureFlags;
|
import com.android.launcher3.config.FeatureFlags;
|
||||||
|
import com.android.launcher3.graphics.FragmentWithPreview;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A frame layout which contains a QSB. This internally uses fragment to bind the view, which
|
* A frame layout which contains a QSB. This internally uses fragment to bind the view, which
|
||||||
|
@ -78,7 +79,7 @@ public class QsbContainerView extends FrameLayout {
|
||||||
/**
|
/**
|
||||||
* A fragment to display the QSB.
|
* A fragment to display the QSB.
|
||||||
*/
|
*/
|
||||||
public static class QsbFragment extends Fragment {
|
public static class QsbFragment extends FragmentWithPreview {
|
||||||
|
|
||||||
public static final int QSB_WIDGET_HOST_ID = 1026;
|
public static final int QSB_WIDGET_HOST_ID = 1026;
|
||||||
private static final int REQUEST_BIND_QSB = 1;
|
private static final int REQUEST_BIND_QSB = 1;
|
||||||
|
@ -93,14 +94,13 @@ public class QsbContainerView extends FrameLayout {
|
||||||
private int mOrientation;
|
private int mOrientation;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onInit(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
mQsbWidgetHost = createHost();
|
mQsbWidgetHost = createHost();
|
||||||
mOrientation = getContext().getResources().getConfiguration().orientation;
|
mOrientation = getContext().getResources().getConfiguration().orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected QsbWidgetHost createHost() {
|
protected QsbWidgetHost createHost() {
|
||||||
return new QsbWidgetHost(getActivity(), QSB_WIDGET_HOST_ID,
|
return new QsbWidgetHost(getContext(), QSB_WIDGET_HOST_ID,
|
||||||
(c) -> new QsbWidgetHostView(c));
|
(c) -> new QsbWidgetHostView(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ public class QsbContainerView extends FrameLayout {
|
||||||
public View onCreateView(
|
public View onCreateView(
|
||||||
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
mWrapper = new FrameLayout(getActivity());
|
mWrapper = new FrameLayout(getContext());
|
||||||
|
|
||||||
// Only add the view when enabled
|
// Only add the view when enabled
|
||||||
if (isQsbEnabled()) {
|
if (isQsbEnabled()) {
|
||||||
|
@ -126,16 +126,16 @@ public class QsbContainerView extends FrameLayout {
|
||||||
return getDefaultView(container, false /* show setup icon */);
|
return getDefaultView(container, false /* show setup icon */);
|
||||||
}
|
}
|
||||||
Bundle opts = createBindOptions();
|
Bundle opts = createBindOptions();
|
||||||
Activity activity = getActivity();
|
Context context = getContext();
|
||||||
AppWidgetManager widgetManager = AppWidgetManager.getInstance(activity);
|
AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
|
||||||
|
|
||||||
int widgetId = Utilities.getPrefs(activity).getInt(mKeyWidgetId, -1);
|
int widgetId = Utilities.getPrefs(context).getInt(mKeyWidgetId, -1);
|
||||||
AppWidgetProviderInfo widgetInfo = widgetManager.getAppWidgetInfo(widgetId);
|
AppWidgetProviderInfo widgetInfo = widgetManager.getAppWidgetInfo(widgetId);
|
||||||
boolean isWidgetBound = (widgetInfo != null) &&
|
boolean isWidgetBound = (widgetInfo != null) &&
|
||||||
widgetInfo.provider.equals(mWidgetInfo.provider);
|
widgetInfo.provider.equals(mWidgetInfo.provider);
|
||||||
|
|
||||||
int oldWidgetId = widgetId;
|
int oldWidgetId = widgetId;
|
||||||
if (!isWidgetBound) {
|
if (!isWidgetBound && !isInPreviewMode()) {
|
||||||
if (widgetId > -1) {
|
if (widgetId > -1) {
|
||||||
// widgetId is already bound and its not the correct provider. reset host.
|
// widgetId is already bound and its not the correct provider. reset host.
|
||||||
mQsbWidgetHost.deleteHost();
|
mQsbWidgetHost.deleteHost();
|
||||||
|
@ -155,14 +155,16 @@ public class QsbContainerView extends FrameLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWidgetBound) {
|
if (isWidgetBound) {
|
||||||
mQsb = (QsbWidgetHostView) mQsbWidgetHost.createView(activity, widgetId, mWidgetInfo);
|
mQsb = (QsbWidgetHostView) mQsbWidgetHost.createView(context, widgetId, mWidgetInfo);
|
||||||
mQsb.setId(R.id.qsb_widget);
|
mQsb.setId(R.id.qsb_widget);
|
||||||
|
|
||||||
if (!Utilities.containsAll(AppWidgetManager.getInstance(activity)
|
if (!isInPreviewMode()) {
|
||||||
.getAppWidgetOptions(widgetId), opts)) {
|
if (!Utilities.containsAll(AppWidgetManager.getInstance(context)
|
||||||
mQsb.updateAppWidgetOptions(opts);
|
.getAppWidgetOptions(widgetId), opts)) {
|
||||||
|
mQsb.updateAppWidgetOptions(opts);
|
||||||
|
}
|
||||||
|
mQsbWidgetHost.startListening();
|
||||||
}
|
}
|
||||||
mQsbWidgetHost.startListening();
|
|
||||||
return mQsb;
|
return mQsb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +173,7 @@ public class QsbContainerView extends FrameLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveWidgetId(int widgetId) {
|
private void saveWidgetId(int widgetId) {
|
||||||
Utilities.getPrefs(getActivity()).edit().putInt(mKeyWidgetId, widgetId).apply();
|
Utilities.getPrefs(getContext()).edit().putInt(mKeyWidgetId, widgetId).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -206,7 +208,7 @@ public class QsbContainerView extends FrameLayout {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mWrapper != null && getActivity() != null) {
|
if (mWrapper != null && getContext() != null) {
|
||||||
mWrapper.removeAllViews();
|
mWrapper.removeAllViews();
|
||||||
mWrapper.addView(createQsb(mWrapper));
|
mWrapper.addView(createQsb(mWrapper));
|
||||||
}
|
}
|
||||||
|
@ -217,10 +219,10 @@ public class QsbContainerView extends FrameLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Bundle createBindOptions() {
|
protected Bundle createBindOptions() {
|
||||||
InvariantDeviceProfile idp = LauncherAppState.getIDP(getActivity());
|
InvariantDeviceProfile idp = LauncherAppState.getIDP(getContext());
|
||||||
|
|
||||||
Bundle opts = new Bundle();
|
Bundle opts = new Bundle();
|
||||||
Rect size = AppWidgetResizeFrame.getWidgetSizeRanges(getActivity(),
|
Rect size = AppWidgetResizeFrame.getWidgetSizeRanges(getContext(),
|
||||||
idp.numColumns, 1, null);
|
idp.numColumns, 1, null);
|
||||||
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, size.left);
|
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, size.left);
|
||||||
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, size.top);
|
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, size.top);
|
||||||
|
@ -252,14 +254,14 @@ public class QsbContainerView extends FrameLayout {
|
||||||
*/
|
*/
|
||||||
protected AppWidgetProviderInfo getSearchWidgetProvider() {
|
protected AppWidgetProviderInfo getSearchWidgetProvider() {
|
||||||
SearchManager searchManager =
|
SearchManager searchManager =
|
||||||
(SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
|
(SearchManager) getContext().getSystemService(Context.SEARCH_SERVICE);
|
||||||
ComponentName searchComponent = searchManager.getGlobalSearchActivity();
|
ComponentName searchComponent = searchManager.getGlobalSearchActivity();
|
||||||
if (searchComponent == null) return null;
|
if (searchComponent == null) return null;
|
||||||
String providerPkg = searchComponent.getPackageName();
|
String providerPkg = searchComponent.getPackageName();
|
||||||
|
|
||||||
AppWidgetProviderInfo defaultWidgetForSearchPackage = null;
|
AppWidgetProviderInfo defaultWidgetForSearchPackage = null;
|
||||||
|
|
||||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getActivity());
|
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getContext());
|
||||||
for (AppWidgetProviderInfo info : appWidgetManager.getInstalledProviders()) {
|
for (AppWidgetProviderInfo info : appWidgetManager.getInstalledProviders()) {
|
||||||
if (info.provider.getPackageName().equals(providerPkg) && info.configure == null) {
|
if (info.provider.getPackageName().equals(providerPkg) && info.configure == null) {
|
||||||
if ((info.widgetCategory
|
if ((info.widgetCategory
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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.util;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import com.android.launcher3.LauncherAppState;
|
||||||
|
|
||||||
|
import com.android.launcher3.graphics.LauncherPreviewRenderer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Remove this class
|
||||||
|
*/
|
||||||
|
@TargetApi(Build.VERSION_CODES.O)
|
||||||
|
public class MyActivity extends Activity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
new AsyncTask<Void, Void, Bitmap>() {
|
||||||
|
@Override
|
||||||
|
protected Bitmap doInBackground(Void... voids) {
|
||||||
|
LauncherPreviewRenderer renderer = new LauncherPreviewRenderer(MyActivity.this,
|
||||||
|
LauncherAppState.getIDP(MyActivity.this));
|
||||||
|
|
||||||
|
Bitmap b = renderer.createScreenShot();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Bitmap bitmap) {
|
||||||
|
ImageView view = new ImageView(MyActivity.this);
|
||||||
|
view.setImageBitmap(bitmap);
|
||||||
|
setContentView(view);
|
||||||
|
|
||||||
|
view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||||
|
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||||
|
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||||
|
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue