Improved UX for DISALLOW_SET_USER_ICON restriction.
Modified popup menu, so that each item has a hint, why it is blocked (in case the DISALLOW_SET_USER_ICON is set). BUG:27914812 Change-Id: I1f891ffe725f383285d577cf47d89c294f2c3986
This commit is contained in:
@@ -1,31 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
/*
|
|
||||||
** Copyright 2013, 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.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
|
|
||||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@android:id/text1"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceListItemSmall"
|
|
||||||
android:textColor="?android:attr/textColorAlertDialogListItem"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:paddingStart="16dip"
|
|
||||||
android:paddingEnd="16dip"
|
|
||||||
android:ellipsize="marquee"
|
|
||||||
/>
|
|
43
res/layout/restricted_popup_menu_item.xml
Normal file
43
res/layout/restricted_popup_menu_item.xml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
** Copyright 2016, 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.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingStart="16dip"
|
||||||
|
android:paddingEnd="16dip">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?android:attr/textColorAlertDialogListItem"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceListItemSmall"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:layout_alignParentLeft="true" />
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/restricted_icon"
|
||||||
|
android:layout_width="@dimen/restricted_icon_size"
|
||||||
|
android:layout_height="@dimen/restricted_icon_size"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
android:src="@drawable/ic_info"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</RelativeLayout>
|
@@ -32,6 +32,7 @@ import android.graphics.Rect;
|
|||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.provider.ContactsContract.DisplayPhoto;
|
import android.provider.ContactsContract.DisplayPhoto;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
@@ -40,13 +41,15 @@ import android.util.Log;
|
|||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ListAdapter;
|
|
||||||
import android.widget.ListPopupWindow;
|
import android.widget.ListPopupWindow;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settingslib.RestrictedLockUtils;
|
||||||
import com.android.settingslib.drawable.CircleFramedDrawable;
|
import com.android.settingslib.drawable.CircleFramedDrawable;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -61,9 +64,6 @@ import java.util.List;
|
|||||||
public class EditUserPhotoController {
|
public class EditUserPhotoController {
|
||||||
private static final String TAG = "EditUserPhotoController";
|
private static final String TAG = "EditUserPhotoController";
|
||||||
|
|
||||||
private static final int POPUP_LIST_ITEM_ID_CHOOSE_PHOTO = 1;
|
|
||||||
private static final int POPUP_LIST_ITEM_ID_TAKE_PHOTO = 2;
|
|
||||||
|
|
||||||
// It seems that this class generates custom request codes and they may
|
// It seems that this class generates custom request codes and they may
|
||||||
// collide with ours, these values are very unlikely to have a conflict.
|
// collide with ours, these values are very unlikely to have a conflict.
|
||||||
private static final int REQUEST_CODE_CHOOSE_PHOTO = 1001;
|
private static final int REQUEST_CODE_CHOOSE_PHOTO = 1001;
|
||||||
@@ -100,10 +100,6 @@ public class EditUserPhotoController {
|
|||||||
showUpdatePhotoPopup();
|
showUpdatePhotoPopup();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
|
||||||
if (um.hasUserRestriction(UserManager.DISALLOW_SET_USER_ICON)) {
|
|
||||||
mImageView.setEnabled(false);
|
|
||||||
}
|
|
||||||
mNewUserPhotoBitmap = bitmap;
|
mNewUserPhotoBitmap = bitmap;
|
||||||
mNewUserPhotoDrawable = drawable;
|
mNewUserPhotoDrawable = drawable;
|
||||||
}
|
}
|
||||||
@@ -142,19 +138,31 @@ public class EditUserPhotoController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context context = mImageView.getContext();
|
final Context context = mImageView.getContext();
|
||||||
final List<EditUserPhotoController.AdapterItem> items = new ArrayList<EditUserPhotoController.AdapterItem>();
|
final List<EditUserPhotoController.RestrictedMenuItem> items = new ArrayList<>();
|
||||||
|
|
||||||
if (canTakePhoto()) {
|
if (canTakePhoto) {
|
||||||
String title = mImageView.getContext().getString( R.string.user_image_take_photo);
|
final String title = context.getString(R.string.user_image_take_photo);
|
||||||
EditUserPhotoController.AdapterItem item = new AdapterItem(title, POPUP_LIST_ITEM_ID_TAKE_PHOTO);
|
final Runnable action = new Runnable() {
|
||||||
items.add(item);
|
@Override
|
||||||
|
public void run() {
|
||||||
|
takePhoto();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
items.add(new RestrictedMenuItem(context, title, UserManager.DISALLOW_SET_USER_ICON,
|
||||||
|
action));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canChoosePhoto) {
|
if (canChoosePhoto) {
|
||||||
String title = context.getString(R.string.user_image_choose_photo);
|
final String title = context.getString(R.string.user_image_choose_photo);
|
||||||
EditUserPhotoController.AdapterItem item = new AdapterItem(title, POPUP_LIST_ITEM_ID_CHOOSE_PHOTO);
|
final Runnable action = new Runnable() {
|
||||||
items.add(item);
|
@Override
|
||||||
|
public void run() {
|
||||||
|
choosePhoto();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
items.add(new RestrictedMenuItem(context, title, UserManager.DISALLOW_SET_USER_ICON,
|
||||||
|
action));
|
||||||
}
|
}
|
||||||
|
|
||||||
final ListPopupWindow listPopupWindow = new ListPopupWindow(context);
|
final ListPopupWindow listPopupWindow = new ListPopupWindow(context);
|
||||||
@@ -162,10 +170,7 @@ public class EditUserPhotoController {
|
|||||||
listPopupWindow.setAnchorView(mImageView);
|
listPopupWindow.setAnchorView(mImageView);
|
||||||
listPopupWindow.setModal(true);
|
listPopupWindow.setModal(true);
|
||||||
listPopupWindow.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
|
listPopupWindow.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
|
||||||
|
listPopupWindow.setAdapter(new RestrictedPopupMenuAdapter(context, items));
|
||||||
ListAdapter adapter = new ArrayAdapter<EditUserPhotoController.AdapterItem>(context,
|
|
||||||
R.layout.edit_user_photo_popup_item, items);
|
|
||||||
listPopupWindow.setAdapter(adapter);
|
|
||||||
|
|
||||||
final int width = Math.max(mImageView.getWidth(), context.getResources()
|
final int width = Math.max(mImageView.getWidth(), context.getResources()
|
||||||
.getDimensionPixelSize(R.dimen.update_user_photo_popup_min_width));
|
.getDimensionPixelSize(R.dimen.update_user_photo_popup_min_width));
|
||||||
@@ -175,17 +180,10 @@ public class EditUserPhotoController {
|
|||||||
listPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
listPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
EditUserPhotoController.AdapterItem item = items.get(position);
|
listPopupWindow.dismiss();
|
||||||
switch (item.id) {
|
final RestrictedMenuItem item =
|
||||||
case POPUP_LIST_ITEM_ID_CHOOSE_PHOTO: {
|
(RestrictedMenuItem) parent.getAdapter().getItem(position);
|
||||||
choosePhoto();
|
item.doAction();
|
||||||
listPopupWindow.dismiss();
|
|
||||||
} break;
|
|
||||||
case POPUP_LIST_ITEM_ID_TAKE_PHOTO: {
|
|
||||||
takePhoto();
|
|
||||||
listPopupWindow.dismiss();
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -363,18 +361,82 @@ public class EditUserPhotoController {
|
|||||||
new File(mContext.getCacheDir(), NEW_USER_PHOTO_FILE_NAME).delete();
|
new File(mContext.getCacheDir(), NEW_USER_PHOTO_FILE_NAME).delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class AdapterItem {
|
private static final class RestrictedMenuItem {
|
||||||
final String title;
|
private final Context mContext;
|
||||||
final int id;
|
private final String mTitle;
|
||||||
|
private final Runnable mAction;
|
||||||
|
private final RestrictedLockUtils.EnforcedAdmin mAdmin;
|
||||||
|
// Restriction may be set by system or something else via UserManager.setUserRestriction().
|
||||||
|
private final boolean mIsRestrictedByBase;
|
||||||
|
|
||||||
public AdapterItem(String title, int id) {
|
/**
|
||||||
this.title = title;
|
* The menu item, used for popup menu. Any element of such a menu can be disabled by admin.
|
||||||
this.id = id;
|
* @param context A context.
|
||||||
|
* @param title The title of the menu item.
|
||||||
|
* @param restriction The restriction, that if is set, blocks the menu item.
|
||||||
|
* @param action The action on menu item click.
|
||||||
|
*/
|
||||||
|
public RestrictedMenuItem(Context context, String title, String restriction,
|
||||||
|
Runnable action) {
|
||||||
|
mContext = context;
|
||||||
|
mTitle = title;
|
||||||
|
mAction = action;
|
||||||
|
|
||||||
|
final int myUserId = UserHandle.myUserId();
|
||||||
|
mAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(context,
|
||||||
|
restriction, myUserId);
|
||||||
|
mIsRestrictedByBase = RestrictedLockUtils.hasBaseUserRestriction(mContext,
|
||||||
|
restriction, myUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return title;
|
return mTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
final void doAction() {
|
||||||
|
if (isRestrictedByBase()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRestrictedByAdmin()) {
|
||||||
|
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, mAdmin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mAction.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean isRestrictedByAdmin() {
|
||||||
|
return mAdmin != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean isRestrictedByBase() {
|
||||||
|
return mIsRestrictedByBase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide this adapter to ListPopupWindow.setAdapter() to have a popup window menu, where
|
||||||
|
* any element can be restricted by admin (profile owner or device owner).
|
||||||
|
*/
|
||||||
|
private static final class RestrictedPopupMenuAdapter extends ArrayAdapter<RestrictedMenuItem> {
|
||||||
|
public RestrictedPopupMenuAdapter(Context context, List<RestrictedMenuItem> items) {
|
||||||
|
super(context, R.layout.restricted_popup_menu_item, R.id.text, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
final View view = super.getView(position, convertView, parent);
|
||||||
|
final RestrictedMenuItem item = getItem(position);
|
||||||
|
final TextView text = (TextView) view.findViewById(R.id.text);
|
||||||
|
final ImageView image = (ImageView) view.findViewById(R.id.restricted_icon);
|
||||||
|
|
||||||
|
text.setEnabled(!item.isRestrictedByAdmin() && !item.isRestrictedByBase());
|
||||||
|
image.setVisibility(item.isRestrictedByAdmin() && !item.isRestrictedByBase() ?
|
||||||
|
ImageView.VISIBLE : ImageView.GONE);
|
||||||
|
|
||||||
|
return view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user