/*
* Copyright (C) 2015 Simon Vig Therkildsen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.simonvt.cathode.widget;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.ViewPropertyAnimator;
import android.widget.TextView;
import java.util.LinkedList;
import net.simonvt.cathode.R;
public class Crouton extends TextView {
private static final String STATE_MESSAGES = "net.simonvt.messagebar.Crouton.messages";
private static final String STATE_CURRENT_MESSAGE =
"net.simonvt.messagebar.Crouton.currentMessage";
public static final String STATE_SUPER = "net.simonvt.cathode.widget.Crouton.superState";
private static final int ANIMATION_DURATION = 600;
private static final int HIDE_DELAY = 20000;
private LinkedList<Message> messages = new LinkedList<>();
private Message currentMessage;
private boolean showing;
private Handler handler = new Handler();
public Crouton(Context context) {
super(context);
init(context);
}
public Crouton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public Crouton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
if (isInEditMode()) {
setBackgroundColor(getResources().getColor(android.R.color.holo_red_dark));
setText(R.string.error_unknown_retrying);
}
}
public void show(String message) {
show(message, 0xFF00FF00);
}
public void show(String message, int backgroundColor) {
Message m = new Message(message, backgroundColor);
if (showing) {
messages.add(m);
} else {
show(m);
}
}
private void show(Message message) {
show(message, false);
}
private void show(Message message, boolean immediately) {
showing = true;
setTranslationY(getHeight());
setBackgroundColor(message.backgroundColor);
setText(message.message);
if (immediately) {
setTranslationY(0);
} else {
animator = animate();
animator.translationY(0);
}
handler.postDelayed(hideRunnable, HIDE_DELAY);
}
public void clear() {
messages.clear();
hideRunnable.run();
}
private boolean hasMessages() {
return messages.size() > 0;
}
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (isInEditMode()) {
return;
}
if (animator != null) {
animator.cancel();
}
if (!hasMessages()) {
setTranslationY(getHeight());
} else {
setTranslationY(0);
}
}
ViewPropertyAnimator animator;
private final Runnable hideRunnable = new Runnable() {
@Override public void run() {
animator = animate();
animator.translationY(getHeight()).withEndAction(new Runnable() {
@Override public void run() {
animator = null;
showing = false;
if (hasMessages()) {
Message message = messages.poll();
show(message);
}
}
});
}
};
@Override public void onRestoreInstanceState(Parcelable state) {
Bundle viewState = (Bundle) state;
Parcelable superState = viewState.getParcelable(STATE_SUPER);
super.onRestoreInstanceState(superState);
Message currentMessage = viewState.getParcelable(STATE_CURRENT_MESSAGE);
if (currentMessage != null) {
show(currentMessage, true);
Parcelable[] messages = viewState.getParcelableArray(STATE_MESSAGES);
for (Parcelable p : messages) {
this.messages.add((Message) p);
}
}
}
public Bundle onSaveInstanceState() {
Bundle b = new Bundle();
Parcelable superState = super.onSaveInstanceState();
b.putParcelable(STATE_SUPER, superState);
b.putParcelable(STATE_CURRENT_MESSAGE, currentMessage);
final int count = messages.size();
final Message[] messages = new Message[count];
int i = 0;
for (Message message : this.messages) {
messages[i++] = message;
}
b.putParcelableArray(STATE_MESSAGES, messages);
return b;
}
private static class Message implements Parcelable {
final String message;
final int backgroundColor;
public Message(String message, int backgroundColor) {
this.message = message;
this.backgroundColor = backgroundColor;
}
public Message(Parcel p) {
message = p.readString();
backgroundColor = p.readInt();
}
public void writeToParcel(Parcel out, int flags) {
out.writeString(message);
out.writeInt(backgroundColor);
}
public int describeContents() {
return 0;
}
public static final Parcelable.Creator<Message> CREATOR = new Parcelable.Creator<Message>() {
public Message createFromParcel(Parcel in) {
return new Message(in);
}
public Message[] newArray(int size) {
return new Message[size];
}
};
}
}