This commit is contained in:
Mariotaku Lee 2017-09-15 17:40:35 +08:00
parent 8db45fef5d
commit 8312ee71c1
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
13 changed files with 257 additions and 149 deletions

View File

@ -1,24 +0,0 @@
package android.support.v7.widget.android.support.v7.view.menu;
import android.content.Context;
import android.support.v7.view.menu.ActionMenuItemView;
import android.util.AttributeSet;
/**
* Created by mariotaku on 16/3/18.
*/
@SuppressWarnings("RestrictedApi")
public class TwidereActionMenuItemView extends ActionMenuItemView {
public TwidereActionMenuItemView(Context context) {
super(context);
}
public TwidereActionMenuItemView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public interface IgnoreTinting {
}
}

View File

@ -22,7 +22,7 @@ package org.mariotaku.twidere.graphic;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.support.v7.graphics.drawable.DrawableWrapper;
import android.support.v7.widget.android.support.v7.view.menu.TwidereActionMenuItemView;
import android.support.v7.view.menu.TwidereActionMenuItemView;
import android.view.MenuItem;
import org.mariotaku.twidere.util.menu.TwidereMenuInfo;

View File

@ -14,7 +14,7 @@ import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.v7.widget.android.support.v7.view.menu.TwidereActionMenuItemView;
import android.support.v7.view.menu.TwidereActionMenuItemView;
import android.util.Property;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;

View File

@ -1,113 +0,0 @@
package org.mariotaku.twidere.menu;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ActionProvider;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.ActionMenuView;
import android.view.MenuItem;
import android.view.View;
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable;
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable.Style;
import java.lang.ref.WeakReference;
/**
* Created by mariotaku on 16/2/18.
*/
public class FavoriteItemProvider extends ActionProvider {
private int mDefaultColor, mActivatedColor;
private boolean mUseStar;
private int mIcon;
/**
* Creates a new instance.
*
* @param context Context for accessing resources.
*/
public FavoriteItemProvider(Context context) {
super(context);
}
@Override
public View onCreateActionView() {
return null;
}
public void setUseStar(boolean useStar) {
mUseStar = useStar;
}
public void setDefaultColor(int defaultColor) {
mDefaultColor = defaultColor;
}
public void setActivatedColor(int activatedColor) {
mActivatedColor = activatedColor;
}
public void invokeItem(MenuItem item, LikeAnimationDrawable.OnLikedListener listener) {
if (MenuItemCompat.getActionProvider(item) != this) throw new IllegalArgumentException();
final Drawable icon = item.getIcon();
if (icon instanceof LikeAnimationDrawable) {
((LikeAnimationDrawable) icon).setOnLikedListener(listener);
((LikeAnimationDrawable) icon).start();
}
}
public void setIcon(int icon) {
mIcon = icon;
}
public void init(final ActionMenuView menuBar, MenuItem item) {
if (MenuItemCompat.getActionProvider(item) != this) throw new IllegalArgumentException();
final Drawable icon = ContextCompat.getDrawable(getContext(), mIcon);
final LikeAnimationDrawable drawable = new LikeAnimationDrawable(icon, mDefaultColor,
mActivatedColor, mUseStar ? Style.FAVORITE : Style.LIKE);
drawable.mutate();
drawable.setCallback(new ViewCallback(menuBar));
item.setIcon(drawable);
}
public void setIsFavorite(MenuItem item, boolean isFavorite) {
if (MenuItemCompat.getActionProvider(item) != this) throw new IllegalArgumentException();
final Drawable icon = item.getIcon();
if (icon instanceof LikeAnimationDrawable) {
icon.mutate();
icon.setColorFilter(isFavorite ? mActivatedColor : mDefaultColor, PorterDuff.Mode.SRC_ATOP);
}
}
private static class ViewCallback implements Drawable.Callback {
private final WeakReference<View> mViewRef;
public ViewCallback(View view) {
mViewRef = new WeakReference<>(view);
}
@Override
public void invalidateDrawable(@NonNull Drawable who) {
final View view = mViewRef.get();
if (view == null) return;
view.invalidate();
}
@Override
public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
final View view = mViewRef.get();
if (view == null) return;
view.postDelayed(what, when);
}
@Override
public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
final View view = mViewRef.get();
if (view == null) return;
view.post(what);
}
}
}

View File

@ -0,0 +1,12 @@
package android.support.v7.view.menu
import android.content.Context
import android.util.AttributeSet
/**
* Created by mariotaku on 16/3/18.
*/
class TwidereActionMenuItemView(context: Context, attrs: AttributeSet? = null) : ActionMenuItemView(context, attrs) {
interface IgnoreTinting
}

View File

@ -20,7 +20,7 @@
package android.support.v7.widget
import android.content.Context
import android.support.v7.widget.android.support.v7.view.menu.TwidereActionMenuItemView
import android.support.v7.view.menu.TwidereActionMenuItemView
import android.util.AttributeSet
import android.view.View

View File

@ -23,6 +23,8 @@ import android.content.Context
import android.graphics.drawable.Drawable
import android.support.annotation.DrawableRes
import android.support.v4.content.ContextCompat
import android.support.v4.view.ActionProvider
import android.support.v4.view.MenuItemCompat
import android.view.Menu
import android.view.MenuItem
import android.view.SubMenu
@ -81,3 +83,9 @@ fun MenuItem.setActionIcon(context: Context, @DrawableRes iconRes: Int) {
setIcon(iconRes)
}
}
var MenuItem.supportActionProvider: ActionProvider?
get() = MenuItemCompat.getActionProvider(this)
set(value) {
MenuItemCompat.setActionProvider(this, value)
}

View File

@ -0,0 +1,32 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.extension.view
import android.annotation.SuppressLint
import android.support.v7.view.menu.MenuView
import android.support.v7.widget.ActionMenuView
import android.view.MenuItem
import android.view.View
import org.mariotaku.twidere.extension.children
@SuppressLint("RestrictedApi")
fun ActionMenuView.findItemView(byItem: MenuItem): View? {
return children.firstOrNull { it is MenuView.ItemView && it.itemData === byItem }
}

View File

@ -0,0 +1,95 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.menu
import android.content.Context
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.support.v4.content.ContextCompat
import android.support.v4.view.ActionProvider
import android.support.v4.view.MenuItemCompat
import android.support.v7.widget.ActionMenuView
import android.view.MenuItem
import android.view.View
import org.mariotaku.ktextension.weak
import org.mariotaku.twidere.extension.view.findItemView
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable.Style
class FavoriteItemProvider(context: Context) : ActionProvider(context) {
var defaultColor: Int = 0
var activatedColor: Int = 0
var useStar: Boolean = false
var icon: Int = 0
var longClickListener: (() -> Boolean)? = null
override fun onCreateActionView() = null
fun invokeItem(item: MenuItem, listener: LikeAnimationDrawable.OnLikedListener) {
if (MenuItemCompat.getActionProvider(item) !== this) throw IllegalArgumentException()
val icon = item.icon
if (icon is LikeAnimationDrawable) {
icon.setOnLikedListener(listener)
icon.start()
}
}
fun init(menuBar: ActionMenuView, item: MenuItem) {
assert(MenuItemCompat.getActionProvider(item) === this)
val icon = ContextCompat.getDrawable(context, this.icon)
val drawable = LikeAnimationDrawable(icon, defaultColor, activatedColor,
if (useStar) Style.FAVORITE else Style.LIKE)
drawable.mutate()
drawable.callback = ViewCallback(menuBar)
item.icon = drawable
val menuView = menuBar.findItemView(item)
menuView?.setOnLongClickListener { longClickListener?.invoke() == true }
}
fun setIsFavorite(item: MenuItem, isFavorite: Boolean) {
if (MenuItemCompat.getActionProvider(item) !== this) throw IllegalArgumentException()
val icon = item.icon
if (icon is LikeAnimationDrawable) {
icon.mutate()
icon.setColorFilter(if (isFavorite) activatedColor else defaultColor, PorterDuff.Mode.SRC_ATOP)
}
}
private class ViewCallback(view: View) : Drawable.Callback {
private val viewRef = view.weak()
override fun invalidateDrawable(who: Drawable) {
val view = viewRef.get() ?: return
view.invalidate()
}
override fun scheduleDrawable(who: Drawable, what: Runnable, `when`: Long) {
val view = viewRef.get() ?: return
view.postDelayed(what, `when`)
}
override fun unscheduleDrawable(who: Drawable, what: Runnable) {
val view = viewRef.get() ?: return
view.post(what)
}
}
}

View File

@ -0,0 +1,42 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.menu
import android.content.Context
import android.support.v4.view.ActionProvider
import android.support.v4.view.MenuItemCompat
import android.support.v7.widget.ActionMenuView
import android.view.MenuItem
import org.mariotaku.twidere.extension.view.findItemView
/**
* Created by mariotaku on 2017/9/15.
*/
class RetweetItemProvider(context: Context) : ActionProvider(context) {
var longClickListener: (() -> Boolean)? = null
override fun onCreateActionView() = null
fun init(menuBar: ActionMenuView, item: MenuItem) {
assert(MenuItemCompat.getActionProvider(item) === this)
val menuView = menuBar.findItemView(item)
menuView?.setOnLongClickListener { longClickListener?.invoke() == true }
}
}

View File

@ -24,7 +24,6 @@ import android.content.SharedPreferences
import android.graphics.Rect
import android.support.annotation.UiThread
import android.support.v4.content.ContextCompat
import android.support.v4.view.MenuItemCompat
import android.support.v4.view.ViewCompat
import android.support.v7.widget.ActionMenuView
import android.support.v7.widget.LinearLayoutManager
@ -39,13 +38,13 @@ import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.adapter_item_status_count_label.view.*
import kotlinx.android.synthetic.main.header_status.view.*
import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.applyFontFamily
import org.mariotaku.ktextension.hideIfEmpty
import org.mariotaku.ktextension.spannable
import org.mariotaku.ktextension.supportActionProvider
import org.mariotaku.microblog.library.twitter.model.TranslationResult
import org.mariotaku.twidere.Constants
import org.mariotaku.twidere.R
@ -56,8 +55,10 @@ import org.mariotaku.twidere.constant.displaySensitiveContentsKey
import org.mariotaku.twidere.constant.newDocumentApiKey
import org.mariotaku.twidere.extension.loadProfileImage
import org.mariotaku.twidere.extension.model.*
import org.mariotaku.twidere.fragment.AbsStatusesFragment
import org.mariotaku.twidere.fragment.status.StatusFragment
import org.mariotaku.twidere.menu.FavoriteItemProvider
import org.mariotaku.twidere.menu.RetweetItemProvider
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.util.ParcelableLocationUtils
import org.mariotaku.twidere.model.util.ParcelableMediaUtils
@ -429,19 +430,37 @@ class DetailStatusViewHolder(
val inflater = activity.menuInflater
val menu = itemView.menuBar.menu
inflater.inflate(R.menu.menu_detail_status, menu)
val favoriteItem = menu.findItem(R.id.favorite)
val provider = MenuItemCompat.getActionProvider(favoriteItem)
if (provider is FavoriteItemProvider) {
val favoriteProvider = favoriteItem?.supportActionProvider
if (favoriteProvider is FavoriteItemProvider) {
val defaultColor = ThemeUtils.getActionIconColor(activity)
provider.setDefaultColor(defaultColor)
favoriteProvider.defaultColor = defaultColor
val favoriteHighlight = ContextCompat.getColor(activity, R.color.highlight_favorite)
val likeHighlight = ContextCompat.getColor(activity, R.color.highlight_like)
val useStar = adapter.useStarsForLikes
provider.setActivatedColor(if (useStar) favoriteHighlight else likeHighlight)
provider.setIcon(if (useStar) R.drawable.ic_action_star else R.drawable.ic_action_heart)
provider.setUseStar(useStar)
provider.init(itemView.menuBar, favoriteItem)
favoriteProvider.activatedColor = if (useStar) favoriteHighlight else likeHighlight
favoriteProvider.icon = if (useStar) R.drawable.ic_action_star else R.drawable.ic_action_heart
favoriteProvider.useStar = useStar
favoriteProvider.longClickListener = {
val status = adapter.getStatus(layoutPosition)
val itemId = adapter.getItemId(layoutPosition)
AbsStatusesFragment.handleActionLongClick(fragment, status, itemId, R.id.favorite)
}
favoriteProvider.init(itemView.menuBar, favoriteItem)
}
val retweetItem = menu.findItem(R.id.retweet)
val retweetProvider = retweetItem?.supportActionProvider
if (retweetProvider is RetweetItemProvider) {
retweetProvider.longClickListener = {
val status = adapter.getStatus(layoutPosition)
val itemId = adapter.getItemId(layoutPosition)
AbsStatusesFragment.handleActionLongClick(fragment, status, itemId, R.id.retweet)
}
retweetProvider.init(itemView.menuBar, retweetItem)
}
ThemeUtils.wrapMenuIcon(itemView.menuBar, excludeGroups = Constants.MENU_GROUP_STATUS_SHARE)
itemView.mediaPreviewLoad.setOnClickListener(this)
itemView.profileContainer.setOnClickListener(this)
@ -757,4 +776,10 @@ class DetailStatusViewHolder(
}
}
}
companion object {
const val REQUEST_FAVORITE_SELECT_ACCOUNT = 101
const val REQUEST_RETWEET_SELECT_ACCOUNT = 102
}
}

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Twidere - Twitter client for Android
~
~ Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>

View File

@ -13,6 +13,7 @@
android:id="@id/retweet"
android:icon="@drawable/ic_action_retweet"
android:title="@string/action_retweet"
app:actionProviderClass="org.mariotaku.twidere.menu.RetweetItemProvider"
app:showAsAction="always"/>
<item
android:id="@id/favorite"