TaskViewFocusFrame.java revision 2cf6ad832d7be4e86765a2326498b50560af07df
121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He/* 221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * Copyright (C) 2017 The Android Open Source Project 321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * 421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * Licensed under the Apache License, Version 2.0 (the "License"); 521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * you may not use this file except in compliance with the License. 621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * You may obtain a copy of the License at 721f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * 821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * http://www.apache.org/licenses/LICENSE-2.0 921f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * 1021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * Unless required by applicable law or agreed to in writing, software 1121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * distributed under the License is distributed on an "AS IS" BASIS, 1221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * See the License for the specific language governing permissions and 1421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * limitations under the License. 1521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He */ 1621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 1721f495f07b1b9ace99986a110d01a763847687b1Jiaquan Hepackage com.android.systemui.recents.views.grid; 1821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 1921f495f07b1b9ace99986a110d01a763847687b1Jiaquan Heimport android.content.Context; 2021f495f07b1b9ace99986a110d01a763847687b1Jiaquan Heimport android.graphics.Rect; 2121f495f07b1b9ace99986a110d01a763847687b1Jiaquan Heimport android.util.AttributeSet; 2221f495f07b1b9ace99986a110d01a763847687b1Jiaquan Heimport android.view.View; 2321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 2421f495f07b1b9ace99986a110d01a763847687b1Jiaquan Heimport android.view.ViewTreeObserver.OnGlobalFocusChangeListener; 2521f495f07b1b9ace99986a110d01a763847687b1Jiaquan Heimport com.android.systemui.R; 266519c1b0fe85c5f25115539e936e4333e8537098Winson Chungimport com.android.systemui.shared.recents.model.TaskStack; 2721f495f07b1b9ace99986a110d01a763847687b1Jiaquan Heimport com.android.systemui.recents.views.TaskStackView; 2821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 2921f495f07b1b9ace99986a110d01a763847687b1Jiaquan Hepublic class TaskViewFocusFrame extends View implements OnGlobalFocusChangeListener { 3021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 3121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He private TaskStackView mSv; 3221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He private TaskGridLayoutAlgorithm mTaskGridLayoutAlgorithm; 3321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He public TaskViewFocusFrame(Context context) { 3421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He this(context, null); 3521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 3621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 3721f495f07b1b9ace99986a110d01a763847687b1Jiaquan He public TaskViewFocusFrame(Context context, AttributeSet attrs) { 3821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He this(context, attrs, 0); 3921f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 4021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 4121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He public TaskViewFocusFrame(Context context, AttributeSet attrs, int defStyleAttr) { 4221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He this(context, attrs, defStyleAttr, 0); 4321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 4421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 4521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He public TaskViewFocusFrame(Context context, AttributeSet attrs, int defStyleAttr, 4621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He int defStyleRes) { 4721f495f07b1b9ace99986a110d01a763847687b1Jiaquan He super(context, attrs, defStyleAttr, defStyleRes); 4821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He setBackground(mContext.getDrawable( 4921f495f07b1b9ace99986a110d01a763847687b1Jiaquan He R.drawable.recents_grid_task_view_focus_frame_background)); 5021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He setFocusable(false); 5121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He hide(); 5221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 5321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 5421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He public TaskViewFocusFrame(Context context, TaskStackView stackView, 5521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He TaskGridLayoutAlgorithm taskGridLayoutAlgorithm) { 5621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He this(context); 5721f495f07b1b9ace99986a110d01a763847687b1Jiaquan He mSv = stackView; 5821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He mTaskGridLayoutAlgorithm = taskGridLayoutAlgorithm; 5921f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 6021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 6121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He /** 6221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * Measure the width and height of the focus frame according to the current grid task view size. 6321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He */ 6421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He public void measure() { 6521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He int thickness = mTaskGridLayoutAlgorithm.getFocusFrameThickness(); 6621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He Rect rect = mTaskGridLayoutAlgorithm.getTaskGridRect(); 6721f495f07b1b9ace99986a110d01a763847687b1Jiaquan He measure( 6821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He MeasureSpec.makeMeasureSpec(rect.width() + thickness * 2, MeasureSpec.EXACTLY), 6921f495f07b1b9ace99986a110d01a763847687b1Jiaquan He MeasureSpec.makeMeasureSpec(rect.height() + thickness * 2, MeasureSpec.EXACTLY)); 7021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 7121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 7221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He /** 7321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * Layout the focus frame with its size. 7421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He */ 7521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He public void layout() { 7621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He layout(0, 0, getMeasuredWidth(), getMeasuredHeight()); 7721f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 7821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 7921f495f07b1b9ace99986a110d01a763847687b1Jiaquan He /** 8021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * Update the current size of grid task view and the focus frame. 8121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He */ 8221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He public void resize() { 8321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He if (mSv.useGridLayout()) { 8421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He mTaskGridLayoutAlgorithm.updateTaskGridRect(mSv.getStack().getTaskCount()); 8521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He measure(); 8621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He requestLayout(); 8721f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 8821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 8921f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 9021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He /** 9121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * Move the task view focus frame to surround the newly focused view. If it's {@code null} or 9221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * it's not an instance of GridTaskView, we hide the focus frame. 9321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He * @param newFocus The newly focused view. 9421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He */ 9521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He public void moveGridTaskViewFocus(View newFocus) { 9621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He if (mSv.useGridLayout()) { 9721f495f07b1b9ace99986a110d01a763847687b1Jiaquan He // The frame only shows up in the grid layout. It shouldn't show up in the stack 9821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He // layout including when we're in the split screen. 9921f495f07b1b9ace99986a110d01a763847687b1Jiaquan He if (newFocus instanceof GridTaskView) { 10021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He // If the focus goes to a GridTaskView, we show the frame and layout it. 10121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He int[] location = new int[2]; 10221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He newFocus.getLocationInWindow(location); 10321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He int thickness = mTaskGridLayoutAlgorithm.getFocusFrameThickness(); 10421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He setTranslationX(location[0] - thickness); 10521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He setTranslationY(location[1] - thickness); 10621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He show(); 10721f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } else { 10821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He // If focus goes to other views, we hide the frame. 10921f495f07b1b9ace99986a110d01a763847687b1Jiaquan He hide(); 11021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 11121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 11221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 11321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 11421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He @Override 11521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He public void onGlobalFocusChanged(View oldFocus, View newFocus) { 11621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He if (!mSv.useGridLayout()) { 11721f495f07b1b9ace99986a110d01a763847687b1Jiaquan He return; 11821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 11921f495f07b1b9ace99986a110d01a763847687b1Jiaquan He if (newFocus == null) { 12021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He // We're going to touch mode, unset the focus. 12121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He moveGridTaskViewFocus(null); 12221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He return; 12321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 12421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He if (oldFocus == null) { 12521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He // We're returning from touch mode, set the focus to the previously focused task. 12621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He final TaskStack stack = mSv.getStack(); 12721f495f07b1b9ace99986a110d01a763847687b1Jiaquan He final int taskCount = stack.getTaskCount(); 1282cf6ad832d7be4e86765a2326498b50560af07dfWinson Chung final int k = stack.indexOfTask(mSv.getFocusedTask()); 12921f495f07b1b9ace99986a110d01a763847687b1Jiaquan He final int taskIndexToFocus = k == -1 ? (taskCount - 1) : (k % taskCount); 13021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He mSv.setFocusedTask(taskIndexToFocus, false, true); 13121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 13221f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 13321f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 13421f495f07b1b9ace99986a110d01a763847687b1Jiaquan He private void show() { 13521f495f07b1b9ace99986a110d01a763847687b1Jiaquan He setAlpha(1f); 13621f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 13721f495f07b1b9ace99986a110d01a763847687b1Jiaquan He 13821f495f07b1b9ace99986a110d01a763847687b1Jiaquan He private void hide() { 13921f495f07b1b9ace99986a110d01a763847687b1Jiaquan He setAlpha(0f); 14021f495f07b1b9ace99986a110d01a763847687b1Jiaquan He } 14121f495f07b1b9ace99986a110d01a763847687b1Jiaquan He} 142