Add avatar picker that shows a predefined set of images.

This is the first in a series of CLs to add a new avatar picker.

This CL adds the basic avatar picker screen to show a set of
predefined images (that can be supplied as an array of drawables).

Resources are provided to adapt the screen to phones and tablets
of various sizes.

Future CLs will integrate the take photo and choose photo
functionality from the current dialog, and will also add a set
of default icons that can be chosen if no predefined images
have been provided.

Bug: 215134398
Test: manual check screen on various screen sizes
Change-Id: I6ce95549cc17dc5a9b67d9dc43c5b7d2bda37874
This commit is contained in:
Oli Lan
2022-01-17 18:19:36 +00:00
parent 4a883f3a32
commit f98ae93fdf
21 changed files with 541 additions and 15 deletions

View File

@@ -50,6 +50,7 @@ android_library {
"SettingsLibSettingsTransition",
"SettingsLibActivityEmbedding",
"SettingsLibButtonPreference",
"setupdesign",
],
// ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES

View File

@@ -18,4 +18,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.settingslib">
<application>
<activity
android:name="com.android.settingslib.users.AvatarPickerActivity"
android:theme="@style/SudThemeGlifV2.DayNight"/>
</application>
</manifest>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2022 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.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape android:shape="oval">
<solid android:color="?android:attr/colorPrimary"/>
</shape>
</item>
</selector>

View File

@@ -0,0 +1,25 @@
<!--
Copyright (C) 2022 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?android:attr/colorPrimary"
android:pathData="M5.85,17.1q1.275,-0.975 2.85,-1.538Q10.275,15 12,15q1.725,0 3.3,0.563 1.575,0.562 2.85,1.537 0.875,-1.025 1.363,-2.325Q20,13.475 20,12q0,-3.325 -2.337,-5.662Q15.325,4 12,4T6.338,6.338Q4,8.675 4,12q0,1.475 0.487,2.775 0.488,1.3 1.363,2.325zM12,13q-1.475,0 -2.488,-1.012Q8.5,10.975 8.5,9.5t1.012,-2.487Q10.525,6 12,6t2.488,1.013Q15.5,8.024 15.5,9.5t-1.012,2.488Q13.475,13 12,13zM12,22q-2.075,0 -3.9,-0.788 -1.825,-0.787 -3.175,-2.137 -1.35,-1.35 -2.137,-3.175Q2,14.075 2,12t0.788,-3.9q0.787,-1.825 2.137,-3.175 1.35,-1.35 3.175,-2.137Q9.925,2 12,2t3.9,0.788q1.825,0.787 3.175,2.137 1.35,1.35 2.137,3.175Q22,9.925 22,12t-0.788,3.9q-0.787,1.825 -2.137,3.175 -1.35,1.35 -3.175,2.137Q14.075,22 12,22zM12,20q1.325,0 2.5,-0.387 1.175,-0.388 2.15,-1.113 -0.975,-0.725 -2.15,-1.113Q13.325,17 12,17t-2.5,0.387q-1.175,0.388 -2.15,1.113 0.975,0.725 2.15,1.113Q10.675,20 12,20zM12,11q0.65,0 1.075,-0.425 0.425,-0.425 0.425,-1.075 0,-0.65 -0.425,-1.075Q12.65,8 12,8q-0.65,0 -1.075,0.425Q10.5,8.85 10.5,9.5q0,0.65 0.425,1.075Q11.35,11 12,11zM12,9.5zM12,18.5z"/>
</vector>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2022 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.
-->
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/avatar_image"
android:layout_height="@dimen/avatar_size_in_picker"
android:layout_width="@dimen/avatar_size_in_picker"
android:layout_margin="@dimen/avatar_picker_margin"
android:layout_gravity="center"
android:padding="@dimen/avatar_picker_padding"
android:background="@drawable/avatar_selector"/>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2022 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.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/glif_layout"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:icon="@drawable/ic_account_circle"
app:sucUsePartnerResource="true"
app:sucHeaderText="@string/avatar_picker_title">
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:gravity="center_horizontal"
style="@style/SudContentFrame">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/avatar_grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</com.google.android.setupdesign.GlifLayout>

View File

@@ -0,0 +1,21 @@
<!--
Copyright (C) 2022 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.
-->
<resources>
<integer name="avatar_picker_columns">4</integer>
<dimen name="avatar_size_in_picker">104dp</dimen>
<dimen name="avatar_picker_padding">8dp</dimen>
<dimen name="avatar_picker_margin">3dp</dimen>
</resources>

View File

@@ -0,0 +1,21 @@
<!--
Copyright (C) 2022 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.
-->
<resources>
<integer name="avatar_picker_columns">4</integer>
<dimen name="avatar_size_in_picker">128dp</dimen>
<dimen name="avatar_picker_padding">8dp</dimen>
<dimen name="avatar_picker_margin">4dp</dimen>
</resources>

View File

@@ -0,0 +1,21 @@
<!--
Copyright (C) 2022 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.
-->
<resources>
<integer name="avatar_picker_columns">4</integer>
<dimen name="avatar_size_in_picker">148dp</dimen>
<dimen name="avatar_picker_padding">8dp</dimen>
<dimen name="avatar_picker_margin">6dp</dimen>
</resources>

View File

@@ -0,0 +1,21 @@
<!--
Copyright (C) 2022 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.
-->
<resources>
<integer name="avatar_picker_columns">3</integer>
<dimen name="avatar_size_in_picker">112dp</dimen>
<dimen name="avatar_picker_padding">8dp</dimen>
<dimen name="avatar_picker_margin">3dp</dimen>
</resources>

View File

@@ -0,0 +1,21 @@
<!--
Copyright (C) 2022 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.
-->
<resources>
<integer name="avatar_picker_columns">4</integer>
<dimen name="avatar_size_in_picker">104dp</dimen>
<dimen name="avatar_picker_padding">8dp</dimen>
<dimen name="avatar_picker_margin">3dp</dimen>
</resources>

View File

@@ -0,0 +1,21 @@
<!--
Copyright (C) 2022 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.
-->
<resources>
<integer name="avatar_picker_columns">4</integer>
<dimen name="avatar_size_in_picker">128dp</dimen>
<dimen name="avatar_picker_padding">8dp</dimen>
<dimen name="avatar_picker_margin">4dp</dimen>
</resources>

View File

@@ -0,0 +1,21 @@
<!--
Copyright (C) 2022 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.
-->
<resources>
<integer name="avatar_picker_columns">4</integer>
<dimen name="avatar_size_in_picker">148dp</dimen>
<dimen name="avatar_picker_padding">8dp</dimen>
<dimen name="avatar_picker_margin">6dp</dimen>
</resources>

View File

@@ -0,0 +1,21 @@
<!--
Copyright (C) 2022 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.
-->
<resources>
<integer name="avatar_picker_columns">4</integer>
<dimen name="avatar_size_in_picker">96dp</dimen>
<dimen name="avatar_picker_padding">6dp</dimen>
<dimen name="avatar_picker_margin">2dp</dimen>
</resources>

View File

@@ -647,4 +647,6 @@
<item>disabled</item>
</array>
<array name="avatar_images"/>
</resources>

View File

@@ -102,4 +102,9 @@
<dimen name="user_photo_size_in_profile_info_dialog">112dp</dimen>
<dimen name="add_a_photo_icon_size_in_profile_info_dialog">32dp</dimen>
<integer name="avatar_picker_columns">3</integer>
<dimen name="avatar_size_in_picker">96dp</dimen>
<dimen name="avatar_picker_padding">6dp</dimen>
<dimen name="avatar_picker_margin">2dp</dimen>
</resources>

View File

@@ -1548,4 +1548,7 @@
<!-- Content description of the no calling for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_no_calling">No calling.</string>
<!-- Title for a screen allowing the user to choose a profile picture. [CHAR LIMIT=NONE] -->
<string name="avatar_picker_title">Choose a profile picture</string>
</resources>

View File

@@ -0,0 +1,194 @@
/*
* Copyright (C) 2022 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.settingslib.users;
import android.app.Activity;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.settingslib.R;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.GlifLayout;
import com.google.android.setupdesign.util.ThemeHelper;
/**
* Activity to allow the user to choose a user profile picture.
*/
public class AvatarPickerActivity extends Activity {
static final String EXTRA_AVATAR_INDEX = "avatar_index";
private FooterButton mDoneButton;
private AvatarAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeHelper.trySetDynamicColor(this);
setContentView(R.layout.avatar_picker);
GlifLayout glifLayout = findViewById(R.id.glif_layout);
RecyclerView recyclerView = findViewById(R.id.avatar_grid);
FooterBarMixin mixin = glifLayout.getMixin(FooterBarMixin.class);
FooterButton secondaryButton =
new FooterButton.Builder(this)
.setText("Cancel")
.setListener(view -> cancel())
.build();
mDoneButton =
new FooterButton.Builder(this)
.setText("Done")
.setListener(view -> confirmSelection())
.build();
mDoneButton.setEnabled(false);
mixin.setSecondaryButton(secondaryButton);
mixin.setPrimaryButton(mDoneButton);
mAdapter = new AvatarAdapter();
recyclerView.setAdapter(mAdapter);
recyclerView.setLayoutManager(new GridLayoutManager(this,
getResources().getInteger(R.integer.avatar_picker_columns)));
}
private void confirmSelection() {
Intent data = new Intent();
data.putExtra(EXTRA_AVATAR_INDEX, mAdapter.indexFromPosition(mAdapter.mSelectedPosition));
setResult(RESULT_OK, data);
finish();
}
private void cancel() {
setResult(RESULT_CANCELED);
finish();
}
private class AvatarAdapter extends RecyclerView.Adapter<AvatarViewHolder> {
private static final int NONE = -1;
private static final int AVATAR_START_POSITION = 0;
private final TypedArray mImageDrawables;
private int mSelectedPosition = NONE;
AvatarAdapter() {
mImageDrawables = getResources().obtainTypedArray(R.array.avatar_images);
}
@NonNull
@Override
public AvatarViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View itemView = layoutInflater.inflate(R.layout.avatar_item, parent, false);
return new AvatarViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull AvatarViewHolder viewHolder, int position) {
Drawable drawable = mImageDrawables.getDrawable(indexFromPosition(position));
if (drawable instanceof BitmapDrawable) {
drawable = circularDrawableFrom((BitmapDrawable) drawable);
} else {
throw new IllegalStateException("Avatar drawables must be bitmaps");
}
viewHolder.setSelected(position == mSelectedPosition);
viewHolder.setDrawable(drawable);
viewHolder.setClickListener(view -> {
if (mSelectedPosition == position) {
deselect(position);
} else {
select(position);
}
});
}
@Override
public int getItemCount() {
return AVATAR_START_POSITION + mImageDrawables.length();
}
private Drawable circularDrawableFrom(BitmapDrawable drawable) {
Bitmap bitmap = drawable.getBitmap();
RoundedBitmapDrawable roundedBitmapDrawable =
RoundedBitmapDrawableFactory.create(getResources(), bitmap);
roundedBitmapDrawable.setCircular(true);
return roundedBitmapDrawable;
}
private int indexFromPosition(int position) {
return position - AVATAR_START_POSITION;
}
private void select(int position) {
final int oldSelection = mSelectedPosition;
mSelectedPosition = position;
notifyItemChanged(position);
if (oldSelection != NONE) {
notifyItemChanged(oldSelection);
} else {
mDoneButton.setEnabled(true);
}
}
private void deselect(int position) {
mSelectedPosition = NONE;
notifyItemChanged(position);
mDoneButton.setEnabled(false);
}
}
private static class AvatarViewHolder extends RecyclerView.ViewHolder {
private final ImageView mImageView;
AvatarViewHolder(View view) {
super(view);
mImageView = view.findViewById(R.id.avatar_image);
}
public void setDrawable(Drawable drawable) {
mImageView.setImageDrawable(drawable);
}
public void setClickListener(View.OnClickListener listener) {
mImageView.setOnClickListener(listener);
}
public void setSelected(boolean selected) {
mImageView.setSelected(selected);
}
}
}

View File

@@ -25,6 +25,7 @@ import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
@@ -36,6 +37,8 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.util.UserIcons;
import com.android.settingslib.R;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.drawable.CircleFramedDrawable;
import java.io.File;
@@ -139,12 +142,20 @@ public class EditUserInfoController {
Drawable userIcon = getUserIcon(activity, defaultUserIcon);
userPhotoView.setImageDrawable(userIcon);
if (canChangePhoto(activity)) {
mEditUserPhotoController = createEditUserPhotoController(activity, activityStarter,
userPhotoView);
} else {
// some users can't change their photos, so we need to remove the suggestive icon
if (isChangePhotoRestrictedByBase(activity)) {
// some users can't change their photos so we need to remove the suggestive icon
content.findViewById(R.id.add_a_photo_icon).setVisibility(View.GONE);
} else {
RestrictedLockUtils.EnforcedAdmin adminRestriction =
getChangePhotoAdminRestriction(activity);
if (adminRestriction != null) {
userPhotoView.setOnClickListener(view ->
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
activity, adminRestriction));
} else {
mEditUserPhotoController = createEditUserPhotoController(activity, activityStarter,
userPhotoView);
}
}
mEditUserInfoDialog = buildDialog(activity, content, userNameView, oldUserIcon,
@@ -203,10 +214,15 @@ public class EditUserInfoController {
}
@VisibleForTesting
boolean canChangePhoto(Context context) {
return (PhotoCapabilityUtils.canCropPhoto(context)
&& PhotoCapabilityUtils.canChoosePhoto(context))
|| PhotoCapabilityUtils.canTakePhoto(context);
boolean isChangePhotoRestrictedByBase(Context context) {
return RestrictedLockUtilsInternal.hasBaseUserRestriction(
context, UserManager.DISALLOW_SET_USER_ICON, UserHandle.myUserId());
}
@VisibleForTesting
RestrictedLockUtils.EnforcedAdmin getChangePhotoAdminRestriction(Context context) {
return RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
context, UserManager.DISALLOW_SET_USER_ICON, UserHandle.myUserId());
}
@VisibleForTesting

View File

@@ -21,6 +21,8 @@ import android.content.ClipData;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
@@ -29,6 +31,7 @@ import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.net.Uri;
@@ -78,6 +81,7 @@ public class EditUserPhotoController {
private static final int REQUEST_CODE_CHOOSE_PHOTO = 1001;
private static final int REQUEST_CODE_TAKE_PHOTO = 1002;
private static final int REQUEST_CODE_CROP_PHOTO = 1003;
private static final int REQUEST_CODE_PICK_AVATAR = 1004;
// in rare cases we get a null Cursor when querying for DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI
// so we need a default photo size
private static final int DEFAULT_PHOTO_SIZE = 500;
@@ -113,7 +117,7 @@ public class EditUserPhotoController {
mCropPictureUri = createTempImageUri(activity, CROP_PICTURE_FILE_NAME, !waiting);
mTakePictureUri = createTempImageUri(activity, TAKE_PICTURE_FILE_NAME, !waiting);
mPhotoSize = getPhotoSize(activity);
mImageView.setOnClickListener(v -> showUpdatePhotoPopup());
mImageView.setOnClickListener(v -> showAvatarPicker());
mNewUserPhotoBitmap = bitmap;
}
@@ -151,6 +155,18 @@ public class EditUserPhotoController {
copyAndCropPhoto(pictureUri);
}
return true;
case REQUEST_CODE_PICK_AVATAR:
int index = data.getIntExtra(AvatarPickerActivity.EXTRA_AVATAR_INDEX, -1);
Resources res = mImageView.getContext().getResources();
try (TypedArray avatarImages = res.obtainTypedArray(R.array.avatar_images)) {
if (index >= 0 && index < avatarImages.length()) {
Drawable drawable = avatarImages.getDrawable(index);
if (!(drawable instanceof BitmapDrawable)) {
return false;
}
onPhotoProcessed(((BitmapDrawable) drawable).getBitmap());
}
}
}
return false;
}
@@ -159,6 +175,11 @@ public class EditUserPhotoController {
return mNewUserPhotoDrawable;
}
private void showAvatarPicker() {
Intent intent = new Intent(mImageView.getContext(), AvatarPickerActivity.class);
mActivityStarter.startActivityForResult(intent, REQUEST_CODE_PICK_AVATAR);
}
private void showUpdatePhotoPopup() {
final Context context = mImageView.getContext();
final boolean canTakePhoto = PhotoCapabilityUtils.canTakePhoto(context);

View File

@@ -62,7 +62,7 @@ public class EditUserInfoControllerTest {
@Mock
private ActivityStarter mActivityStarter;
private boolean mCanChangePhoto;
private boolean mPhotoRestrictedByBase;
private Activity mActivity;
private TestEditUserInfoController mController;
@@ -85,8 +85,8 @@ public class EditUserInfoControllerTest {
}
@Override
boolean canChangePhoto(Context context) {
return mCanChangePhoto;
boolean isChangePhotoRestrictedByBase(Context context) {
return mPhotoRestrictedByBase;
}
}
@@ -96,7 +96,7 @@ public class EditUserInfoControllerTest {
mActivity = spy(ActivityController.of(new FragmentActivity()).get());
mActivity.setTheme(R.style.Theme_AppCompat_DayNight);
mController = new TestEditUserInfoController();
mCanChangePhoto = true;
mPhotoRestrictedByBase = true;
}
@Test
@@ -260,7 +260,7 @@ public class EditUserInfoControllerTest {
@Test
public void createDialog_canNotChangePhoto_nullPhotoController() {
mCanChangePhoto = false;
mPhotoRestrictedByBase = false;
mController.createDialog(mActivity, mActivityStarter, mCurrentIcon,
"test", "title", null, null);