parent
fb9f16ad29
commit
296796eb54
@ -0,0 +1,24 @@
|
|||||||
|
<!--
|
||||||
|
Copyright 2013 Google Inc.
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="@dimen/color_grid_item_size"
|
||||||
|
android:layout_height="@dimen/color_grid_item_size">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/color_view"
|
||||||
|
android:layout_width="36dp"
|
||||||
|
android:layout_height="36dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:scaleType="fitXY" />
|
||||||
|
</FrameLayout>
|
@ -0,0 +1,21 @@
|
|||||||
|
<!--
|
||||||
|
Copyright 2013 Google Inc.
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<android.support.v7.widget.GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/color_grid"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:orientation="horizontal"
|
||||||
|
app:columnCount="5"/>
|
@ -0,0 +1,292 @@
|
|||||||
|
package org.thoughtcrime.securesms.preferences;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Google Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.GradientDrawable;
|
||||||
|
import android.graphics.drawable.LayerDrawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.Preference;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v7.widget.GridLayout;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A preference that allows the user to choose an application or shortcut.
|
||||||
|
*/
|
||||||
|
public class ColorPreference extends Preference {
|
||||||
|
private int[] mColorChoices = {};
|
||||||
|
private int mValue = 0;
|
||||||
|
private int mItemLayoutId = R.layout.color_preference_item;
|
||||||
|
private int mNumColumns = 5;
|
||||||
|
private View mPreviewView;
|
||||||
|
|
||||||
|
public ColorPreference(Context context) {
|
||||||
|
super(context);
|
||||||
|
initAttrs(null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPreference(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
initAttrs(attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
initAttrs(attrs, defStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initAttrs(AttributeSet attrs, int defStyle) {
|
||||||
|
TypedArray a = getContext().getTheme().obtainStyledAttributes(
|
||||||
|
attrs, R.styleable.ColorPreference, defStyle, defStyle);
|
||||||
|
|
||||||
|
try {
|
||||||
|
mItemLayoutId = a.getResourceId(R.styleable.ColorPreference_itemLayout, mItemLayoutId);
|
||||||
|
mNumColumns = a.getInteger(R.styleable.ColorPreference_numColumns, mNumColumns);
|
||||||
|
int choicesResId = a.getResourceId(R.styleable.ColorPreference_choices,
|
||||||
|
R.array.default_color_choice_values);
|
||||||
|
if (choicesResId > 0) {
|
||||||
|
String[] choices = a.getResources().getStringArray(choicesResId);
|
||||||
|
mColorChoices = new int[choices.length];
|
||||||
|
for (int i = 0; i < choices.length; i++) {
|
||||||
|
mColorChoices[i] = Color.parseColor(choices[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
a.recycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
setWidgetLayoutResource(mItemLayoutId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onBindView(View view) {
|
||||||
|
super.onBindView(view);
|
||||||
|
mPreviewView = view.findViewById(R.id.color_view);
|
||||||
|
setColorViewValue(mPreviewView, mValue, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(int value) {
|
||||||
|
if (callChangeListener(value)) {
|
||||||
|
mValue = value;
|
||||||
|
persistInt(value);
|
||||||
|
notifyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onClick() {
|
||||||
|
super.onClick();
|
||||||
|
|
||||||
|
ColorDialogFragment fragment = ColorDialogFragment.newInstance();
|
||||||
|
fragment.setPreference(this);
|
||||||
|
|
||||||
|
((AppCompatActivity) getContext()).getSupportFragmentManager().beginTransaction()
|
||||||
|
.add(fragment, getFragmentTag())
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onAttachedToActivity() {
|
||||||
|
super.onAttachedToActivity();
|
||||||
|
|
||||||
|
AppCompatActivity activity = (AppCompatActivity) getContext();
|
||||||
|
ColorDialogFragment fragment = (ColorDialogFragment) activity
|
||||||
|
.getSupportFragmentManager().findFragmentByTag(getFragmentTag());
|
||||||
|
if (fragment != null) {
|
||||||
|
// re-bind preference to fragment
|
||||||
|
fragment.setPreference(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object onGetDefaultValue(TypedArray a, int index) {
|
||||||
|
return a.getInt(index, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
|
||||||
|
setValue(restoreValue ? getPersistedInt(0) : (Integer) defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFragmentTag() {
|
||||||
|
return "color_" + getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return mValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ColorDialogFragment extends android.support.v4.app.DialogFragment {
|
||||||
|
private ColorPreference mPreference;
|
||||||
|
private GridLayout mColorGrid;
|
||||||
|
|
||||||
|
public ColorDialogFragment() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ColorDialogFragment newInstance() {
|
||||||
|
return new ColorDialogFragment();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPreference(ColorPreference preference) {
|
||||||
|
mPreference = preference;
|
||||||
|
repopulateItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Activity activity) {
|
||||||
|
super.onAttach(activity);
|
||||||
|
repopulateItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
|
||||||
|
View rootView = layoutInflater.inflate(R.layout.color_preference_items, null);
|
||||||
|
|
||||||
|
mColorGrid = (GridLayout) rootView.findViewById(R.id.color_grid);
|
||||||
|
mColorGrid.setColumnCount(mPreference.mNumColumns);
|
||||||
|
repopulateItems();
|
||||||
|
|
||||||
|
return new AlertDialog.Builder(getActivity())
|
||||||
|
.setView(rootView)
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void repopulateItems() {
|
||||||
|
if (mPreference == null || mColorGrid == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context context = mColorGrid.getContext();
|
||||||
|
mColorGrid.removeAllViews();
|
||||||
|
for (final int color : mPreference.mColorChoices) {
|
||||||
|
View itemView = LayoutInflater.from(context)
|
||||||
|
.inflate(R.layout.color_preference_item, mColorGrid, false);
|
||||||
|
|
||||||
|
setColorViewValue(itemView.findViewById(R.id.color_view), color,
|
||||||
|
color == mPreference.getValue());
|
||||||
|
itemView.setClickable(true);
|
||||||
|
itemView.setFocusable(true);
|
||||||
|
itemView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
mPreference.setValue(color);
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mColorGrid.addView(itemView);
|
||||||
|
}
|
||||||
|
|
||||||
|
sizeDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
sizeDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sizeDialog() {
|
||||||
|
if (mPreference == null || mColorGrid == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog dialog = getDialog();
|
||||||
|
if (dialog == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Resources res = mColorGrid.getContext().getResources();
|
||||||
|
DisplayMetrics dm = res.getDisplayMetrics();
|
||||||
|
|
||||||
|
// Can't use Integer.MAX_VALUE here (weird issue observed otherwise on 4.2)
|
||||||
|
mColorGrid.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(dm.widthPixels, View.MeasureSpec.AT_MOST),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(dm.heightPixels, View.MeasureSpec.AT_MOST));
|
||||||
|
int width = mColorGrid.getMeasuredWidth();
|
||||||
|
int height = mColorGrid.getMeasuredHeight();
|
||||||
|
|
||||||
|
int extraPadding = res.getDimensionPixelSize(R.dimen.color_grid_extra_padding);
|
||||||
|
|
||||||
|
width += extraPadding;
|
||||||
|
height += extraPadding;
|
||||||
|
|
||||||
|
dialog.getWindow().setLayout(width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setColorViewValue(View view, int color, boolean selected) {
|
||||||
|
if (view instanceof ImageView) {
|
||||||
|
ImageView imageView = (ImageView) view;
|
||||||
|
Resources res = imageView.getContext().getResources();
|
||||||
|
|
||||||
|
Drawable currentDrawable = imageView.getDrawable();
|
||||||
|
GradientDrawable colorChoiceDrawable;
|
||||||
|
if (currentDrawable instanceof GradientDrawable) {
|
||||||
|
// Reuse drawable
|
||||||
|
colorChoiceDrawable = (GradientDrawable) currentDrawable;
|
||||||
|
} else {
|
||||||
|
colorChoiceDrawable = new GradientDrawable();
|
||||||
|
colorChoiceDrawable.setShape(GradientDrawable.OVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set stroke to dark version of color
|
||||||
|
// int darkenedColor = Color.rgb(
|
||||||
|
// Color.red(color) * 192 / 256,
|
||||||
|
// Color.green(color) * 192 / 256,
|
||||||
|
// Color.blue(color) * 192 / 256);
|
||||||
|
|
||||||
|
colorChoiceDrawable.setColor(color);
|
||||||
|
// colorChoiceDrawable.setStroke((int) TypedValue.applyDimension(
|
||||||
|
// TypedValue.COMPLEX_UNIT_DIP, 2, res.getDisplayMetrics()), darkenedColor);
|
||||||
|
|
||||||
|
Drawable drawable = colorChoiceDrawable;
|
||||||
|
if (selected) {
|
||||||
|
BitmapDrawable checkmark = (BitmapDrawable) res.getDrawable(R.drawable.check);
|
||||||
|
checkmark.setGravity(Gravity.CENTER);
|
||||||
|
drawable = new LayerDrawable(new Drawable[]{
|
||||||
|
colorChoiceDrawable,
|
||||||
|
checkmark});
|
||||||
|
}
|
||||||
|
|
||||||
|
imageView.setImageDrawable(drawable);
|
||||||
|
|
||||||
|
} else if (view instanceof TextView) {
|
||||||
|
((TextView) view).setTextColor(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue