improve snackbar displays

This commit is contained in:
Phillip Thelen 2017-09-26 17:01:01 +02:00
parent 7a71d621a8
commit 2949e63eb9
17 changed files with 176 additions and 78 deletions

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/gray_50" />
<corners android:radius="100dp" />
<stroke android:width="1dp" android:color="@color/black_20_alpha" />
</shape>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/white_95_alpha" />
<corners android:topRightRadius="40dp" android:bottomRightRadius="40dp" />
</shape>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@color/white" />
</shape>

View file

@ -1,45 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true"
android:clipToPadding="false">
<LinearLayout
android:id="@+id/snackbar_view"
android:orientation="vertical"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingLeft="6dp"
android:gravity="center"
tools:background="@drawable/snackbar_background_green"
android:layout_marginBottom="16dp"
android:layout_gravity="center_horizontal"
android:elevation="24dp">
<TextView
android:id="@+id/snackbar_title"
<ImageView
android:id="@+id/leftImageView"
android:layout_height="@dimen/snackbar_image_size"
android:layout_width="@dimen/snackbar_image_size"
android:background="@drawable/white_circle_background"
android:visibility="gone"
tools:visibility="visible" />
<LinearLayout
android:id="@+id/content_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="This is the Title"
android:gravity="center"
style="@style/Title2"
android:textSize="18sp"
android:orientation="vertical"
android:paddingLeft="12dp"
android:paddingRight="18dp"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
android:id="@+id/snackbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="This is the Title"
android:gravity="center"
style="@style/Title2"
android:textSize="18sp"
android:visibility="gone"
tools:visibility="visible"
android:textColor="@color/white_75_alpha"/>
<TextView
android:id="@+id/snackbar_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="This is the Content"
android:gravity="center"
style="@style/Body1"
android:textSize="13sp"
android:visibility="gone"
tools:visibility="visible"
android:textColor="@color/white_75_alpha"/>
</LinearLayout>
<LinearLayout
android:id="@+id/rightView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:background="@drawable/snackbar_right_bg"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:layout_marginRight="1dp"
android:layout_marginTop="1dp"
android:layout_marginBottom="1dp"
android:visibility="gone"
tools:visibility="visible"
android:textColor="@color/white_75_alpha"/>
<TextView
android:id="@+id/snackbar_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="This is the Content"
android:gravity="center"
style="@style/Body1"
android:textSize="13sp"
android:visibility="gone"
tools:visibility="visible"
android:textColor="@color/white_75_alpha"/>
tools:visibility="visible">
<ImageView
android:id="@+id/rightIconView"
android:layout_width="@dimen/currency_icon_size"
android:layout_height="@dimen/currency_icon_size" />
<TextView
android:id="@+id/rightTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="4dp"
tools:text="12"/>
</LinearLayout>
</LinearLayout>
</FrameLayout>

View file

@ -130,6 +130,7 @@
<color name="gem_icon_color">#24cc8f</color>
<color name="subscription_description_text">#b1000000</color>
<color name="pill_gray">#efefef</color>
<color name="white_95_alpha">#f2ffffff</color>
<color name="white_80_alpha">#ccffffff</color>
<color name="white_75_alpha">#bfffffff</color>
<color name="white_50_alpha">#7fffffff</color>

View file

@ -117,4 +117,5 @@
<dimen name="shopitem_dialog_content_inset">24dp</dimen>
<dimen name="reward_width">84dp</dimen>
<dimen name="task_min_height">60dp</dimen>
<dimen name="snackbar_image_size">46dp</dimen>
</resources>

View file

@ -337,7 +337,8 @@
<string name="close">Close</string>
<string name="share">Share</string>
<string name="notification_pet_fed" >You fed your %1$s %2$s!</string>
<string name="notification_purchase" >%s was purchased</string>
<string name="notification_purchase" >You purchased %s</string>
<string name="notification_purchase_reward" >You purchased a reward</string>
<string name="sectionpets">Base Pets</string>
<string name="sectionpremiumPets">Magic Potion Pets</string>
<string name="sectionquestPets">Quest Pets</string>

View file

@ -1,5 +1,7 @@
package com.habitrpg.android.habitica.events;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.view.View;
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar;
@ -10,8 +12,12 @@ import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar;
public class ShowSnackbarEvent {
public Drawable leftImage;
public String title;
public String text;
public HabiticaSnackbar.SnackbarDisplayType type;
public View specialView;
public Drawable rightIcon;
public int rightTextColor;
public String rightText;
}

View file

@ -32,7 +32,7 @@ public class DisplayItemDropUseCase extends UseCase<DisplayItemDropUseCase.Reque
if (data != null) {
if (data.drop != null) {
new Handler().postDelayed(() -> {
HabiticaSnackbar.showSnackbar(requestValues.context, requestValues.snackbarTargetView,
HabiticaSnackbar.showSnackbar(requestValues.snackbarTargetView,
data.drop.getDialog(), HabiticaSnackbar.SnackbarDisplayType.DROP);
soundManager.loadAndPlayAudio(SoundManager.SoundItemDrop);
}, 3000L);

View file

@ -58,7 +58,7 @@ public class NotifyUserUseCase extends UseCase<NotifyUserUseCase.RequestValues,
.map(User::getStats);
} else {
Pair<View, SnackbarDisplayType> pair = getNotificationAndAddStatsToUser(requestValues.context, requestValues.xp, requestValues.hp, requestValues.gold, requestValues.mp, requestValues.user);
showSnackbar(requestValues.context, requestValues.snackbarTargetView, null, null, pair.first, pair.second);
showSnackbar(requestValues.snackbarTargetView, null, null, pair.first, pair.second);
return Observable.just(stats);
}
});
@ -66,7 +66,7 @@ public class NotifyUserUseCase extends UseCase<NotifyUserUseCase.RequestValues,
public static Pair<View, SnackbarDisplayType> getNotificationAndAddStatsToUser(Context context, double xp, double hp, double gold, double mp, User user){
SnackbarDisplayType displayType = SnackbarDisplayType.NORMAL;
SnackbarDisplayType displayType = SnackbarDisplayType.SUCCESS;
LinearLayout container = new LinearLayout(context);
container.setOrientation(LinearLayout.HORIZONTAL);

View file

@ -413,7 +413,7 @@ public class ChallengeDetailActivity extends BaseActivity {
@Subscribe
public void onEvent(final BuyRewardCommand event) {
if (user.getStats().getGp() < event.Reward.getValue()) {
HabiticaSnackbar.showSnackbar(this, floatingMenuWrapper, getString(R.string.no_gold), HabiticaSnackbar.SnackbarDisplayType.FAILURE);
HabiticaSnackbar.showSnackbar(floatingMenuWrapper, getString(R.string.no_gold), HabiticaSnackbar.SnackbarDisplayType.FAILURE);
return;
}
@ -421,7 +421,7 @@ public class ChallengeDetailActivity extends BaseActivity {
if (event.Reward.specialTag == null || !event.Reward.specialTag.equals("item")) {
buyRewardUseCase.observable(new BuyRewardUseCase.RequestValues(user, event.Reward))
.subscribe(res -> HabiticaSnackbar.showSnackbar(this, floatingMenuWrapper, getString(R.string.notification_purchase, event.Reward.getText()), HabiticaSnackbar.SnackbarDisplayType.NORMAL), error -> {});
.subscribe(res -> HabiticaSnackbar.showSnackbar(floatingMenuWrapper, getString(R.string.notification_purchase_reward), HabiticaSnackbar.SnackbarDisplayType.NORMAL), error -> {});
}
}

View file

@ -187,7 +187,7 @@ public class FullProfileActivity extends BaseActivity {
final AlertDialog addMessageDialog = new AlertDialog.Builder(this)
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
socialRepository.postPrivateMessage(userId, emojiEditText.getText().toString())
.subscribe(postChatMessageResult -> showSnackbar(FullProfileActivity.this, (ViewGroup) FullProfileActivity.this.fullprofile_scrollview.getChildAt(0),
.subscribe(postChatMessageResult -> showSnackbar((ViewGroup) FullProfileActivity.this.fullprofile_scrollview.getChildAt(0),
String.format(getString(R.string.profile_message_sent_to), userName), SnackbarDisplayType.NORMAL), RxErrorHandler.handleEmptyError());
UiUtils.dismissKeyboard(this);

View file

@ -12,6 +12,7 @@ import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@ -554,7 +555,7 @@ public class MainActivity extends BaseActivity implements TutorialView.OnTutoria
final String rewardKey = event.Reward.getId();
if (user.getStats().getGp() < event.Reward.getValue()) {
showSnackbar(this, floatingMenuWrapper, getString(R.string.no_gold), SnackbarDisplayType.FAILURE);
showSnackbar(floatingMenuWrapper, getString(R.string.no_gold), SnackbarDisplayType.FAILURE);
return;
}
@ -563,7 +564,7 @@ public class MainActivity extends BaseActivity implements TutorialView.OnTutoria
int maxHp = user.getStats().getMaxHealth();
if (currentHp == maxHp) {
showSnackbar(this, floatingMenuWrapper, getString(R.string.no_potion), SnackbarDisplayType.FAILURE_BLUE);
showSnackbar(floatingMenuWrapper, getString(R.string.no_potion), SnackbarDisplayType.FAILURE_BLUE);
return;
}
}
@ -582,11 +583,15 @@ public class MainActivity extends BaseActivity implements TutorialView.OnTutoria
}
soundManager.loadAndPlayAudio(SoundManager.SoundItemDrop);
}
showSnackbar(MainActivity.this, floatingMenuWrapper, snackbarMessage, SnackbarDisplayType.NORMAL);
showSnackbar(floatingMenuWrapper, null, snackbarMessage, new BitmapDrawable(getResources(), HabiticaIconsHelper.imageOfGold()), ContextCompat.getColor(this, R.color.yellow_10), "-"+event.Reward.value, SnackbarDisplayType.NORMAL);
}, RxErrorHandler.handleEmptyError());
} else {
buyRewardUseCase.observable(new BuyRewardUseCase.RequestValues(user, event.Reward))
.subscribe(res -> showSnackbar(this, floatingMenuWrapper, getString(R.string.notification_purchase, event.Reward.getText()), SnackbarDisplayType.NORMAL), error -> {});
.subscribe(res -> showSnackbar(floatingMenuWrapper, null, getString(R.string.notification_purchase_reward),
new BitmapDrawable(getResources(), HabiticaIconsHelper.imageOfGold()),
ContextCompat.getColor(this, R.color.yellow_10),
"-"+ ((int) event.Reward.value),
SnackbarDisplayType.DROP), error -> {});
}
}
@ -659,7 +664,7 @@ public class MainActivity extends BaseActivity implements TutorialView.OnTutoria
final Pet pet = event.usingPet;
this.inventoryRepository.feedPet(event.usingPet, event.usingFood)
.subscribe(feedResponse -> {
showSnackbar(MainActivity.this, floatingMenuWrapper, getString(R.string.notification_pet_fed, pet.getColorText(), pet.getAnimalText()), SnackbarDisplayType.NORMAL);
showSnackbar(floatingMenuWrapper, getString(R.string.notification_pet_fed, pet.getColorText(), pet.getAnimalText()), SnackbarDisplayType.NORMAL);
if (feedResponse.value == -1) {
FrameLayout mountWrapper = (FrameLayout) View.inflate(this, R.layout.pet_imageview, null);
SimpleDraweeView mountImageView = (SimpleDraweeView) mountWrapper.findViewById(R.id.pet_imageview);
@ -923,7 +928,7 @@ public class MainActivity extends BaseActivity implements TutorialView.OnTutoria
@Subscribe
public void showSnackBarEvent(ShowSnackbarEvent event) {
showSnackbar(this, floatingMenuWrapper, event.title, event.text, event.specialView, event.type);
showSnackbar(floatingMenuWrapper, event.leftImage, event.title, event.text, event.specialView, event.rightIcon, event.rightTextColor, event.rightText, event.type);
}
public boolean isAppBarExpanded() {

View file

@ -3,8 +3,10 @@ package com.habitrpg.android.habitica.ui.fragments.skills;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
@ -24,6 +26,7 @@ import com.habitrpg.android.habitica.ui.activities.SkillMemberActivity;
import com.habitrpg.android.habitica.ui.activities.SkillTasksActivity;
import com.habitrpg.android.habitica.ui.adapter.SkillsRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper;
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar;
import org.greenrobot.eventbus.Subscribe;
@ -130,24 +133,17 @@ public class SkillsFragment extends BaseMainFragment {
public void displaySkillResult(Skill usedSkill, SkillResponse response) {
removeProgressDialog();
adapter.setMana(response.user.getStats().mp);
StringBuilder message = new StringBuilder();
if (activity == null) {
return;
}
if ("special".equals(usedSkill.habitClass)) {
message.append(getContext().getString(R.string.used_skill_without_mana, usedSkill.text));
showSnackbar(activity.getFloatingMenuWrapper(), getContext().getString(R.string.used_skill_without_mana, usedSkill.text), HabiticaSnackbar.SnackbarDisplayType.BLUE);
} else {
message.append(getContext().getString(R.string.used_skill, usedSkill.text, usedSkill.mana));
}
if (response.expDiff != 0) {
message.append(" + ").append(round(response.expDiff, 2)).append(" XP");
}
if (response.hpDiff != 0) {
message.append(" + ").append(round(response.hpDiff, 2)).append(" HP");
}
if (response.goldDiff != 0) {
message.append(" + ").append(round(response.goldDiff, 2)).append(" GP");
}
if (activity != null) {
showSnackbar(activity, activity.getFloatingMenuWrapper(), message.toString(), HabiticaSnackbar.SnackbarDisplayType.NORMAL);
showSnackbar(activity.getFloatingMenuWrapper(), null,
getContext().getString(R.string.used_skill_without_mana, usedSkill.text),
new BitmapDrawable(getResources(), HabiticaIconsHelper.imageOfMagic()),
ContextCompat.getColor(getContext(), R.color.blue_10), "-"+usedSkill.mana,
HabiticaSnackbar.SnackbarDisplayType.BLUE);
}
userRepository.retrieveUser(false).subscribe(habitRPGUser -> {}, RxErrorHandler.handleEmptyError());
}

View file

@ -204,7 +204,7 @@ public class ChatListFragment extends BaseFragment implements SwipeRefreshLayout
ClipData messageText = ClipData.newPlainText("Chat message", chatMessage.text);
clipMan.setPrimaryClip(messageText);
MainActivity activity = (MainActivity) getActivity();
showSnackbar(activity, activity.getFloatingMenuWrapper(), getString(R.string.chat_message_copied), SnackbarDisplayType.NORMAL);
showSnackbar(activity.getFloatingMenuWrapper(), getString(R.string.chat_message_copied), SnackbarDisplayType.NORMAL);
}
public void showFlagConfirmationDialog(ChatMessage chatMessage) {
@ -213,7 +213,7 @@ public class ChatListFragment extends BaseFragment implements SwipeRefreshLayout
.setPositiveButton(R.string.flag_confirm, (dialog, id) -> socialRepository.flagMessage(chatMessage)
.subscribe(aVoid -> {
MainActivity activity = (MainActivity) getActivity();
showSnackbar(activity, activity.getFloatingMenuWrapper(), "Flagged message by " + chatMessage.user, SnackbarDisplayType.NORMAL);
showSnackbar(activity.getFloatingMenuWrapper(), "Flagged message by " + chatMessage.user, SnackbarDisplayType.NORMAL);
}, RxErrorHandler.handleEmptyError()))
.setNegativeButton(R.string.action_cancel, (dialog, id) -> {});
builder.show();

View file

@ -1,7 +1,10 @@
package com.habitrpg.android.habitica.ui.views;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.design.widget.BaseTransientBottomBar;
@ -12,6 +15,7 @@ import android.text.Spannable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -63,6 +67,29 @@ public class HabiticaSnackbar extends BaseTransientBottomBar<HabiticaSnackbar> {
return this;
}
public HabiticaSnackbar setRightDiff(Drawable icon, int textColor, String text) {
if (icon == null) {
return this;
}
View rightView = getView().findViewById(R.id.rightView);
rightView.setVisibility(View.VISIBLE);
ImageView rightIconView = getView().findViewById(R.id.rightIconView);
rightIconView.setImageDrawable(icon);
TextView rightTextView = getView().findViewById(R.id.rightTextView);
rightTextView.setTextColor(textColor);
rightTextView.setText(text);
return this;
}
public HabiticaSnackbar setLeftIcon(Drawable image) {
if (image == null) {
return this;
}
ImageView imageView = getView().findViewById(R.id.leftImageView);
imageView.setImageDrawable(image);
return this;
}
public HabiticaSnackbar setBackgroundColor(@ColorInt int color) {
getView().setBackgroundColor(color);
return this;
@ -77,7 +104,7 @@ public class HabiticaSnackbar extends BaseTransientBottomBar<HabiticaSnackbar> {
private HabiticaSnackbar setSpecialView(View specialView) {
if (specialView != null) {
LinearLayout snackbarView = (LinearLayout) getView().findViewById(R.id.snackbar_view);
LinearLayout snackbarView = (LinearLayout) getView().findViewById(R.id.content_container);
snackbarView.addView(specialView);
}
return this;
@ -95,38 +122,42 @@ public class HabiticaSnackbar extends BaseTransientBottomBar<HabiticaSnackbar> {
public void animateContentIn(int delay, int duration) {
content.setScaleY(0f);
ViewCompat.animate(content).scaleY(1f).setDuration(duration).setStartDelay(delay);
ViewCompat.animate(content).alpha(1f).setDuration(duration).setStartDelay(delay);
}
@Override
public void animateContentOut(int delay, int duration) {
content.setScaleY(1);
ViewCompat.animate(content).scaleY(0f).setDuration(duration).setStartDelay(delay);
ViewCompat.animate(content).alpha(0f).setDuration(duration).setStartDelay(delay);
}
}
/**
* Shows snackbar in given container.
*
* @param context Context.
* @param container Parent view where Snackbar will appear.
* @param content message.
*/
public static void showSnackbar(Context context, ViewGroup container, CharSequence content, SnackbarDisplayType displayType) {
showSnackbar(context, container, null, content, null, displayType);
public static void showSnackbar(ViewGroup container, CharSequence content, SnackbarDisplayType displayType) {
showSnackbar(container, null, null, content, null, null, 0, null, displayType);
}
/**
* Shows snackbar in given container.
*
* @param context Context.
* @param container Parent view where Snackbar will appear.
* @param content message.
*/
public static void showSnackbar(Context context, ViewGroup container, CharSequence title, CharSequence content, View specialView, SnackbarDisplayType displayType) {
public static void showSnackbar(ViewGroup container, Drawable leftImage, CharSequence title, CharSequence content, SnackbarDisplayType displayType) {
showSnackbar(container, leftImage, title, content, null, null, 0, null, displayType);
}
public static void showSnackbar(ViewGroup container, CharSequence title, CharSequence content, Drawable rightIcon, int rightTextColor, String rightText, SnackbarDisplayType displayType) {
showSnackbar(container, null, title, content, null, rightIcon, rightTextColor, rightText, displayType);
}
public static void showSnackbar(ViewGroup container, CharSequence title, CharSequence content, View specialView, SnackbarDisplayType displayType) {
showSnackbar(container, null, title, content, specialView, null, 0, null, displayType);
}
public static void showSnackbar(ViewGroup container, Drawable leftImage, CharSequence title, CharSequence content, View specialView, Drawable rightIcon, int rightTextColor, String rightText, SnackbarDisplayType displayType) {
HabiticaSnackbar snackbar = HabiticaSnackbar.make(container, Snackbar.LENGTH_LONG)
.setTitle(title)
.setText(content)
.setSpecialView(specialView);
.setSpecialView(specialView)
.setLeftIcon(leftImage)
.setRightDiff(rightIcon, rightTextColor, rightText);
switch (displayType) {
case FAILURE:
@ -134,10 +165,12 @@ public class HabiticaSnackbar extends BaseTransientBottomBar<HabiticaSnackbar> {
break;
case FAILURE_BLUE:
case BLUE:
case DROP:
snackbar.setBackgroundResource(R.drawable.snackbar_background_blue);
break;
case DROP:
case NORMAL:
snackbar.setBackgroundResource(R.drawable.snackbar_background_gray);
break;
case SUCCESS:
snackbar.setBackgroundResource(R.drawable.snackbar_background_green);
break;
@ -149,5 +182,4 @@ public class HabiticaSnackbar extends BaseTransientBottomBar<HabiticaSnackbar> {
public enum SnackbarDisplayType {
NORMAL, FAILURE, FAILURE_BLUE, DROP, SUCCESS, BLUE
}
}

View file

@ -175,7 +175,6 @@ public class PurchaseDialog extends AlertDialog {
}
@OnClick(R.id.closeButton)
void onCloseClicked() {
dismiss();
@ -203,6 +202,9 @@ public class PurchaseDialog extends AlertDialog {
ShowSnackbarEvent event = new ShowSnackbarEvent();
event.title = getContext().getString(R.string.successful_purchase, shopItem.text);
event.type = HabiticaSnackbar.SnackbarDisplayType.NORMAL;
event.rightIcon = priceLabel.getCompoundDrawables()[0];
event.rightTextColor = priceLabel.getCurrentTextColor();
event.rightText = "-"+priceLabel.getText();
EventBus.getDefault().post(event);
})
.flatMap(buyResponse -> userRepository.retrieveUser(false, true))