added elevation for FAB (L+)

trying to improve fav/unfav indication
This commit is contained in:
Mariotaku Lee 2014-12-10 22:41:55 +08:00
parent 30c302fa52
commit c5c40c2f67
14 changed files with 356 additions and 136 deletions

View File

@ -77,10 +77,7 @@ public interface IntentConstants {
public static final String BROADCAST_FRIENDSHIP_ACCEPTED = INTENT_PACKAGE_PREFIX + "FRIENDSHIP_ACCEPTED";
public static final String BROADCAST_FRIENDSHIP_DENIED = INTENT_PACKAGE_PREFIX + "FRIENDSHIP_DENIED";
public static final String BROADCAST_STATUS_FAVORITE_CREATED = INTENT_PACKAGE_PREFIX + "STATUS_FAVORITE_CREATED";
public static final String BROADCAST_STATUS_FAVORITE_DESTROYED = INTENT_PACKAGE_PREFIX + "STATUS_FAVORITE_DESTROYED";
public static final String BROADCAST_STATUS_RETWEETED = INTENT_PACKAGE_PREFIX + "STATUS_RETWEETED";
public static final String BROADCAST_STATUS_DESTROYED = INTENT_PACKAGE_PREFIX + "STATUS_DESTROYED";
public static final String BROADCAST_USER_LIST_MEMBERS_DELETED = INTENT_PACKAGE_PREFIX + "USER_LIST_MEMBER_DELETED";
public static final String BROADCAST_USER_LIST_MEMBERS_ADDED = INTENT_PACKAGE_PREFIX + "USER_LIST_MEMBER_ADDED";
public static final String BROADCAST_USER_LIST_SUBSCRIBED = INTENT_PACKAGE_PREFIX + "USER_LIST_SUBSRCIBED";

View File

@ -1,9 +1,7 @@
package org.mariotaku.twidere.fragment.support;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Rect;
import android.os.Bundle;
@ -19,10 +17,13 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.squareup.otto.Bus;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.AbsStatusesAdapter;
import org.mariotaku.twidere.adapter.AbsStatusesAdapter.StatusAdapterListener;
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.constant.IntentConstants;
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
import org.mariotaku.twidere.model.ParcelableStatus;
@ -40,16 +41,6 @@ import org.mariotaku.twidere.view.holder.StatusViewHolder;
public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment implements LoaderCallbacks<Data>,
OnRefreshListener, DrawerCallback, RefreshScrollTopInterface, StatusAdapterListener {
private final BroadcastReceiver mStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
if (getActivity() == null || !isAdded() || isDetached()) return;
onReceivedBroadcast(intent, intent.getAction());
}
};
private View mContentView;
private SharedPreferences mPreferences;
private View mProgressContainer;
@ -159,14 +150,20 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
@Override
public void onStart() {
super.onStart();
final IntentFilter filter = new IntentFilter();
onSetIntentFilter(filter);
registerReceiver(mStateReceiver, filter);
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
final Object callback = getMessageBusCallback();
if (callback != null) {
bus.register(callback);
}
}
@Override
public void onStop() {
unregisterReceiver(mStateReceiver);
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
final Object callback = getMessageBusCallback();
if (callback != null) {
bus.unregister(callback);
}
super.onStop();
}
@ -276,14 +273,14 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
mAdapter.setData(data);
}
protected Object getMessageBusCallback() {
return null;
}
protected abstract AbsStatusesAdapter<Data> onCreateAdapter(Context context, boolean compact);
protected abstract void onLoadMoreStatuses();
protected abstract void onReceivedBroadcast(Intent intent, String action);
protected abstract void onSetIntentFilter(IntentFilter filter);
private void setListShown(boolean shown) {
mProgressContainer.setVisibility(shown ? View.GONE : View.VISIBLE);
mSwipeRefreshLayout.setVisibility(shown ? View.VISIBLE : View.GONE);

View File

@ -60,34 +60,11 @@ public class HomeTimelineFragment extends CursorStatusesFragment {
return twitter.getHomeTimelineAsync(accountIds, maxIds, sinceIds);
}
@Override
public void onStart() {
super.onStart();
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
bus.register(this);
}
@Override
public void onStop() {
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
bus.unregister(this);
super.onStop();
}
@Subscribe
public void notifyTaskStateChanged(TaskStateChangedEvent event) {
updateRefreshState();
}
@Override
protected void onReceivedBroadcast(Intent intent, String action) {
}
@Override
protected void onSetIntentFilter(IntentFilter filter) {
}
private void updateRefreshState() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();

View File

@ -79,14 +79,6 @@ public class MentionsTimelineFragment extends CursorStatusesFragment {
updateRefreshState();
}
@Override
protected void onReceivedBroadcast(Intent intent, String action) {
}
@Override
protected void onSetIntentFilter(IntentFilter filter) {
}
private void updateRefreshState() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null) return;

View File

@ -20,26 +20,38 @@
package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter;
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.util.message.StatusDestroyedEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Created by mariotaku on 14/12/3.
*/
public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<List<ParcelableStatus>> {
private final StatusesBusCallback mStatusesBusCallback;
protected ParcelableStatusesFragment() {
mStatusesBusCallback = new StatusesBusCallback(this);
}
public final void deleteStatus(final long statusId) {
final List<ParcelableStatus> data = getAdapterData();
if (statusId <= 0 || data == null) return;
final ArrayList<ParcelableStatus> dataToRemove = new ArrayList<>();
final Set<ParcelableStatus> dataToRemove = new HashSet<>();
for (final ParcelableStatus status : data) {
if (status.id == statusId || status.retweet_id > 0 && status.retweet_id == statusId) {
dataToRemove.add(status);
@ -62,11 +74,30 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<Lis
return -1;
}
@Override
public void onStart() {
super.onStart();
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
bus.register(this);
}
@Override
public void onStop() {
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
bus.unregister(this);
super.onStop();
}
@Override
protected long[] getAccountIds() {
return new long[]{getAccountId()};
}
@Override
protected Object getMessageBusCallback() {
return mStatusesBusCallback;
}
@Override
protected ParcelableStatusesAdapter onCreateAdapter(final Context context, final boolean compact) {
return new ParcelableStatusesAdapter(context, compact);
@ -79,19 +110,15 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<Lis
getStatuses(null, maxIds, null);
}
@Override
protected void onReceivedBroadcast(Intent intent, String action) {
switch (action) {
case BROADCAST_STATUS_DESTROYED: {
deleteStatus(intent.getLongExtra(EXTRA_STATUS_ID, -1));
break;
public final void replaceStatus(final ParcelableStatus status) {
final List<ParcelableStatus> data = getAdapterData();
if (status == null || data == null) return;
for (int i = 0, j = data.size(); i < j; i++) {
if (status.equals(data.get(i))) {
data.set(i, status);
}
}
}
@Override
protected void onSetIntentFilter(IntentFilter filter) {
filter.addAction(BROADCAST_STATUS_DESTROYED);
setAdapterData(data);
}
@Override
@ -116,4 +143,37 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<Lis
return null;
}
private void updateFavoritedStatus(ParcelableStatus status) {
final Context context = getActivity();
if (context == null) return;
if (status.account_id == getAccountId()) {
replaceStatus(status);
}
}
protected static class StatusesBusCallback {
private final ParcelableStatusesFragment fragment;
StatusesBusCallback(ParcelableStatusesFragment fragment) {
this.fragment = fragment;
}
@Subscribe
public void notifyFavoriteCreated(FavoriteCreatedEvent event) {
fragment.updateFavoritedStatus(event.status);
}
@Subscribe
public void notifyFavoriteDestroyed(FavoriteDestroyedEvent event) {
fragment.updateFavoritedStatus(event.status);
}
@Subscribe
public void notifyStatusDestroyed(StatusDestroyedEvent event) {
fragment.deleteStatus(event.status.id);
}
}
}

View File

@ -53,12 +53,7 @@ public abstract class ParcelableStatusesListFragment extends BaseStatusesListFra
public void onReceive(final Context context, final Intent intent) {
if (getActivity() == null || !isAdded() || isDetached()) return;
final String action = intent.getAction();
if (BROADCAST_STATUS_DESTROYED.equals(action)) {
final long statusId = intent.getLongExtra(EXTRA_STATUS_ID, -1);
if (statusId > 0) {
deleteStatus(statusId);
}
} else if (BROADCAST_STATUS_RETWEETED.equals(action)) {
if (BROADCAST_STATUS_RETWEETED.equals(action)) {
final long status_id = intent.getLongExtra(EXTRA_STATUS_ID, -1);
final boolean retweeted = intent.getBooleanExtra(EXTRA_RETWEETED, false);
if (status_id > 0 && !retweeted) {
@ -157,14 +152,10 @@ public abstract class ParcelableStatusesListFragment extends BaseStatusesListFra
@Override
public void onStart() {
super.onStart();
final IntentFilter filter = new IntentFilter(BROADCAST_STATUS_DESTROYED);
filter.addAction(BROADCAST_STATUS_RETWEETED);
registerReceiver(mStateReceiver, filter);
}
@Override
public void onStop() {
unregisterReceiver(mStateReceiver);
super.onStop();
}

View File

@ -125,7 +125,6 @@ import static org.mariotaku.twidere.util.Utils.getMapStaticImageUri;
import static org.mariotaku.twidere.util.Utils.getTwitterInstance;
import static org.mariotaku.twidere.util.Utils.getUserTypeIconRes;
import static org.mariotaku.twidere.util.Utils.isMyRetweet;
import static org.mariotaku.twidere.util.Utils.isSameAccount;
import static org.mariotaku.twidere.util.Utils.openImageDirectly;
import static org.mariotaku.twidere.util.Utils.openMap;
import static org.mariotaku.twidere.util.Utils.openStatus;
@ -196,14 +195,6 @@ public class StatusFragmentOld extends ParcelableStatusesListFragment implements
// }
// break;
// }
case BROADCAST_STATUS_FAVORITE_CREATED: {
final ParcelableStatus status = intent.getParcelableExtra(EXTRA_STATUS);
if (mStatus != null && status != null && isSameAccount(context, status.account_id, mStatus.account_id)
&& status.id == getStatusId()) {
getStatus(true);
}
break;
}
case BROADCAST_STATUS_RETWEETED: {
final long status_id = intent.getLongExtra(EXTRA_STATUS_ID, -1);
if (status_id > 0 && status_id == getStatusId()) {
@ -684,7 +675,6 @@ public class StatusFragmentOld extends ParcelableStatusesListFragment implements
public void onStart() {
super.onStart();
final IntentFilter filter = new IntentFilter();
filter.addAction(BROADCAST_STATUS_FAVORITE_CREATED);
filter.addAction(BROADCAST_STATUS_RETWEETED);
registerReceiver(mStatusReceiver, filter);
updateUserColor();

View File

@ -20,8 +20,6 @@
package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.Loader;
@ -30,39 +28,11 @@ import org.mariotaku.twidere.model.ParcelableStatus;
import java.util.List;
import static org.mariotaku.twidere.util.Utils.isSameAccount;
/**
* Created by mariotaku on 14/12/2.
*/
public class UserFavoritesFragment extends ParcelableStatusesFragment {
@Override
protected void onReceivedBroadcast(Intent intent, String action) {
switch (action) {
case BROADCAST_STATUS_FAVORITE_DESTROYED: {
final Context context = getActivity();
final ParcelableStatus status = intent.getParcelableExtra(EXTRA_STATUS);
final Bundle args = getArguments();
if (context == null || status == null || args == null) return;
final long userId = args.getLong(EXTRA_USER_ID, -1);
final String screenName = args.getString(EXTRA_SCREEN_NAME);
if (isSameAccount(context, status.account_id, userId)
|| isSameAccount(context, status.account_id, screenName)) {
deleteStatus(status.id);
}
return;
}
}
super.onReceivedBroadcast(intent, action);
}
@Override
protected void onSetIntentFilter(IntentFilter filter) {
super.onSetIntentFilter(filter);
filter.addAction(BROADCAST_STATUS_FAVORITE_DESTROYED);
}
@Override
public Loader<List<ParcelableStatus>> onCreateLoader(int id, Bundle args) {
setRefreshing(true);

View File

@ -58,8 +58,11 @@ import org.mariotaku.twidere.service.BackgroundOperationService;
import org.mariotaku.twidere.task.CacheUsersStatusesTask;
import org.mariotaku.twidere.task.ManagedAsyncTask;
import org.mariotaku.twidere.task.TwidereAsyncTask;
import org.mariotaku.twidere.util.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.util.message.FriendshipUpdatedEvent;
import org.mariotaku.twidere.util.message.ProfileUpdatedEvent;
import org.mariotaku.twidere.util.message.StatusDestroyedEvent;
import java.io.FileNotFoundException;
import java.util.ArrayList;
@ -834,9 +837,8 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
@Override
protected void onPostExecute(final SingleResponse<ParcelableStatus> result) {
if (result.hasData()) {
final Intent intent = new Intent(BROADCAST_STATUS_FAVORITE_CREATED);
intent.putExtra(EXTRA_STATUS, result.getData());
mContext.sendBroadcast(intent);
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
bus.post(new FavoriteCreatedEvent(result.getData()));
mMessagesManager.showOkMessage(R.string.status_favorited, false);
} else {
mMessagesManager.showErrorMessage(R.string.action_favoriting, result.getException(), true);
@ -1353,9 +1355,8 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
@Override
protected void onPostExecute(final SingleResponse<ParcelableStatus> result) {
if (result.hasData()) {
final Intent intent = new Intent(BROADCAST_STATUS_FAVORITE_DESTROYED);
intent.putExtra(EXTRA_STATUS, result.getData());
mContext.sendBroadcast(intent);
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
bus.post(new FavoriteDestroyedEvent(result.getData()));
mMessagesManager.showInfoMessage(R.string.status_unfavorited, false);
} else {
mMessagesManager.showErrorMessage(R.string.action_unfavoriting, result.getException(), true);
@ -1455,7 +1456,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
}
class DestroyStatusTask extends ManagedAsyncTask<Void, Void, SingleResponse<twitter4j.Status>> {
class DestroyStatusTask extends ManagedAsyncTask<Void, Void, SingleResponse<ParcelableStatus>> {
private final long account_id;
@ -1468,17 +1469,17 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
}
@Override
protected SingleResponse<twitter4j.Status> doInBackground(final Void... params) {
protected SingleResponse<ParcelableStatus> doInBackground(final Void... params) {
final Twitter twitter = getTwitterInstance(mContext, account_id, false);
if (twitter == null) return SingleResponse.getInstance();
twitter4j.Status status = null;
ParcelableStatus status = null;
TwitterException exception = null;
try {
status = twitter.destroyStatus(status_id);
status = new ParcelableStatus(twitter.destroyStatus(status_id), account_id, false);
} catch (final TwitterException e) {
exception = e;
}
if (status != null || (exception != null && exception.getErrorCode() == HttpResponseCode.NOT_FOUND)) {
if (status != null || exception.getErrorCode() == HttpResponseCode.NOT_FOUND) {
final ContentValues values = new ContentValues();
values.put(Statuses.MY_RETWEET_ID, -1);
for (final Uri uri : TweetStore.STATUSES_URIS) {
@ -1490,16 +1491,16 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
}
@Override
protected void onPostExecute(final SingleResponse<twitter4j.Status> result) {
if (result.hasData() && result.getData().getId() > 0) {
if (result.getData().getRetweetedStatus() != null) {
protected void onPostExecute(final SingleResponse<ParcelableStatus> result) {
if (result.hasData()) {
final ParcelableStatus status = result.getData();
if (status.retweet_id > 0) {
mMessagesManager.showInfoMessage(R.string.retweet_cancelled, false);
} else {
mMessagesManager.showInfoMessage(R.string.status_deleted, false);
}
final Intent intent = new Intent(BROADCAST_STATUS_DESTROYED);
intent.putExtra(EXTRA_STATUS_ID, status_id);
mContext.sendBroadcast(intent);
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
bus.post(new StatusDestroyedEvent(status));
} else {
mMessagesManager.showErrorMessage(R.string.action_deleting, result.getException(), true);
}

View File

@ -0,0 +1,37 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.util.message;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.model.ParcelableStatus;
/**
* Created by mariotaku on 14/12/10.
*/
public class FavoriteCreatedEvent {
@NonNull
public final ParcelableStatus status;
public FavoriteCreatedEvent(@NonNull ParcelableStatus status) {
this.status = status;
}
}

View File

@ -0,0 +1,37 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.util.message;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.model.ParcelableStatus;
/**
* Created by mariotaku on 14/12/10.
*/
public class FavoriteDestroyedEvent {
@NonNull
public final ParcelableStatus status;
public FavoriteDestroyedEvent(@NonNull ParcelableStatus status) {
this.status = status;
}
}

View File

@ -0,0 +1,34 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.util.message;
import org.mariotaku.twidere.model.ParcelableStatus;
/**
* Created by mariotaku on 14/12/10.
*/
public class StatusDestroyedEvent {
public final ParcelableStatus status;
public StatusDestroyedEvent(ParcelableStatus status) {
this.status = status;
}
}

View File

@ -39,11 +39,13 @@ import android.widget.ProgressBar;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.accessor.ViewAccessor;
import org.mariotaku.twidere.view.helper.PressElevateViewHelper;
import org.mariotaku.twidere.view.iface.IHomeActionButton;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class HomeActionButton extends FrameLayout implements IHomeActionButton {
private final PressElevateViewHelper mHelper;
private final ImageView mIconView;
private final ProgressBar mProgressBar;
@ -57,6 +59,7 @@ public class HomeActionButton extends FrameLayout implements IHomeActionButton {
public HomeActionButton(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
mHelper = new PressElevateViewHelper(this);
inflate(ThemeUtils.getActionBarContext(context), R.layout.action_item_home_actions, this);
mIconView = (ImageView) findViewById(android.R.id.icon);
mProgressBar = (ProgressBar) findViewById(android.R.id.progress);
@ -107,6 +110,15 @@ public class HomeActionButton extends FrameLayout implements IHomeActionButton {
setTitle(getResources().getText(title));
}
@Override
public void setPressed(boolean pressed) {
final boolean oldState = mHelper.getState();
super.setPressed(pressed);
final boolean state = mHelper.getState();
if (oldState == state) return;
mHelper.updateButtonState();
}
private static class HomeActionButtonOutlineProvider extends ViewOutlineProvider {
@Override
public void getOutline(View view, Outline outline) {
@ -116,4 +128,6 @@ public class HomeActionButton extends FrameLayout implements IHomeActionButton {
outline.setOval(left, top, left + size, top + size);
}
}
}

View File

@ -0,0 +1,123 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.view.helper;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.os.Build;
import android.view.View;
/**
* Created by mariotaku on 14-7-30.
*/
public class PressElevateViewHelper implements Animator.AnimatorListener {
private static final float ELEVATION = 2f;
private final View mView;
private Animator mCurrentAnimator;
private AnimatorRunnable mAnimatorRunnable;
public PressElevateViewHelper(View view) {
mView = view;
}
public boolean getState() {
return mView.isPressed();
}
public void updateButtonState() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
final boolean state = getState();
final AnimatorRunnable runnable = new AnimatorRunnable(this, state);
if (mCurrentAnimator != null) {
mAnimatorRunnable = runnable;
mCurrentAnimator = null;
return;
}
runnable.run();
mAnimatorRunnable = null;
}
@Override
public void onAnimationStart(Animator animation) {
mCurrentAnimator = animation;
}
@Override
public void onAnimationEnd(Animator animation) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
mCurrentAnimator = null;
final AnimatorRunnable runnable = mAnimatorRunnable;
if (runnable != null) {
runnable.run();
}
mAnimatorRunnable = null;
}
@Override
public void onAnimationCancel(Animator animation) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
mCurrentAnimator = null;
final AnimatorRunnable runnable = mAnimatorRunnable;
if (runnable != null) {
runnable.run();
}
mAnimatorRunnable = null;
}
@Override
public void onAnimationRepeat(Animator animation) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
}
public View getView() {
return mView;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static class AnimatorRunnable implements Runnable {
private final PressElevateViewHelper helper;
private final View view;
private final boolean state;
private final float elevation;
AnimatorRunnable(PressElevateViewHelper helper, boolean state) {
this.helper = helper;
this.state = state;
this.view = helper.getView();
this.elevation = view.getResources().getDisplayMetrics().density * ELEVATION;
}
@Override
public void run() {
final float from = state ? 0 : elevation;
final float to = state ? elevation : 0;
final ObjectAnimator translationZ = ObjectAnimator.ofFloat(view, View.TRANSLATION_Z, from, to);
translationZ.setDuration(200);
translationZ.addListener(helper);
translationZ.start();
}
}
}