From 2145426e3c1e8544418a4eee029b6e8c6c16829d Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Sun, 22 Dec 2013 17:28:17 +0800 Subject: [PATCH] improved color picker --- res/layout/color_picker.xml | 15 +- res/layout/color_picker_preset_item.xml | 19 +- res/menu/action_user_profile.xml | 32 +-- res/menu/menu_status.xml | 30 +-- res/values/dimens.xml | 6 +- res/values/ids.xml | 1 - .../scvngr/levelup/views/gallery/Gallery.java | 8 - src/org/mariotaku/twidere/Constants.java | 1 - .../mariotaku/twidere/TwidereConstants.java | 1 + .../support/ColorPickerDialogActivity.java | 13 +- .../activity/support/ComposeActivity.java | 1 - .../activity/support/SignInActivity.java | 7 +- .../fragment/dialog/ColorPickerDialog.java | 183 +++++++++++++++ .../support/AccountsDrawerFragment.java | 3 +- .../support/ColorPickerDialogFragment.java | 89 ++------ .../SetUserNicknameDialogFragment.java | 28 ++- .../fragment/support/StatusFragment.java | 17 +- .../fragment/support/UserProfileFragment.java | 10 +- .../twidere/graphic/AlphaPatternDrawable.java | 26 +-- .../twidere/graphic/ColorPreviewDrawable.java | 50 +++++ .../preference/ColorPickerPreference.java | 86 +++---- .../twidere/provider/TwidereDataProvider.java | 15 +- .../twidere/view/ColorPickerPresetsView.java | 54 ----- .../twidere/view/ColorPickerView.java | 110 ++++----- src/org/mariotaku/twidere/view/ColorView.java | 47 ---- .../twidere/view/ForegroundColorView.java | 156 +++++++++++++ .../twidere/view/ForegroundImageView.java | 161 ++------------ .../twidere/view/HandleSpanClickTextView.java | 5 +- .../twidere/view/iface/IForegroundView.java | 209 ++++++++++++++++++ 29 files changed, 815 insertions(+), 568 deletions(-) create mode 100644 src/org/mariotaku/twidere/fragment/dialog/ColorPickerDialog.java create mode 100644 src/org/mariotaku/twidere/graphic/ColorPreviewDrawable.java delete mode 100644 src/org/mariotaku/twidere/view/ColorPickerPresetsView.java delete mode 100644 src/org/mariotaku/twidere/view/ColorView.java create mode 100644 src/org/mariotaku/twidere/view/ForegroundColorView.java create mode 100644 src/org/mariotaku/twidere/view/iface/IForegroundView.java diff --git a/res/layout/color_picker.xml b/res/layout/color_picker.xml index 545b3501..19152f86 100644 --- a/res/layout/color_picker.xml +++ b/res/layout/color_picker.xml @@ -12,16 +12,11 @@ android:layout_height="wrap_content" android:layout_weight="1"/> - - - - + android:layout_height="@dimen/button_bar_height" + android:layout_weight="0" + android:spacing="0dp"/> \ No newline at end of file diff --git a/res/layout/color_picker_preset_item.xml b/res/layout/color_picker_preset_item.xml index 898382a5..8529b9ce 100644 --- a/res/layout/color_picker_preset_item.xml +++ b/res/layout/color_picker_preset_item.xml @@ -1,6 +1,17 @@ - + android:padding="@dimen/element_spacing_extra_small"> + + + + \ No newline at end of file diff --git a/res/menu/action_user_profile.xml b/res/menu/action_user_profile.xml index fa1a8be9..b0b57bef 100644 --- a/res/menu/action_user_profile.xml +++ b/res/menu/action_user_profile.xml @@ -15,35 +15,13 @@ android:icon="@android:drawable/ic_menu_add" android:title="@string/add_to_list"/> - - - - - - + - - - - - + android:title="@string/set_nickname"/> - - - - - + android:title="@string/set_color"/> - - - - - + android:title="@string/set_nickname"/> 20dp - 36dp + 48dp + 48dp 400dp @@ -56,4 +57,7 @@ 64dp + + 32dp + \ No newline at end of file diff --git a/res/values/ids.xml b/res/values/ids.xml index 85637cb3..f58e36e0 100644 --- a/res/values/ids.xml +++ b/res/values/ids.xml @@ -47,7 +47,6 @@ - diff --git a/src/com/scvngr/levelup/views/gallery/Gallery.java b/src/com/scvngr/levelup/views/gallery/Gallery.java index 4a453ed1..e9d1a9e5 100644 --- a/src/com/scvngr/levelup/views/gallery/Gallery.java +++ b/src/com/scvngr/levelup/views/gallery/Gallery.java @@ -179,7 +179,6 @@ public void run() { private boolean mIsRtl = true; private boolean mScrollToChildAfterItemClickEnabled; - private boolean mScrollWhenChildsLesserThanItems; private boolean mRightSpacingEnabled; /** @@ -214,7 +213,6 @@ public Gallery(final Context context, final AttributeSet attrs, final int defSty mGestureDetector = new GestureDetector(context, this); mGestureDetector.setIsLongpressEnabled(true); setScrollAfterItemClickEnabled(true); - setScrollWhenChildsLesserThanItems(true); setScrollRightSpacingEnabled(true); } @@ -504,10 +502,6 @@ public void setScrollRightSpacingEnabled(final boolean enabled) { mRightSpacingEnabled = enabled; } - public void setScrollWhenChildsLesserThanItems(final boolean enabled) { - mScrollWhenChildsLesserThanItems = enabled; - } - /** * Sets the spacing between items in a Gallery. * @@ -1367,8 +1361,6 @@ void trackMotionScroll(final int deltaX) { if (getChildCount() == 0) return; - if (!mScrollWhenChildsLesserThanItems && mAdapter != null && getChildCount() >= mAdapter.getCount()) return; - final boolean toLeft = deltaX < 0; final int limitedDeltaX = getLimitedMotionScrollAmount(toLeft, deltaX); diff --git a/src/org/mariotaku/twidere/Constants.java b/src/org/mariotaku/twidere/Constants.java index 3e4ba11d..fb6bc64e 100644 --- a/src/org/mariotaku/twidere/Constants.java +++ b/src/org/mariotaku/twidere/Constants.java @@ -79,7 +79,6 @@ public interface Constants extends TwidereConstants { public static final int MENU_UP = R.id.up; public static final int MENU_DOWN = R.id.down; public static final int MENU_MULTI_SELECT = R.id.multi_select; - public static final int MENU_CLEAR_COLOR = R.id.clear_color; public static final int MENU_COPY = R.id.copy; public static final int MENU_TOGGLE_SENSITIVE = R.id.toggle_sensitive; public static final int MENU_REVOKE = R.id.revoke; diff --git a/src/org/mariotaku/twidere/TwidereConstants.java b/src/org/mariotaku/twidere/TwidereConstants.java index 5466d890..9b585999 100644 --- a/src/org/mariotaku/twidere/TwidereConstants.java +++ b/src/org/mariotaku/twidere/TwidereConstants.java @@ -490,6 +490,7 @@ public interface TwidereConstants { public static final String EXTRA_RECIPIENT_ID = "recipient_id"; public static final String EXTRA_OFFICIAL_KEY_ONLY = "official_key_only"; public static final String EXTRA_SEARCH_ID = "search_id"; + public static final String EXTRA_CLEAR_BUTTON = "clear_button"; public static final int MENU_GROUP_STATUS_EXTENSION = 10; public static final int MENU_GROUP_COMPOSE_EXTENSION = 11; diff --git a/src/org/mariotaku/twidere/activity/support/ColorPickerDialogActivity.java b/src/org/mariotaku/twidere/activity/support/ColorPickerDialogActivity.java index f67b894d..1d31e075 100644 --- a/src/org/mariotaku/twidere/activity/support/ColorPickerDialogActivity.java +++ b/src/org/mariotaku/twidere/activity/support/ColorPickerDialogActivity.java @@ -25,16 +25,24 @@ import android.os.Bundle; import org.mariotaku.twidere.fragment.support.ColorPickerDialogFragment; -import org.mariotaku.twidere.fragment.support.ColorPickerDialogFragment.OnColorSelectedListener; +import org.mariotaku.twidere.fragment.support.ColorPickerDialogFragment.Callback; import org.mariotaku.twidere.util.ThemeUtils; -public class ColorPickerDialogActivity extends BaseSupportDialogActivity implements OnColorSelectedListener { +public class ColorPickerDialogActivity extends BaseSupportDialogActivity implements Callback { + + public static final int RESULT_CLEARED = -2; @Override public int getThemeResourceId() { return ThemeUtils.getNoDisplayThemeResource(this); } + @Override + public void onColorCleared() { + setResult(RESULT_CLEARED); + finish(); + } + @Override public void onColorSelected(final int color) { final Intent intent = new Intent(); @@ -51,6 +59,7 @@ protected void onCreate(final Bundle savedInstanceState) { final InternalColorPickerDialogFragment f = new InternalColorPickerDialogFragment(); final Bundle args = new Bundle(); args.putInt(EXTRA_COLOR, intent.getIntExtra(EXTRA_COLOR, Color.WHITE)); + args.putBoolean(EXTRA_CLEAR_BUTTON, intent.getBooleanExtra(EXTRA_CLEAR_BUTTON, false)); args.putBoolean(EXTRA_ALPHA_SLIDER, intent.getBooleanExtra(EXTRA_ALPHA_SLIDER, true)); f.setArguments(args); f.show(getSupportFragmentManager(), "color_picker_dialog"); diff --git a/src/org/mariotaku/twidere/activity/support/ComposeActivity.java b/src/org/mariotaku/twidere/activity/support/ComposeActivity.java index 2d69f9ba..3b6cf8b4 100644 --- a/src/org/mariotaku/twidere/activity/support/ComposeActivity.java +++ b/src/org/mariotaku/twidere/activity/support/ComposeActivity.java @@ -562,7 +562,6 @@ protected void onCreate(final Bundle savedInstanceState) { mAccountSelector.setOnItemClickListener(this); mAccountSelector.setOnItemLongClickListener(this); mAccountSelector.setScrollAfterItemClickEnabled(false); - mAccountSelector.setScrollWhenChildsLesserThanItems(false); mAccountSelector.setScrollRightSpacingEnabled(false); final Intent intent = getIntent(); diff --git a/src/org/mariotaku/twidere/activity/support/SignInActivity.java b/src/org/mariotaku/twidere/activity/support/SignInActivity.java index fe70d798..f9f905dc 100644 --- a/src/org/mariotaku/twidere/activity/support/SignInActivity.java +++ b/src/org/mariotaku/twidere/activity/support/SignInActivity.java @@ -144,8 +144,10 @@ public void onActivityResult(final int requestCode, final int resultCode, final break; } case REQUEST_SET_COLOR: { - if (resultCode == BaseSupportActivity.RESULT_OK && data != null) { - mUserColor = data.getIntExtra(EXTRA_COLOR, Color.TRANSPARENT); + if (resultCode == BaseSupportActivity.RESULT_OK) { + mUserColor = data != null ? data.getIntExtra(EXTRA_COLOR, Color.TRANSPARENT) : null; + } else if (resultCode == ColorPickerDialogActivity.RESULT_CLEARED) { + mUserColor = null; } setUserColorButton(); break; @@ -193,6 +195,7 @@ public void onClick(final View v) { intent.putExtra(EXTRA_COLOR, mUserColor); } intent.putExtra(EXTRA_ALPHA_SLIDER, false); + intent.putExtra(EXTRA_CLEAR_BUTTON, true); startActivityForResult(intent, REQUEST_SET_COLOR); break; } diff --git a/src/org/mariotaku/twidere/fragment/dialog/ColorPickerDialog.java b/src/org/mariotaku/twidere/fragment/dialog/ColorPickerDialog.java new file mode 100644 index 00000000..d012113c --- /dev/null +++ b/src/org/mariotaku/twidere/fragment/dialog/ColorPickerDialog.java @@ -0,0 +1,183 @@ +package org.mariotaku.twidere.fragment.dialog; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.scvngr.levelup.views.gallery.AdapterView; +import com.scvngr.levelup.views.gallery.AdapterView.OnItemClickListener; +import com.scvngr.levelup.views.gallery.Gallery; + +import org.mariotaku.twidere.Constants; +import org.mariotaku.twidere.R; +import org.mariotaku.twidere.adapter.ArrayAdapter; +import org.mariotaku.twidere.view.ColorPickerView; +import org.mariotaku.twidere.view.ColorPickerView.OnColorChangedListener; +import org.mariotaku.twidere.view.ForegroundColorView; + +public final class ColorPickerDialog extends AlertDialog implements OnItemClickListener, OnColorChangedListener, + Constants { + + private final static int[] COLORS = { HOLO_RED_DARK, HOLO_RED_LIGHT, HOLO_ORANGE_DARK, HOLO_ORANGE_LIGHT, + HOLO_GREEN_LIGHT, HOLO_GREEN_DARK, HOLO_BLUE_LIGHT, HOLO_BLUE_DARK, HOLO_PURPLE_DARK, HOLO_PURPLE_LIGHT, + Color.WHITE }; + + private final ColorsAdapter mColorsAdapter; + + private ColorPickerView mColorPicker; + private Gallery mColorPresets; + + private final Resources mResources; + + private final Bitmap mTempBitmap; + private final Canvas mCanvas; + + private final int mIconWidth, mIconHeight; + private final int mRectrangleSize, mNumRectanglesHorizontal, mNumRectanglesVertical; + + public ColorPickerDialog(final Context context, final int initialColor, final boolean showAlphaSlider) { + super(context); + mColorsAdapter = new ColorsAdapter(context); + mResources = context.getResources(); + final float density = mResources.getDisplayMetrics().density; + mIconWidth = (int) (32 * density); + mIconHeight = (int) (32 * density); + mRectrangleSize = (int) (density * 5); + mNumRectanglesHorizontal = (int) Math.ceil(mIconWidth / mRectrangleSize); + mNumRectanglesVertical = (int) Math.ceil(mIconHeight / mRectrangleSize); + mTempBitmap = Bitmap.createBitmap(mIconWidth, mIconHeight, Config.ARGB_8888); + mCanvas = new Canvas(mTempBitmap); + init(context, initialColor, showAlphaSlider); + initColors(); + mColorsAdapter.setCurrentColor(initialColor); + } + + public int getColor() { + return mColorPicker.getColor(); + } + + @Override + public void onColorChanged(final int color) { + mColorsAdapter.setCurrentColor(color); + updateColorPreviewBitmap(color); + setIcon(new BitmapDrawable(mResources, mTempBitmap)); + } + + @Override + public void onItemClick(final AdapterView parent, final View view, final int position, final long id) { + final int color = mColorsAdapter.getItem(position); + if (mColorPicker == null) return; + mColorPicker.setColor(color, true); + } + + public final void setAlphaSliderVisible(final boolean visible) { + mColorPicker.setAlphaSliderVisible(visible); + } + + public final void setColor(final int color) { + mColorPicker.setColor(color); + } + + public final void setColor(final int color, final boolean callback) { + mColorPicker.setColor(color, callback); + } + + private void init(final Context context, final int color, final boolean showAlphaSlider) { + + // To fight color branding. + getWindow().setFormat(PixelFormat.RGBA_8888); + + final LayoutInflater inflater = LayoutInflater.from(getContext()); + final View dialogView = inflater.inflate(R.layout.color_picker, null); + + mColorPicker = (ColorPickerView) dialogView.findViewById(R.id.color_picker); + mColorPresets = (Gallery) dialogView.findViewById(R.id.color_presets); + + mColorPicker.setOnColorChangedListener(this); + mColorPresets.setAdapter(mColorsAdapter); + mColorPresets.setOnItemClickListener(this); + mColorPresets.setScrollAfterItemClickEnabled(false); + mColorPresets.setScrollRightSpacingEnabled(false); + + setColor(color, true); + setAlphaSliderVisible(showAlphaSlider); + + setView(dialogView); + setTitle(R.string.pick_color); + } + + private void initColors() { + for (final int color : COLORS) { + mColorsAdapter.add(color); + } + } + + private void updateColorPreviewBitmap(final int color) { + final Rect r = new Rect(); + boolean verticalStartWhite = true; + for (int i = 0; i <= mNumRectanglesVertical; i++) { + + boolean isWhite = verticalStartWhite; + for (int j = 0; j <= mNumRectanglesHorizontal; j++) { + + r.top = i * mRectrangleSize; + r.left = j * mRectrangleSize; + r.bottom = r.top + mRectrangleSize; + r.right = r.left + mRectrangleSize; + final Paint paint = new Paint(); + paint.setColor(isWhite ? Color.WHITE : Color.GRAY); + + mCanvas.drawRect(r, paint); + + isWhite = !isWhite; + } + + verticalStartWhite = !verticalStartWhite; + + } + mCanvas.drawColor(color); + final Paint paint = new Paint(); + paint.setColor(Color.WHITE); + paint.setStrokeWidth(2.0f); + final float[] points = new float[] { 0, 0, mIconWidth, 0, 0, 0, 0, mIconHeight, mIconWidth, 0, mIconWidth, + mIconHeight, 0, mIconHeight, mIconWidth, mIconHeight }; + mCanvas.drawLines(points, paint); + + } + + public static class ColorsAdapter extends ArrayAdapter { + + private int mCurrentColor; + + public ColorsAdapter(final Context context) { + super(context, R.layout.color_picker_preset_item); + } + + @Override + public View getView(final int position, final View convertView, final ViewGroup parent) { + final View view = super.getView(position, convertView, parent); + final ForegroundColorView colorView = (ForegroundColorView) view.findViewById(R.id.color); + final int color = getItem(position); + colorView.setColor(color); + colorView.setActivated(mCurrentColor == color); + return view; + } + + public void setCurrentColor(final int color) { + mCurrentColor = color; + notifyDataSetChanged(); + } + + } +} \ No newline at end of file diff --git a/src/org/mariotaku/twidere/fragment/support/AccountsDrawerFragment.java b/src/org/mariotaku/twidere/fragment/support/AccountsDrawerFragment.java index 2abdfd40..0c7ef5ea 100644 --- a/src/org/mariotaku/twidere/fragment/support/AccountsDrawerFragment.java +++ b/src/org/mariotaku/twidere/fragment/support/AccountsDrawerFragment.java @@ -93,7 +93,8 @@ public void onActivityCreated(final Bundle savedInstanceState) { public void onActivityResult(final int requestCode, final int resultCode, final Intent data) { switch (requestCode) { case REQUEST_SET_COLOR: { - if (resultCode == Activity.RESULT_OK && data != null) { + if (resultCode == Activity.RESULT_OK) { + if (data == null) return; final ContentValues values = new ContentValues(); values.put(Accounts.COLOR, data.getIntExtra(EXTRA_COLOR, Color.WHITE)); final String where = Accounts.ACCOUNT_ID + " = " + mAdapter.getSelectedAccountId(); diff --git a/src/org/mariotaku/twidere/fragment/support/ColorPickerDialogFragment.java b/src/org/mariotaku/twidere/fragment/support/ColorPickerDialogFragment.java index 6b9eee34..8086422f 100644 --- a/src/org/mariotaku/twidere/fragment/support/ColorPickerDialogFragment.java +++ b/src/org/mariotaku/twidere/fragment/support/ColorPickerDialogFragment.java @@ -19,23 +19,14 @@ package org.mariotaku.twidere.fragment.support; -import android.app.AlertDialog; import android.app.Dialog; -import android.content.Context; import android.content.DialogInterface; import android.graphics.Color; -import android.graphics.PixelFormat; -import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.support.v4.app.FragmentActivity; -import android.view.LayoutInflater; -import android.view.View; import org.mariotaku.twidere.R; -import org.mariotaku.twidere.view.ColorPickerPresetsView; -import org.mariotaku.twidere.view.ColorPickerPresetsView.OnColorClickListener; -import org.mariotaku.twidere.view.ColorPickerView; -import org.mariotaku.twidere.view.ColorPickerView.OnColorChangedListener; +import org.mariotaku.twidere.fragment.dialog.ColorPickerDialog; public class ColorPickerDialogFragment extends BaseSupportDialogFragment implements DialogInterface.OnClickListener { @@ -43,12 +34,17 @@ public class ColorPickerDialogFragment extends BaseSupportDialogFragment impleme public void onClick(final DialogInterface dialog, final int which) { final FragmentActivity a = getActivity(); final Dialog d = getDialog(); - if (!(a instanceof OnColorSelectedListener) || !(d instanceof ColorPickerDialog)) return; + if (!(a instanceof Callback) || !(d instanceof ColorPickerDialog)) return; switch (which) { - case DialogInterface.BUTTON_POSITIVE: + case DialogInterface.BUTTON_POSITIVE: { final int color = ((ColorPickerDialog) d).getColor(); - ((OnColorSelectedListener) a).onColorSelected(color); + ((Callback) a).onColorSelected(color); break; + } + case DialogInterface.BUTTON_NEUTRAL: { + ((Callback) a).onColorCleared(); + break; + } } } @@ -64,6 +60,9 @@ public Dialog onCreateDialog(final Bundle savedInstanceState) { final boolean showAlphaSlider = args.getBoolean(EXTRA_ALPHA_SLIDER, true); final ColorPickerDialog d = new ColorPickerDialog(getActivity(), color, showAlphaSlider); d.setButton(DialogInterface.BUTTON_POSITIVE, getString(android.R.string.ok), this); + if (args.getBoolean(EXTRA_CLEAR_BUTTON, false)) { + d.setButton(DialogInterface.BUTTON_NEUTRAL, getString(R.string.clear), this); + } d.setButton(DialogInterface.BUTTON_NEGATIVE, getString(android.R.string.cancel), this); return d; } @@ -77,69 +76,9 @@ public void onSaveInstanceState(final Bundle outState) { super.onSaveInstanceState(outState); } - public static final class ColorPickerDialog extends AlertDialog implements OnColorChangedListener, - OnColorClickListener { - - private ColorPickerView mColorPicker; - private ColorPickerPresetsView mColorPresets; - - public ColorPickerDialog(final Context context, final int initialColor, final boolean showAlphaSlider) { - super(context); - init(context, initialColor, showAlphaSlider); - } - - public int getColor() { - return mColorPicker.getColor(); - } - - @Override - public final void onColorChanged(final int color) { - final Context context = getContext(); - setIcon(new BitmapDrawable(context.getResources(), ColorPickerView.getColorPreviewBitmap(context, color))); - } - - @Override - public final void onColorClick(final int color) { - if (mColorPicker == null) return; - mColorPicker.setColor(color, true); - } - - public final void setAlphaSliderVisible(final boolean visible) { - mColorPicker.setAlphaSliderVisible(visible); - } - - public final void setColor(final int color) { - mColorPicker.setColor(color); - } - - public final void setColor(final int color, final boolean callback) { - mColorPicker.setColor(color, callback); - } - - private void init(final Context context, final int color, final boolean showAlphaSlider) { - - // To fight color branding. - getWindow().setFormat(PixelFormat.RGBA_8888); - - final LayoutInflater inflater = LayoutInflater.from(getContext()); - final View view = inflater.inflate(R.layout.color_picker, null); - - mColorPicker = (ColorPickerView) view.findViewById(R.id.color_picker); - mColorPresets = (ColorPickerPresetsView) view.findViewById(R.id.color_presets); - - mColorPicker.setOnColorChangedListener(this); - mColorPresets.setOnColorClickListener(this); - - setColor(color, true); - setAlphaSliderVisible(showAlphaSlider); - - setTitle(R.string.pick_color); - setView(view); - } - - } + public interface Callback { - public interface OnColorSelectedListener { + public void onColorCleared(); public void onColorSelected(int color); } diff --git a/src/org/mariotaku/twidere/fragment/support/SetUserNicknameDialogFragment.java b/src/org/mariotaku/twidere/fragment/support/SetUserNicknameDialogFragment.java index 575edb82..b5c2e1c7 100644 --- a/src/org/mariotaku/twidere/fragment/support/SetUserNicknameDialogFragment.java +++ b/src/org/mariotaku/twidere/fragment/support/SetUserNicknameDialogFragment.java @@ -27,22 +27,36 @@ public class SetUserNicknameDialogFragment extends BaseSupportDialogFragment imp public void onClick(final DialogInterface dialog, final int which) { final Bundle args = getArguments(); final String text = ParseUtils.parseString(mEditText.getText()); - final long user_id = args != null ? args.getLong(EXTRA_USER_ID, -1) : -1; - if (user_id == -1) return; - if (TextUtils.isEmpty(text)) { - clearUserNickname(getActivity(), user_id); - } else { - setUserNickname(getActivity(), user_id, text); + final long userId = args != null ? args.getLong(EXTRA_USER_ID, -1) : -1; + if (userId == -1) return; + switch (which) { + case DialogInterface.BUTTON_POSITIVE: { + if (TextUtils.isEmpty(text)) { + clearUserNickname(getActivity(), userId); + } else { + setUserNickname(getActivity(), userId, text); + } + break; + } + case DialogInterface.BUTTON_NEUTRAL: { + clearUserNickname(getActivity(), userId); + break; + } } + } @Override public Dialog onCreateDialog(final Bundle savedInstanceState) { final Bundle args = getArguments(); + final String nick = args.getString(EXTRA_NAME); final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity()); final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped); builder.setTitle(R.string.set_nickname); builder.setPositiveButton(android.R.string.ok, this); + if (!TextUtils.isEmpty(nick)) { + builder.setNeutralButton(R.string.clear, this); + } builder.setNegativeButton(android.R.string.cancel, null); final FrameLayout view = new FrameLayout(wrapped); mEditText = new EditText(wrapped); @@ -52,7 +66,7 @@ public Dialog onCreateDialog(final Bundle savedInstanceState) { R.dimen.element_spacing_default); view.addView(mEditText, lp); builder.setView(view); - mEditText.setText(args.getString(EXTRA_NAME)); + mEditText.setText(nick); return builder.create(); } diff --git a/src/org/mariotaku/twidere/fragment/support/StatusFragment.java b/src/org/mariotaku/twidere/fragment/support/StatusFragment.java index e7efb8d3..005b5cb4 100644 --- a/src/org/mariotaku/twidere/fragment/support/StatusFragment.java +++ b/src/org/mariotaku/twidere/fragment/support/StatusFragment.java @@ -465,9 +465,13 @@ public void onActivityCreated(final Bundle savedInstanceState) { public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) { switch (requestCode) { case REQUEST_SET_COLOR: { - if (resultCode == Activity.RESULT_OK && intent != null && mStatus != null) { + if (mStatus == null) return; + if (resultCode == Activity.RESULT_OK) { + if (intent == null) return; final int color = intent.getIntExtra(EXTRA_COLOR, Color.TRANSPARENT); setUserColor(getActivity(), mStatus.user_id, color); + } else if (resultCode == ColorPickerDialogActivity.RESULT_CLEARED) { + clearUserColor(getActivity(), mStatus.user_id); } break; } @@ -735,16 +739,15 @@ protected boolean handleMenuItemClick(final MenuItem item) { } case MENU_SET_COLOR: { final Intent intent = new Intent(getActivity(), ColorPickerDialogActivity.class); - intent.putExtra(EXTRA_COLOR, getUserColor(getActivity(), mStatus.user_id, true)); + final int color = getUserColor(getActivity(), mStatus.user_id, true); + if (color != 0) { + intent.putExtra(EXTRA_COLOR, color); + } + intent.putExtra(EXTRA_CLEAR_BUTTON, color != 0); intent.putExtra(EXTRA_ALPHA_SLIDER, false); startActivityForResult(intent, REQUEST_SET_COLOR); break; } - case MENU_CLEAR_COLOR: { - clearUserColor(getActivity(), mStatus.user_id); - displayStatus(mStatus); - break; - } case MENU_CLEAR_NICKNAME: { clearUserNickname(getActivity(), mStatus.user_id); displayStatus(mStatus); diff --git a/src/org/mariotaku/twidere/fragment/support/UserProfileFragment.java b/src/org/mariotaku/twidere/fragment/support/UserProfileFragment.java index f0cd69d5..0751f073 100644 --- a/src/org/mariotaku/twidere/fragment/support/UserProfileFragment.java +++ b/src/org/mariotaku/twidere/fragment/support/UserProfileFragment.java @@ -435,9 +435,12 @@ public void onActivityCreated(final Bundle savedInstanceState) { public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) { switch (requestCode) { case REQUEST_SET_COLOR: { - if (resultCode == Activity.RESULT_OK && intent != null) { + if (resultCode == Activity.RESULT_OK) { + if (intent == null) return; final int color = intent.getIntExtra(EXTRA_COLOR, Color.TRANSPARENT); setUserColor(getActivity(), mUserId, color); + } else if (resultCode == ColorPickerDialogActivity.RESULT_CLEARED) { + clearUserColor(getActivity(), mUserId); } break; } @@ -686,13 +689,10 @@ public boolean onMenuItemClick(final MenuItem item) { final Intent intent = new Intent(getActivity(), ColorPickerDialogActivity.class); intent.putExtra(EXTRA_COLOR, getUserColor(getActivity(), mUser.id, true)); intent.putExtra(EXTRA_ALPHA_SLIDER, false); + intent.putExtra(EXTRA_CLEAR_BUTTON, true); startActivityForResult(intent, REQUEST_SET_COLOR); break; } - case MENU_CLEAR_COLOR: { - clearUserColor(getActivity(), mUserId); - break; - } case MENU_CLEAR_NICKNAME: { clearUserNickname(getActivity(), mUser.id); break; diff --git a/src/org/mariotaku/twidere/graphic/AlphaPatternDrawable.java b/src/org/mariotaku/twidere/graphic/AlphaPatternDrawable.java index 83c69c1c..597a2f69 100644 --- a/src/org/mariotaku/twidere/graphic/AlphaPatternDrawable.java +++ b/src/org/mariotaku/twidere/graphic/AlphaPatternDrawable.java @@ -32,30 +32,30 @@ */ public class AlphaPatternDrawable extends Drawable { - private final int mRectangleSize; + private final int mAlphaPatternSize; - private int numRectanglesHorizontal; - private int numRectanglesVertical; + private int mNumRectanglesHorizontal; + private int mNumRectanglesVertical; private final Rect mRect = new Rect(), mBounds = new Rect(); private final Paint mPaint = new Paint(); - public AlphaPatternDrawable(final int rectangleSize) { - mRectangleSize = rectangleSize; + public AlphaPatternDrawable(final int alphaPatternSize) { + mAlphaPatternSize = alphaPatternSize; } @Override public void draw(final Canvas canvas) { boolean verticalStartWhite = true; - for (int i = 0; i <= numRectanglesVertical; i++) { + for (int i = 0; i <= mNumRectanglesVertical; i++) { boolean horizontalStartWhite = verticalStartWhite; - for (int j = 0; j <= numRectanglesHorizontal; j++) { + for (int j = 0; j <= mNumRectanglesHorizontal; j++) { mRect.setEmpty(); - mRect.top = i * mRectangleSize + mBounds.top; - mRect.left = j * mRectangleSize + mBounds.left; - mRect.bottom = Math.min(mRect.top + mRectangleSize, mBounds.bottom); - mRect.right = Math.min(mRect.left + mRectangleSize, mBounds.right); + mRect.top = i * mAlphaPatternSize + mBounds.top; + mRect.left = j * mAlphaPatternSize + mBounds.left; + mRect.bottom = Math.min(mRect.top + mAlphaPatternSize, mBounds.bottom); + mRect.right = Math.min(mRect.left + mAlphaPatternSize, mBounds.right); mPaint.setColor(horizontalStartWhite ? Color.WHITE : Color.GRAY); canvas.drawRect(mRect, mPaint); @@ -87,8 +87,8 @@ protected void onBoundsChange(final Rect bounds) { mBounds.set(bounds); final int height = bounds.height(); final int width = bounds.width(); - numRectanglesHorizontal = (int) Math.ceil(width / mRectangleSize); - numRectanglesVertical = (int) Math.ceil(height / mRectangleSize); + mNumRectanglesHorizontal = (int) Math.ceil(width / mAlphaPatternSize); + mNumRectanglesVertical = (int) Math.ceil(height / mAlphaPatternSize); invalidateSelf(); } diff --git a/src/org/mariotaku/twidere/graphic/ColorPreviewDrawable.java b/src/org/mariotaku/twidere/graphic/ColorPreviewDrawable.java new file mode 100644 index 00000000..3447b6dd --- /dev/null +++ b/src/org/mariotaku/twidere/graphic/ColorPreviewDrawable.java @@ -0,0 +1,50 @@ +package org.mariotaku.twidere.graphic; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; + +public class ColorPreviewDrawable extends AlphaPatternDrawable { + + private final int mColor; + private final Paint mPaint; + private final float[] mPoints; + + public ColorPreviewDrawable(final int alphaPatternSize, final int color) { + super(alphaPatternSize); + mPaint = new Paint(); + mPaint.setColor(Color.WHITE); + mPaint.setStrokeWidth(2.0f); + mColor = color; + mPoints = new float[16]; + } + + @Override + public void draw(final Canvas canvas) { + super.draw(canvas); + canvas.drawColor(mColor); + canvas.drawLines(mPoints, mPaint); + } + + @Override + protected void onBoundsChange(final Rect bounds) { + super.onBoundsChange(bounds); + mPoints[0] = bounds.top; + mPoints[1] = bounds.top; + mPoints[2] = bounds.right; + mPoints[3] = bounds.top; + mPoints[4] = bounds.top; + mPoints[5] = bounds.top; + mPoints[6] = bounds.top; + mPoints[7] = bounds.bottom; + mPoints[8] = bounds.right; + mPoints[9] = bounds.top; + mPoints[10] = bounds.right; + mPoints[11] = bounds.bottom; + mPoints[12] = bounds.top; + mPoints[13] = bounds.bottom; + mPoints[14] = bounds.right; + mPoints[15] = bounds.bottom; + } +} diff --git a/src/org/mariotaku/twidere/preference/ColorPickerPreference.java b/src/org/mariotaku/twidere/preference/ColorPickerPreference.java index 0ff4161f..99293be4 100644 --- a/src/org/mariotaku/twidere/preference/ColorPickerPreference.java +++ b/src/org/mariotaku/twidere/preference/ColorPickerPreference.java @@ -16,28 +16,22 @@ package org.mariotaku.twidere.preference; -import android.app.AlertDialog; -import android.app.AlertDialog.Builder; import android.content.Context; import android.content.DialogInterface; +import android.content.res.Resources; import android.graphics.Color; -import android.graphics.drawable.BitmapDrawable; -import android.preference.DialogPreference; +import android.preference.Preference; import android.util.AttributeSet; import android.util.Log; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; -import org.mariotaku.twidere.R; -import org.mariotaku.twidere.view.ColorPickerPresetsView; -import org.mariotaku.twidere.view.ColorPickerPresetsView.OnColorClickListener; +import org.mariotaku.twidere.Constants; +import org.mariotaku.twidere.fragment.dialog.ColorPickerDialog; import org.mariotaku.twidere.view.ColorPickerView; -import org.mariotaku.twidere.view.ColorPickerView.OnColorChangedListener; -public class ColorPickerPreference extends DialogPreference implements DialogInterface.OnClickListener, - OnColorChangedListener, OnColorClickListener { +public class ColorPickerPreference extends Preference implements DialogInterface.OnClickListener, Constants { private View mView; protected int mDefaultValue = Color.WHITE; @@ -48,8 +42,9 @@ public class ColorPickerPreference extends DialogPreference implements DialogInt private static final String ATTR_DEFAULTVALUE = "defaultValue"; private static final String ATTR_ALPHASLIDER = "alphaSlider"; - private ColorPickerView mColorPicker; - private ColorPickerPresetsView mColorPresets; + private final Resources mResources; + + private ColorPickerDialog mDialog; public ColorPickerPreference(final Context context, final AttributeSet attrs) { this(context, attrs, android.R.attr.preferenceStyle); @@ -57,15 +52,22 @@ public ColorPickerPreference(final Context context, final AttributeSet attrs) { public ColorPickerPreference(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - mDensity = context.getResources().getDisplayMetrics().density; + mResources = context.getResources(); + mDensity = mResources.getDisplayMetrics().density; init(context, attrs); } + public void onActivityDestroy() { + if (mDialog == null || !mDialog.isShowing()) return; + mDialog.dismiss(); + } + @Override public void onClick(final DialogInterface dialog, final int which) { switch (which) { case DialogInterface.BUTTON_POSITIVE: - final int color = mColorPicker.getColor(); + if (mDialog == null) return; + final int color = mDialog.getColor(); if (isPersistent()) { persistInt(color); } @@ -78,20 +80,6 @@ public void onClick(final DialogInterface dialog, final int which) { } } - @Override - public void onColorChanged(final int color) { - final AlertDialog dialog = (AlertDialog) getDialog(); - if (dialog == null) return; - final Context context = getContext(); - dialog.setIcon(new BitmapDrawable(context.getResources(), ColorPickerView.getColorPreviewBitmap(context, color))); - } - - @Override - public void onColorClick(final int color) { - if (mColorPicker == null) return; - mColorPicker.setColor(color, true); - } - @Override public void setDefaultValue(final Object value) { if (!(value instanceof Integer)) return; @@ -126,25 +114,13 @@ protected void onBindView(final View view) { } @Override - protected void onPrepareDialogBuilder(final Builder builder) { - super.onPrepareDialogBuilder(builder); - final Context context = getContext(); - final LayoutInflater inflater = LayoutInflater.from(getContext()); - final View view = inflater.inflate(R.layout.color_picker, null); - - final int val = getValue(); - - mColorPicker = (ColorPickerView) view.findViewById(R.id.color_picker); - mColorPresets = (ColorPickerPresetsView) view.findViewById(R.id.color_presets); - mColorPicker.setOnColorChangedListener(this); - mColorPresets.setOnColorClickListener(this); - - mColorPicker.setColor(val, true); - mColorPicker.setAlphaSliderVisible(mAlphaSliderEnabled); - builder.setView(view); - builder.setIcon(new BitmapDrawable(context.getResources(), ColorPickerView.getColorPreviewBitmap(context, val))); - builder.setPositiveButton(android.R.string.ok, this); - builder.setNegativeButton(android.R.string.cancel, null); + protected void onClick() { + if (mDialog != null && mDialog.isShowing()) return; + mDialog = new ColorPickerDialog(getContext(), getValue(), mAlphaSliderEnabled); + mDialog.setButton(DialogInterface.BUTTON_POSITIVE, mResources.getString(android.R.string.ok), this); + mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, mResources.getString(android.R.string.cancel), this); + mDialog.show(); + return; } @Override @@ -167,15 +143,15 @@ private void setPreviewColor() { if (mView == null) return; final View widget_frame_view = mView.findViewById(android.R.id.widget_frame); if (!(widget_frame_view instanceof ViewGroup)) return; - final ViewGroup widget_frame = (ViewGroup) widget_frame_view; - widget_frame.setVisibility(View.VISIBLE); - widget_frame.setPadding(widget_frame.getPaddingLeft(), widget_frame.getPaddingTop(), (int) (mDensity * 8), - widget_frame.getPaddingBottom()); + final ViewGroup widgetFrame = (ViewGroup) widget_frame_view; + widgetFrame.setVisibility(View.VISIBLE); + widgetFrame.setPadding(widgetFrame.getPaddingLeft(), widgetFrame.getPaddingTop(), (int) (mDensity * 8), + widgetFrame.getPaddingBottom()); // remove preview image that is already created - widget_frame.removeAllViews(); - widget_frame.setAlpha(isEnabled() ? 1 : 0.25f); + widgetFrame.removeAllViews(); + widgetFrame.setAlpha(isEnabled() ? 1 : 0.25f); final ImageView imageView = new ImageView(getContext()); - widget_frame.addView(imageView); + widgetFrame.addView(imageView); imageView.setImageBitmap(ColorPickerView.getColorPreviewBitmap(getContext(), getValue())); } diff --git a/src/org/mariotaku/twidere/provider/TwidereDataProvider.java b/src/org/mariotaku/twidere/provider/TwidereDataProvider.java index 4278763f..bf7fed71 100644 --- a/src/org/mariotaku/twidere/provider/TwidereDataProvider.java +++ b/src/org/mariotaku/twidere/provider/TwidereDataProvider.java @@ -909,25 +909,25 @@ private Cursor getUnreadCountsCursor(final int position) { final MatrixCursor c = new MatrixCursor(TweetStore.UnreadCounts.MATRIX_COLUMNS); final Context context = getContext(); final SupportTabSpec tab = CustomTabUtils.getAddedTabAt(context, position); - final String type = tab != null ? tab.type : null; + if (tab == null) return c; final int count; - if (TAB_TYPE_HOME_TIMELINE.equals(type) || TAB_TYPE_STAGGERED_HOME_TIMELINE.equals(type)) { + if (TAB_TYPE_HOME_TIMELINE.equals(tab.type) || TAB_TYPE_STAGGERED_HOME_TIMELINE.equals(tab.type)) { final long account_id = tab.args != null ? tab.args.getLong(EXTRA_ACCOUNT_ID, -1) : -1; final long[] account_ids = account_id > 0 ? new long[] { account_id } : getActivatedAccountIds(context); count = getUnreadCount(mUnreadStatuses, account_ids); - } else if (TAB_TYPE_MENTIONS_TIMELINE.equals(type)) { + } else if (TAB_TYPE_MENTIONS_TIMELINE.equals(tab.type)) { final long account_id = tab.args != null ? tab.args.getLong(EXTRA_ACCOUNT_ID, -1) : -1; final long[] account_ids = account_id > 0 ? new long[] { account_id } : getActivatedAccountIds(context); count = getUnreadCount(mUnreadMentions, account_ids); - } else if (TAB_TYPE_DIRECT_MESSAGES.equals(type)) { + } else if (TAB_TYPE_DIRECT_MESSAGES.equals(tab.type)) { final long account_id = tab.args != null ? tab.args.getLong(EXTRA_ACCOUNT_ID, -1) : -1; final long[] account_ids = account_id > 0 ? new long[] { account_id } : getActivatedAccountIds(context); count = getUnreadCount(mUnreadMessages, account_ids); } else { count = 0; } - if (type != null) { - c.addRow(new Object[] { position, type, count }); + if (tab.type != null) { + c.addRow(new Object[] { position, tab.type, count }); } return c; } @@ -1206,9 +1206,10 @@ private void updatePreferences() { } private static int clearUnreadCount(final List set, final long[] accountIds) { + if (accountIds == null) return 0; int count = 0; for (final UnreadItem item : set.toArray(new UnreadItem[set.size()])) { - if (ArrayUtils.contains(accountIds, item.account_id) && set.remove(item)) { + if (item != null && ArrayUtils.contains(accountIds, item.account_id) && set.remove(item)) { count++; } } diff --git a/src/org/mariotaku/twidere/view/ColorPickerPresetsView.java b/src/org/mariotaku/twidere/view/ColorPickerPresetsView.java deleted file mode 100644 index 33d54307..00000000 --- a/src/org/mariotaku/twidere/view/ColorPickerPresetsView.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.mariotaku.twidere.view; - -import android.content.Context; -import android.graphics.Color; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.LinearLayout; - -import org.mariotaku.twidere.Constants; -import org.mariotaku.twidere.R; - -public class ColorPickerPresetsView extends LinearLayout implements View.OnClickListener, Constants { - - private final static int[] COLORS = { HOLO_RED_DARK, HOLO_RED_LIGHT, HOLO_ORANGE_DARK, HOLO_ORANGE_LIGHT, - HOLO_GREEN_LIGHT, HOLO_GREEN_DARK, HOLO_BLUE_LIGHT, HOLO_BLUE_DARK, HOLO_PURPLE_DARK, HOLO_PURPLE_LIGHT, - Color.WHITE }; - - private OnColorClickListener mOnColorClickListener; - - public ColorPickerPresetsView(final Context context) { - this(context, null); - } - - public ColorPickerPresetsView(final Context context, final AttributeSet attrs) { - this(context, attrs, 0); - } - - public ColorPickerPresetsView(final Context context, final AttributeSet attrs, final int defStyleAttr) { - super(context, attrs, defStyleAttr); - setOrientation(HORIZONTAL); - final LayoutInflater inflater = LayoutInflater.from(context); - for (final int color : COLORS) { - final ColorView v = (ColorView) inflater.inflate(R.layout.color_picker_preset_item, this, false); - v.setColor(color); - v.setOnClickListener(this); - addView(v); - } - } - - @Override - public void onClick(final View v) { - if (!(v instanceof ColorView) || mOnColorClickListener == null) return; - mOnColorClickListener.onColorClick(((ColorView) v).getColor()); - } - - public void setOnColorClickListener(final OnColorClickListener listener) { - mOnColorClickListener = listener; - } - - public interface OnColorClickListener { - void onColorClick(int color); - } -} diff --git a/src/org/mariotaku/twidere/view/ColorPickerView.java b/src/org/mariotaku/twidere/view/ColorPickerView.java index 244fdba0..eb050cb1 100644 --- a/src/org/mariotaku/twidere/view/ColorPickerView.java +++ b/src/org/mariotaku/twidere/view/ColorPickerView.java @@ -88,15 +88,11 @@ public class ColorPickerView extends View { private float mDensity = 1f; - private OnColorChangedListener mListener; + private OnColorChangedListener mOnColorChangedListener; - private Paint mSatValPaint; + private Paint mHuePaint, mSatValPaint; - private Paint mSatValTrackerPaint; - - private Paint mHuePaint; - - private Paint mHueTrackerPaint; + private Paint mHueTrackerPaint, mSatValTrackerPaint; private Paint mAlphaPaint; @@ -104,26 +100,17 @@ public class ColorPickerView extends View { private Paint mBorderPaint; - private Shader mValShader; - - private Shader mSatShader; - - private Shader mHueShader; - private Shader mAlphaShader; - private int mAlpha = 0xff; + private Shader mValShader, mSatShader, mHueShader; - private float mHue = 360f; - - private float mSat = 0f; + private int mAlpha = 0xff; - private float mVal = 0f; + private float mHue = 360f, mSat = 0f, mVal = 0f; private String mAlphaSliderText = ""; private int mSliderTrackerColor = 0xff1c1c1c; - private int mBorderColor = 0xff6E6E6E; private boolean mShowAlphaPanel = false; @@ -190,7 +177,8 @@ public int getBorderColor() { * @return the current color. */ public int getColor() { - return Color.HSVToColor(mAlpha, new float[] { mHue, mSat, mVal }); + if (mShowAlphaPanel) return Color.HSVToColor(mAlpha, new float[] { mHue, mSat, mVal }); + return Color.HSVToColor(new float[] { mHue, mSat, mVal }); } /** @@ -231,8 +219,14 @@ public boolean onTouchEvent(final MotionEvent event) { } if (update) { - if (mListener != null) { - mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[] { mHue, mSat, mVal })); + if (mOnColorChangedListener != null) { + final int color; + if (mShowAlphaPanel) { + color = Color.HSVToColor(mAlpha, new float[] { mHue, mSat, mVal }); + } else { + color = Color.HSVToColor(new float[] { mHue, mSat, mVal }); + } + mOnColorChangedListener.onColorChanged(color); } invalidate(); return true; @@ -242,87 +236,69 @@ public boolean onTouchEvent(final MotionEvent event) { @Override public boolean onTrackballEvent(final MotionEvent event) { - - final float x = event.getX(); - final float y = event.getY(); - + final float x = event.getX(), y = event.getY(); boolean update = false; - if (event.getAction() == MotionEvent.ACTION_MOVE) { switch (mLastTouchedPanel) { - - case PANEL_SAT_VAL: - - float sat, - val; - + case PANEL_SAT_VAL: { + float sat, val; sat = mSat + x / 50f; val = mVal - y / 50f; - if (sat < 0f) { sat = 0f; } else if (sat > 1f) { sat = 1f; } - if (val < 0f) { val = 0f; } else if (val > 1f) { val = 1f; } - mSat = sat; mVal = val; - update = true; - break; - - case PANEL_HUE: - + } + case PANEL_HUE: { float hue = mHue - y * 10f; - if (hue < 0f) { hue = 0f; } else if (hue > 360f) { hue = 360f; } - mHue = hue; - update = true; - break; - - case PANEL_ALPHA: - + } + case PANEL_ALPHA: { if (!mShowAlphaPanel || mAlphaRect == null) { update = false; } else { - int alpha = (int) (mAlpha - x * 10); - if (alpha < 0) { alpha = 0; } else if (alpha > 0xff) { alpha = 0xff; } - mAlpha = alpha; - update = true; } break; + } } } if (update) { - - if (mListener != null) { - mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[] { mHue, mSat, mVal })); + final int color; + if (mShowAlphaPanel) { + color = Color.HSVToColor(mAlpha, new float[] { mHue, mSat, mVal }); + } else { + color = Color.HSVToColor(new float[] { mHue, mSat, mVal }); + } + if (mOnColorChangedListener != null) { + mOnColorChangedListener.onColorChanged(color); } - invalidate(); return true; } @@ -373,7 +349,6 @@ public void setAlphaSliderVisible(final boolean visible) { mSatShader = null; mHueShader = null; mAlphaShader = null; - ; requestLayout(); } @@ -411,21 +386,24 @@ public void setColor(final int color) { public void setColor(final int color, final boolean callback) { final int alpha = Color.alpha(color); - final int red = Color.red(color); - final int blue = Color.blue(color); - final int green = Color.green(color); final float[] hsv = new float[3]; - Color.RGBToHSV(red, green, blue, hsv); + Color.colorToHSV(color, hsv); - mAlpha = alpha; + if (mShowAlphaPanel) { + mAlpha = alpha; + } else { + mAlpha = 0xff; + } mHue = hsv[0]; mSat = hsv[1]; mVal = hsv[2]; - if (callback && mListener != null) { - mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[] { mHue, mSat, mVal })); + if (callback) { + if (mOnColorChangedListener != null) { + mOnColorChangedListener.onColorChanged(color); + } } invalidate(); @@ -438,8 +416,7 @@ public void setColor(final int color, final boolean callback) { * @param listener */ public void setOnColorChangedListener(final OnColorChangedListener listener) { - - mListener = listener; + mOnColorChangedListener = listener; } public void setSliderTrackerColor(final int color) { @@ -968,5 +945,4 @@ public interface OnColorChangedListener { public void onColorChanged(int color); } - } diff --git a/src/org/mariotaku/twidere/view/ColorView.java b/src/org/mariotaku/twidere/view/ColorView.java deleted file mode 100644 index 65e009b7..00000000 --- a/src/org/mariotaku/twidere/view/ColorView.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.mariotaku.twidere.view; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.util.AttributeSet; -import android.view.View; - -public class ColorView extends View { - - private final Paint mPaint; - - public ColorView(final Context context) { - this(context, null); - } - - public ColorView(final Context context, final AttributeSet attrs) { - this(context, attrs, 0); - } - - public ColorView(final Context context, final AttributeSet attrs, final int defStyleAttr) { - super(context, attrs, defStyleAttr); - mPaint = new Paint(); - final TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.color }); - setColor(a.getColor(0, Color.TRANSPARENT)); - a.recycle(); - } - - public int getColor() { - return mPaint.getColor(); - } - - public void setColor(final int color) { - mPaint.setColor(color); - invalidate(); - } - - @Override - protected void onDraw(final Canvas canvas) { - super.onDraw(canvas); - final int w = getWidth(), h = getHeight(); - canvas.drawRect(getPaddingLeft(), getPaddingTop(), w - getPaddingRight(), h - getPaddingBottom(), mPaint); - } - -} diff --git a/src/org/mariotaku/twidere/view/ForegroundColorView.java b/src/org/mariotaku/twidere/view/ForegroundColorView.java new file mode 100644 index 00000000..fd0bca21 --- /dev/null +++ b/src/org/mariotaku/twidere/view/ForegroundColorView.java @@ -0,0 +1,156 @@ +package org.mariotaku.twidere.view; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; + +import org.mariotaku.twidere.view.iface.IForegroundView; + +public class ForegroundColorView extends View implements IForegroundView { + + private final ForegroundViewHelper mForegroundViewHelper; + + private final Rect mAlphaRect, mColorRect; + private final Paint mPaint; + + private boolean mAlphaPattern; + + private int mNumRectanglesHorizontal; + + private int mNumRectanglesVertical; + + private final int mAlphaPatternSize; + + public ForegroundColorView(final Context context) { + this(context, null); + } + + public ForegroundColorView(final Context context, final AttributeSet attrs) { + this(context, attrs, 0); + } + + public ForegroundColorView(final Context context, final AttributeSet attrs, final int defStyle) { + super(context, attrs, defStyle); + mForegroundViewHelper = new ForegroundViewHelper(this, context, attrs, defStyle); + mAlphaPatternSize = Math.round(getResources().getDisplayMetrics().density * 4); + mAlphaRect = new Rect(); + mColorRect = new Rect(); + mPaint = new Paint(); + final TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.color }); + setColor(a.getColor(0, Color.TRANSPARENT)); + a.recycle(); + } + + public int getColor() { + return mPaint.getColor(); + } + + @Override + public Drawable getForeground() { + return mForegroundViewHelper.getForeground(); + } + + @Override + public void jumpDrawablesToCurrentState() { + super.jumpDrawablesToCurrentState(); + mForegroundViewHelper.jumpDrawablesToCurrentState(); + } + + public void setAlphaPatternEnable(final boolean alphaPattern) { + if (mAlphaPattern == alphaPattern) return; + mAlphaPattern = alphaPattern; + invalidate(); + } + + public void setColor(final int color) { + mPaint.setColor(color); + invalidate(); + } + + /** + * Supply a Drawable that is to be rendered on top of all of the child views + * in the frame layout. Any padding in the Drawable will be taken into + * account by ensuring that the children are inset to be placed inside of + * the padding area. + * + * @param drawable The Drawable to be drawn on top of the children. + * + * @attr ref android.R.styleable#FrameLayout_foreground + */ + @Override + public void setForeground(final Drawable drawable) { + mForegroundViewHelper.setForeground(drawable); + } + + /** + * Describes how the foreground is positioned. Defaults to START and TOP. + * + * @param foregroundGravity See {@link android.view.Gravity} + * + * @attr ref android.R.styleable#FrameLayout_foregroundGravity + */ + @Override + public void setForegroundGravity(final int foregroundGravity) { + mForegroundViewHelper.setForegroundGravity(foregroundGravity); + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + mForegroundViewHelper.drawableStateChanged(); + } + + @Override + protected void onDraw(final Canvas canvas) { + drawAlphaPattern(canvas); + canvas.drawRect(mColorRect, mPaint); + mForegroundViewHelper.onDraw(canvas); + } + + @Override + protected void onLayout(final boolean changed, final int left, final int top, final int right, final int bottom) { + mForegroundViewHelper.onLayout(changed, left, top, right, bottom); + super.onLayout(changed, left, top, right, bottom); + } + + @Override + protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + mForegroundViewHelper.onSizeChanged(w, h, oldw, oldh); + mColorRect.set(getPaddingLeft(), getPaddingTop(), w - getPaddingRight(), h - getPaddingBottom()); + mNumRectanglesHorizontal = (int) Math.ceil(w / mAlphaPatternSize); + mNumRectanglesVertical = (int) Math.ceil(h / mAlphaPatternSize); + } + + @Override + protected boolean verifyDrawable(final Drawable who) { + return super.verifyDrawable(who) || mForegroundViewHelper.verifyDrawable(who); + } + + private void drawAlphaPattern(final Canvas canvas) { + if (!mAlphaPattern) return; + boolean verticalStartWhite = true; + for (int i = 0; i <= mNumRectanglesVertical; i++) { + boolean horizontalStartWhite = verticalStartWhite; + for (int j = 0; j <= mNumRectanglesHorizontal; j++) { + mAlphaRect.top = i * mAlphaPatternSize + getTop(); + mAlphaRect.left = j * mAlphaPatternSize + getLeft(); + mAlphaRect.bottom = Math.min(mAlphaRect.top + mAlphaPatternSize, getBottom()); + mAlphaRect.right = Math.min(mAlphaRect.left + mAlphaPatternSize, getRight()); + + mPaint.setColor(horizontalStartWhite ? Color.WHITE : Color.GRAY); + canvas.drawRect(mAlphaRect, mPaint); + + horizontalStartWhite = !horizontalStartWhite; + } + verticalStartWhite = !verticalStartWhite; + } + } + +} diff --git a/src/org/mariotaku/twidere/view/ForegroundImageView.java b/src/org/mariotaku/twidere/view/ForegroundImageView.java index dc240973..c5b5bfe3 100644 --- a/src/org/mariotaku/twidere/view/ForegroundImageView.java +++ b/src/org/mariotaku/twidere/view/ForegroundImageView.java @@ -1,28 +1,16 @@ package org.mariotaku.twidere.view; import android.content.Context; -import android.content.res.TypedArray; import android.graphics.Canvas; -import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.support.v4.view.GravityCompat; -import android.support.v4.view.ViewCompat; import android.util.AttributeSet; -import android.view.Gravity; import android.widget.ImageView; -public class ForegroundImageView extends ImageView { +import org.mariotaku.twidere.view.iface.IForegroundView; - private Drawable mForeground; +public class ForegroundImageView extends ImageView implements IForegroundView { - private final Rect mSelfBounds = new Rect(); - private final Rect mOverlayBounds = new Rect(); - - private int mForegroundGravity = Gravity.FILL; - - protected boolean mForegroundInPadding = true; - - boolean mForegroundBoundsChanged = false; + private final ForegroundViewHelper mForegroundViewHelper; public ForegroundImageView(final Context context) { this(context, null); @@ -34,71 +22,18 @@ public ForegroundImageView(final Context context, final AttributeSet attrs) { public ForegroundImageView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - final TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.foreground, - android.R.attr.foregroundGravity }, defStyle, 0); - - mForegroundGravity = a.getInt(1, mForegroundGravity); - - final Drawable d = a.getDrawable(0); - if (d != null) { - setForeground(d); - } - - mForegroundInPadding = true; - - a.recycle(); + mForegroundViewHelper = new ForegroundViewHelper(this, context, attrs, defStyle); } - /** - * {@inheritDoc} - */ @Override - public void draw(final Canvas canvas) { - super.draw(canvas); - - if (mForeground != null) { - final Drawable foreground = mForeground; - - if (mForegroundBoundsChanged) { - mForegroundBoundsChanged = false; - final Rect selfBounds = mSelfBounds; - final Rect overlayBounds = mOverlayBounds; - - final int w = getRight() - getLeft(); - final int h = getBottom() - getTop(); - - if (mForegroundInPadding) { - selfBounds.set(0, 0, w, h); - } else { - selfBounds.set(getPaddingLeft(), getPaddingTop(), w - getPaddingRight(), h - getPaddingBottom()); - } - - final int layoutDirection = ViewCompat.getLayoutDirection(this); - GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(), - foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection); - foreground.setBounds(overlayBounds); - } - - foreground.draw(canvas); - } - } - - /** - * Returns the drawable used as the foreground of this FrameLayout. The - * foreground drawable, if non-null, is always drawn on top of the children. - * - * @return A Drawable or null if no foreground was set. - */ public Drawable getForeground() { - return mForeground; + return mForegroundViewHelper.getForeground(); } @Override public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); - if (mForeground != null) { - mForeground.jumpToCurrentState(); - } + mForegroundViewHelper.jumpDrawablesToCurrentState(); } /** @@ -111,29 +46,9 @@ public void jumpDrawablesToCurrentState() { * * @attr ref android.R.styleable#FrameLayout_foreground */ + @Override public void setForeground(final Drawable drawable) { - if (mForeground != drawable) { - if (mForeground != null) { - mForeground.setCallback(null); - unscheduleDrawable(mForeground); - } - - mForeground = drawable; - - if (drawable != null) { - drawable.setCallback(this); - if (drawable.isStateful()) { - drawable.setState(getDrawableState()); - } - if (mForegroundGravity == Gravity.FILL) { - final Rect padding = new Rect(); - if (drawable.getPadding(padding)) { - } - } - } - requestLayout(); - invalidate(); - } + mForegroundViewHelper.setForeground(drawable); } /** @@ -143,82 +58,38 @@ public void setForeground(final Drawable drawable) { * * @attr ref android.R.styleable#FrameLayout_foregroundGravity */ - public void setForegroundGravity(int foregroundGravity) { - if (mForegroundGravity != foregroundGravity) { - if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) { - foregroundGravity |= Gravity.START; - } - - if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { - foregroundGravity |= Gravity.TOP; - } - - mForegroundGravity = foregroundGravity; - - if (mForegroundGravity == Gravity.FILL && mForeground != null) { - final Rect padding = new Rect(); - if (mForeground.getPadding(padding)) { - } - } else { - } - - requestLayout(); - } + @Override + public void setForegroundGravity(final int foregroundGravity) { + mForegroundViewHelper.setForegroundGravity(foregroundGravity); } @Override protected void drawableStateChanged() { super.drawableStateChanged(); - if (mForeground != null && mForeground.isStateful()) { - mForeground.setState(getDrawableState()); - } + mForegroundViewHelper.drawableStateChanged(); } @Override protected void onDraw(final Canvas canvas) { super.onDraw(canvas); - if (mForeground != null) { - final Drawable foreground = mForeground; - - if (mForegroundBoundsChanged) { - mForegroundBoundsChanged = false; - final Rect selfBounds = mSelfBounds; - final Rect overlayBounds = mOverlayBounds; - - final int w = getRight() - getLeft(); - final int h = getBottom() - getTop(); - - if (mForegroundInPadding) { - selfBounds.set(0, 0, w, h); - } else { - selfBounds.set(getPaddingLeft(), getPaddingTop(), w - getPaddingRight(), h - getPaddingBottom()); - } - - final int layoutDirection = ViewCompat.getLayoutDirection(this); - GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(), - foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection); - foreground.setBounds(overlayBounds); - } - - foreground.draw(canvas); - } + mForegroundViewHelper.onDraw(canvas); } @Override protected void onLayout(final boolean changed, final int left, final int top, final int right, final int bottom) { - mForegroundBoundsChanged = true; + mForegroundViewHelper.onLayout(changed, left, top, right, bottom); super.onLayout(changed, left, top, right, bottom); } @Override protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { super.onSizeChanged(w, h, oldw, oldh); - mForegroundBoundsChanged = true; + mForegroundViewHelper.onSizeChanged(w, h, oldw, oldh); } @Override protected boolean verifyDrawable(final Drawable who) { - return super.verifyDrawable(who) || who == mForeground; + return super.verifyDrawable(who) || mForegroundViewHelper.verifyDrawable(who); } } diff --git a/src/org/mariotaku/twidere/view/HandleSpanClickTextView.java b/src/org/mariotaku/twidere/view/HandleSpanClickTextView.java index e2b85a49..37bc0440 100644 --- a/src/org/mariotaku/twidere/view/HandleSpanClickTextView.java +++ b/src/org/mariotaku/twidere/view/HandleSpanClickTextView.java @@ -68,16 +68,17 @@ public boolean onTouchEvent(final MotionEvent event) { if (links.length != 0 && x <= lineWidth) { final ClickableSpan link = links[0]; if (action == MotionEvent.ACTION_UP) { - link.onClick(this); + Selection.removeSelection(buffer); setClickable(false); + link.onClick(this); return true; } else if (action == MotionEvent.ACTION_DOWN) { Selection.setSelection(buffer, buffer.getSpanStart(link), buffer.getSpanEnd(link)); setClickable(true); } } else { - setClickable(false); Selection.removeSelection(buffer); + setClickable(false); } } return super.onTouchEvent(event); diff --git a/src/org/mariotaku/twidere/view/iface/IForegroundView.java b/src/org/mariotaku/twidere/view/iface/IForegroundView.java new file mode 100644 index 00000000..3457ce60 --- /dev/null +++ b/src/org/mariotaku/twidere/view/iface/IForegroundView.java @@ -0,0 +1,209 @@ +package org.mariotaku.twidere.view.iface; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.v4.view.GravityCompat; +import android.support.v4.view.ViewCompat; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; + +public interface IForegroundView { + + /** + * Returns the drawable used as the foreground of this FrameLayout. The + * foreground drawable, if non-null, is always drawn on top of the children. + * + * @return A Drawable or null if no foreground was set. + */ + public Drawable getForeground(); + + /** + * Supply a Drawable that is to be rendered on top of all of the child views + * in the frame layout. Any padding in the Drawable will be taken into + * account by ensuring that the children are inset to be placed inside of + * the padding area. + * + * @param drawable The Drawable to be drawn on top of the children. + * + * @attr ref android.R.attr#foreground + */ + public void setForeground(final Drawable drawable); + + /** + * Describes how the foreground is positioned. Defaults to START and TOP. + * + * @param foregroundGravity See {@link android.view.Gravity} + * + * @attr ref android.R.attr#foregroundGravity + */ + public void setForegroundGravity(int foregroundGravity); + + public static class ForegroundViewHelper { + + private final View mView; + + private final Rect mSelfBounds = new Rect(); + private final Rect mOverlayBounds = new Rect(); + + private Drawable mForeground; + + private int mForegroundGravity = Gravity.FILL; + private boolean mForegroundInPadding = true; + private boolean mForegroundBoundsChanged = false; + + public ForegroundViewHelper(final View view, final Context context, final AttributeSet attrs, final int defStyle) { + mView = view; + final TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.foreground, + android.R.attr.foregroundGravity }, defStyle, 0); + + mForegroundGravity = a.getInt(1, mForegroundGravity); + + final Drawable d = a.getDrawable(0); + if (d != null) { + setForeground(d); + } + + mForegroundInPadding = true; + + a.recycle(); + } + + public void draw(final Canvas canvas) { + if (mForeground != null) { + final Drawable foreground = mForeground; + + if (mForegroundBoundsChanged) { + mForegroundBoundsChanged = false; + final Rect selfBounds = mSelfBounds; + final Rect overlayBounds = mOverlayBounds; + + final int w = mView.getRight() - mView.getLeft(); + final int h = mView.getBottom() - mView.getTop(); + + if (mForegroundInPadding) { + selfBounds.set(0, 0, w, h); + } else { + selfBounds.set(mView.getPaddingLeft(), mView.getPaddingTop(), w - mView.getPaddingRight(), h + - mView.getPaddingBottom()); + } + + final int layoutDirection = ViewCompat.getLayoutDirection(mView); + GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(), + foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection); + foreground.setBounds(overlayBounds); + } + + foreground.draw(canvas); + } + } + + public void drawableStateChanged() { + if (mForeground != null && mForeground.isStateful()) { + mForeground.setState(mView.getDrawableState()); + } + } + + public Drawable getForeground() { + return mForeground; + } + + public void jumpDrawablesToCurrentState() { + if (mForeground != null) { + mForeground.jumpToCurrentState(); + } + } + + public void onDraw(final Canvas canvas) { + if (mForeground != null) { + final Drawable foreground = mForeground; + + if (mForegroundBoundsChanged) { + mForegroundBoundsChanged = false; + final Rect selfBounds = mSelfBounds; + final Rect overlayBounds = mOverlayBounds; + + final int w = mView.getRight() - mView.getLeft(); + final int h = mView.getBottom() - mView.getTop(); + + if (mForegroundInPadding) { + selfBounds.set(0, 0, w, h); + } else { + selfBounds.set(mView.getPaddingLeft(), mView.getPaddingTop(), w - mView.getPaddingRight(), h + - mView.getPaddingBottom()); + } + + final int layoutDirection = ViewCompat.getLayoutDirection(mView); + GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(), + foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection); + foreground.setBounds(overlayBounds); + } + + foreground.draw(canvas); + } + } + + public void onLayout(final boolean changed, final int left, final int top, final int right, final int bottom) { + mForegroundBoundsChanged = true; + } + + public void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { + mForegroundBoundsChanged = true; + } + + public void setForeground(final Drawable drawable) { + if (mForeground != drawable) { + if (mForeground != null) { + mForeground.setCallback(null); + mView.unscheduleDrawable(mForeground); + } + + mForeground = drawable; + + if (drawable != null) { + drawable.setCallback(mView); + if (drawable.isStateful()) { + drawable.setState(mView.getDrawableState()); + } + if (mForegroundGravity == Gravity.FILL) { + final Rect padding = new Rect(); + if (drawable.getPadding(padding)) { + } + } + } + mView.requestLayout(); + mView.invalidate(); + } + } + + public void setForegroundGravity(int foregroundGravity) { + if (mForegroundGravity != foregroundGravity) { + if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) { + foregroundGravity |= Gravity.START; + } + + if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { + foregroundGravity |= Gravity.TOP; + } + + mForegroundGravity = foregroundGravity; + + if (mForegroundGravity == Gravity.FILL && mForeground != null) { + final Rect padding = new Rect(); + if (mForeground.getPadding(padding)) { + } + } else { + } + + mView.requestLayout(); + } + } + + public boolean verifyDrawable(final Drawable who) { + return who == mForeground; + } + } +}