blob: cfa986467ccb96fd7e1832c622f4cbb8bcd67589 [file] [log] [blame]
/*
* Copyright (C) 2015 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.systemui.statusbar.car;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.util.UserIcons;
import com.android.systemui.R;
import com.android.systemui.statusbar.UserUtil;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.UserSwitcherController;
/**
* Displays a ViewPager with icons for the users in the system to allow switching between users.
* One of the uses of this is for the lock screen in auto.
*/
public class UserGridView extends ViewPager {
private StatusBar mStatusBar;
private UserSwitcherController mUserSwitcherController;
private Adapter mAdapter;
private UserSelectionListener mUserSelectionListener;
public UserGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void init(StatusBar statusBar, UserSwitcherController userSwitcherController) {
mStatusBar = statusBar;
mUserSwitcherController = userSwitcherController;
mAdapter = new Adapter(mUserSwitcherController);
addOnLayoutChangeListener(mAdapter);
setAdapter(mAdapter);
}
public void onUserSwitched(int newUserId) {
// Bring up security view after user switch is completed.
post(this::showOfflineAuthUi);
}
public void setUserSelectionListener(UserSelectionListener userSelectionListener) {
mUserSelectionListener = userSelectionListener;
}
void showOfflineAuthUi() {
// TODO: Show keyguard UI in-place.
mStatusBar.executeRunnableDismissingKeyguard(null, null, true, true, true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Wrap content doesn't work in ViewPagers, so simulate the behavior in code.
int height = 0;
for(int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec,
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
height = Math.max(child.getMeasuredHeight(), height);
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* This is a ViewPager.PagerAdapter which deletegates the work to a
* UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have
* to use composition instead to achieve the same goal since both the base classes are abstract
* classes and not interfaces.
*/
private final class Adapter extends PagerAdapter implements View.OnLayoutChangeListener {
private final int mPodWidth;
private final int mPodMargin;
private final WrappedBaseUserAdapter mUserAdapter;
private int mContainerWidth;
public Adapter(UserSwitcherController controller) {
super();
mUserAdapter = new WrappedBaseUserAdapter(controller, this);
mPodWidth = getResources().getDimensionPixelSize(
R.dimen.car_fullscreen_user_pod_image_avatar_width);
mPodMargin = getResources().getDimensionPixelSize(
R.dimen.car_fullscreen_user_pod_margin_side);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
private int getIconsPerPage() {
// We need to know how many pods we need in this page. Each pod has its own width and
// margins on both sides. We can then divide the measured width of the parent by the
// sum of pod width and margin to get the number of pods that will completely fit.
return mContainerWidth / (mPodWidth + mPodMargin * 2);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Context context = getContext();
LayoutInflater inflater = LayoutInflater.from(context);
ViewGroup pods = (ViewGroup) inflater.inflate(
R.layout.car_fullscreen_user_pod_container, null);
int iconsPerPage = getIconsPerPage();
int limit = Math.min(mUserAdapter.getCount(), (position + 1) * iconsPerPage);
for (int i = position * iconsPerPage; i < limit; i++) {
pods.addView(makeUserPod(inflater, context, i, pods));
}
container.addView(pods);
return pods;
}
private Drawable getUserIcon(Context context, UserSwitcherController.UserRecord record) {
if (record.isAddUser) {
Drawable icon = context.getDrawable(R.drawable.ic_add_circle_qs);
icon.setTint(Color.WHITE);
return icon;
}
return UserIcons.getDefaultUserIcon(record.resolveId(), /* light= */ true);
}
private View makeUserPod(LayoutInflater inflater, Context context,
int position, ViewGroup parent) {
final UserSwitcherController.UserRecord record = mUserAdapter.getItem(position);
View view = inflater.inflate(R.layout.car_fullscreen_user_pod, parent, false);
TextView nameView = view.findViewById(R.id.user_name);
if (record != null) {
nameView.setText(mUserAdapter.getName(context, record));
view.setActivated(record.isCurrent);
} else {
nameView.setText(context.getString(R.string.unknown_user_label));
}
ImageView iconView = (ImageView) view.findViewById(R.id.user_avatar);
if (record == null || record.picture == null) {
iconView.setImageDrawable(getUserIcon(context, record));
} else {
iconView.setImageBitmap(record.picture);
}
iconView.setOnClickListener(v -> {
if (record == null) {
return;
}
if (mUserSelectionListener != null) {
mUserSelectionListener.onUserSelected(record);
}
if (record.isCurrent) {
showOfflineAuthUi();
} else {
mUserSwitcherController.switchTo(record);
}
});
return view;
}
@Override
public int getCount() {
int iconsPerPage = getIconsPerPage();
if (iconsPerPage == 0) {
return 0;
}
return (int) Math.ceil((double) mUserAdapter.getCount() / getIconsPerPage());
}
public void refresh() {
mUserAdapter.refresh();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
mContainerWidth = Math.max(left - right, right - left);
notifyDataSetChanged();
}
}
private final class WrappedBaseUserAdapter extends UserSwitcherController.BaseUserAdapter {
private Adapter mContainer;
public WrappedBaseUserAdapter(UserSwitcherController controller, Adapter container) {
super(controller);
mContainer = container;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
throw new UnsupportedOperationException("unused");
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
mContainer.notifyDataSetChanged();
}
}
interface UserSelectionListener {
void onUserSelected(UserSwitcherController.UserRecord record);
};
}