Animated Button on Android using AfterEffects and Lottie
I have a question about my implementation of a "special" Next-Button.
First I want to show you my AfterEffects file:
So This Animation has 3 parts
- Green: Entry correct
- Red: Entry incorrect
- Blue: Button has been pressed (visual feedback)
As I could not work this out with AVD and states I decided to use the Lottie library and play the different segments.
Main Activity - Only TestMethod, nothing really to review actually
private void initButtonTwo(){
mNext = findViewById(R.id.next);
mNextButton = new CancelCheckButton(mNext, new NextButtonListener() {
@Override
public void onClick() {
if(enableVibration){
vibrateFeedback();
}
switch (mNextCounter){
//This is just a Test-Method, i want Tick and Cross to alternate
case 1:
case 3:
mNextButton.showTick();
break;
case 2:
case 4:
mNextButton.showCross();
break;
case 5:
mNextButton.showTickEnd();
break;
}
if(mNextCounter >= 5){
mNextCounter = 1;
}else{
mNextCounter = mNextCounter + 1;
}
}
});
}
Interface for Communication Main -> Custom Button C
public interface NextButtonListener {
public void onClick();
}
Custom Class CancelCheckButton
public class CancelCheckButton implements View.OnTouchListener, Animator.AnimatorListener {
private LottieAnimationView mAnimationView;
private NextButtonListener mListener;
private final String LOG_TAG = this.getClass().getSimpleName();
public CancelCheckButton(LottieAnimationView mView, final NextButtonListener mListener){
this.mAnimationView = mView;
this.mListener = mListener;
this.setTouchListener();
this.setAnimatorListener();
Log.d(LOG_TAG, "CancelCheckButton: called");
}
private void setAnimatorListener(){
mAnimationView.addAnimatorListener(this);
Log.d(LOG_TAG, "CancelCheckButton: AnimatorListener called");
}
private void setTouchListener(){
mAnimationView.setOnTouchListener(this);
Log.d(LOG_TAG, "CancelCheckButton: TouchListener called");
}
/*****TOUCH INTERACTION ANIMATION*****/
public void showPressed(){
mAnimationView.setMinAndMaxFrame(452,462);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: PressAnimation played");
}
public void showReleased(){
mAnimationView.setMinAndMaxFrame(485,495);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: RelleaseAnimation played");
}
/*****FEDBACK CONTROL ANIMATION*****/
public void showTick(){
mAnimationView.setOnTouchListener(null);
mAnimationView.setMinAndMaxFrame(58,181);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: TickAnimation played, Touchlistener deactivated");
}
public void showTickEnd(){
mAnimationView.setOnTouchListener(null);
mAnimationView.setMinAndMaxFrame(58,94);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: TickEndAnimation played, Touchlistener deactivated");
}
public void showCross(){
mAnimationView.setOnTouchListener(null);
mAnimationView.setMinAndMaxFrame(300,431);
mAnimationView.setSpeed(2.0f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: CrossAnimation played, Touchlistener deactivated");
}
/*****LISTENER*****/
@Override
public boolean onTouch(View v, MotionEvent event) {
if(v.getId() == mAnimationView.getId()){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
showPressed();
Log.d(LOG_TAG, "CancelCheckButton: View is touched");
break;
case MotionEvent.ACTION_UP:
showReleased();
v.performClick();
mListener.onClick();
Log.d(LOG_TAG, "CancelCheckButton: View is relleased, OnClick is fired");
break;
}
}
return true;
}
@Override
public void onAnimationStart(Animator animation) {
Log.d(LOG_TAG, "CancelCheckButton: Called Animation is STARTED and Touchlistener deactivated");
}
@Override
public void onAnimationEnd(Animator animation) {
setTouchListener();
Log.d(LOG_TAG, "CancelCheckButton: Called Animation is FINISHED and Touchlistener reset");
}
@Override
public void onAnimationCancel(Animator animation) {
Log.d(LOG_TAG, "CancelCheckButton: Called Animation is CANCELED and Touchlistener reset");
}
@Override
public void onAnimationRepeat(Animator animation) {
}
}
Notes
When you click on the button I want the blue part to appear and disappear when the finger is released. As it is a very short animation I decided to not deactivate the OnTouchListener. No matter how fast I tipped I could not see a difference.
For the green or red part I deactivated the onTouchListener to avoid an accidental restart of the animation.
It actually works perfectly but even though I tried to keep the code clean I am not happy with it. Is there a more effective or at least a more common way to do it?
java android animation
New contributor
add a comment |
I have a question about my implementation of a "special" Next-Button.
First I want to show you my AfterEffects file:
So This Animation has 3 parts
- Green: Entry correct
- Red: Entry incorrect
- Blue: Button has been pressed (visual feedback)
As I could not work this out with AVD and states I decided to use the Lottie library and play the different segments.
Main Activity - Only TestMethod, nothing really to review actually
private void initButtonTwo(){
mNext = findViewById(R.id.next);
mNextButton = new CancelCheckButton(mNext, new NextButtonListener() {
@Override
public void onClick() {
if(enableVibration){
vibrateFeedback();
}
switch (mNextCounter){
//This is just a Test-Method, i want Tick and Cross to alternate
case 1:
case 3:
mNextButton.showTick();
break;
case 2:
case 4:
mNextButton.showCross();
break;
case 5:
mNextButton.showTickEnd();
break;
}
if(mNextCounter >= 5){
mNextCounter = 1;
}else{
mNextCounter = mNextCounter + 1;
}
}
});
}
Interface for Communication Main -> Custom Button C
public interface NextButtonListener {
public void onClick();
}
Custom Class CancelCheckButton
public class CancelCheckButton implements View.OnTouchListener, Animator.AnimatorListener {
private LottieAnimationView mAnimationView;
private NextButtonListener mListener;
private final String LOG_TAG = this.getClass().getSimpleName();
public CancelCheckButton(LottieAnimationView mView, final NextButtonListener mListener){
this.mAnimationView = mView;
this.mListener = mListener;
this.setTouchListener();
this.setAnimatorListener();
Log.d(LOG_TAG, "CancelCheckButton: called");
}
private void setAnimatorListener(){
mAnimationView.addAnimatorListener(this);
Log.d(LOG_TAG, "CancelCheckButton: AnimatorListener called");
}
private void setTouchListener(){
mAnimationView.setOnTouchListener(this);
Log.d(LOG_TAG, "CancelCheckButton: TouchListener called");
}
/*****TOUCH INTERACTION ANIMATION*****/
public void showPressed(){
mAnimationView.setMinAndMaxFrame(452,462);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: PressAnimation played");
}
public void showReleased(){
mAnimationView.setMinAndMaxFrame(485,495);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: RelleaseAnimation played");
}
/*****FEDBACK CONTROL ANIMATION*****/
public void showTick(){
mAnimationView.setOnTouchListener(null);
mAnimationView.setMinAndMaxFrame(58,181);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: TickAnimation played, Touchlistener deactivated");
}
public void showTickEnd(){
mAnimationView.setOnTouchListener(null);
mAnimationView.setMinAndMaxFrame(58,94);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: TickEndAnimation played, Touchlistener deactivated");
}
public void showCross(){
mAnimationView.setOnTouchListener(null);
mAnimationView.setMinAndMaxFrame(300,431);
mAnimationView.setSpeed(2.0f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: CrossAnimation played, Touchlistener deactivated");
}
/*****LISTENER*****/
@Override
public boolean onTouch(View v, MotionEvent event) {
if(v.getId() == mAnimationView.getId()){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
showPressed();
Log.d(LOG_TAG, "CancelCheckButton: View is touched");
break;
case MotionEvent.ACTION_UP:
showReleased();
v.performClick();
mListener.onClick();
Log.d(LOG_TAG, "CancelCheckButton: View is relleased, OnClick is fired");
break;
}
}
return true;
}
@Override
public void onAnimationStart(Animator animation) {
Log.d(LOG_TAG, "CancelCheckButton: Called Animation is STARTED and Touchlistener deactivated");
}
@Override
public void onAnimationEnd(Animator animation) {
setTouchListener();
Log.d(LOG_TAG, "CancelCheckButton: Called Animation is FINISHED and Touchlistener reset");
}
@Override
public void onAnimationCancel(Animator animation) {
Log.d(LOG_TAG, "CancelCheckButton: Called Animation is CANCELED and Touchlistener reset");
}
@Override
public void onAnimationRepeat(Animator animation) {
}
}
Notes
When you click on the button I want the blue part to appear and disappear when the finger is released. As it is a very short animation I decided to not deactivate the OnTouchListener. No matter how fast I tipped I could not see a difference.
For the green or red part I deactivated the onTouchListener to avoid an accidental restart of the animation.
It actually works perfectly but even though I tried to keep the code clean I am not happy with it. Is there a more effective or at least a more common way to do it?
java android animation
New contributor
add a comment |
I have a question about my implementation of a "special" Next-Button.
First I want to show you my AfterEffects file:
So This Animation has 3 parts
- Green: Entry correct
- Red: Entry incorrect
- Blue: Button has been pressed (visual feedback)
As I could not work this out with AVD and states I decided to use the Lottie library and play the different segments.
Main Activity - Only TestMethod, nothing really to review actually
private void initButtonTwo(){
mNext = findViewById(R.id.next);
mNextButton = new CancelCheckButton(mNext, new NextButtonListener() {
@Override
public void onClick() {
if(enableVibration){
vibrateFeedback();
}
switch (mNextCounter){
//This is just a Test-Method, i want Tick and Cross to alternate
case 1:
case 3:
mNextButton.showTick();
break;
case 2:
case 4:
mNextButton.showCross();
break;
case 5:
mNextButton.showTickEnd();
break;
}
if(mNextCounter >= 5){
mNextCounter = 1;
}else{
mNextCounter = mNextCounter + 1;
}
}
});
}
Interface for Communication Main -> Custom Button C
public interface NextButtonListener {
public void onClick();
}
Custom Class CancelCheckButton
public class CancelCheckButton implements View.OnTouchListener, Animator.AnimatorListener {
private LottieAnimationView mAnimationView;
private NextButtonListener mListener;
private final String LOG_TAG = this.getClass().getSimpleName();
public CancelCheckButton(LottieAnimationView mView, final NextButtonListener mListener){
this.mAnimationView = mView;
this.mListener = mListener;
this.setTouchListener();
this.setAnimatorListener();
Log.d(LOG_TAG, "CancelCheckButton: called");
}
private void setAnimatorListener(){
mAnimationView.addAnimatorListener(this);
Log.d(LOG_TAG, "CancelCheckButton: AnimatorListener called");
}
private void setTouchListener(){
mAnimationView.setOnTouchListener(this);
Log.d(LOG_TAG, "CancelCheckButton: TouchListener called");
}
/*****TOUCH INTERACTION ANIMATION*****/
public void showPressed(){
mAnimationView.setMinAndMaxFrame(452,462);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: PressAnimation played");
}
public void showReleased(){
mAnimationView.setMinAndMaxFrame(485,495);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: RelleaseAnimation played");
}
/*****FEDBACK CONTROL ANIMATION*****/
public void showTick(){
mAnimationView.setOnTouchListener(null);
mAnimationView.setMinAndMaxFrame(58,181);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: TickAnimation played, Touchlistener deactivated");
}
public void showTickEnd(){
mAnimationView.setOnTouchListener(null);
mAnimationView.setMinAndMaxFrame(58,94);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: TickEndAnimation played, Touchlistener deactivated");
}
public void showCross(){
mAnimationView.setOnTouchListener(null);
mAnimationView.setMinAndMaxFrame(300,431);
mAnimationView.setSpeed(2.0f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: CrossAnimation played, Touchlistener deactivated");
}
/*****LISTENER*****/
@Override
public boolean onTouch(View v, MotionEvent event) {
if(v.getId() == mAnimationView.getId()){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
showPressed();
Log.d(LOG_TAG, "CancelCheckButton: View is touched");
break;
case MotionEvent.ACTION_UP:
showReleased();
v.performClick();
mListener.onClick();
Log.d(LOG_TAG, "CancelCheckButton: View is relleased, OnClick is fired");
break;
}
}
return true;
}
@Override
public void onAnimationStart(Animator animation) {
Log.d(LOG_TAG, "CancelCheckButton: Called Animation is STARTED and Touchlistener deactivated");
}
@Override
public void onAnimationEnd(Animator animation) {
setTouchListener();
Log.d(LOG_TAG, "CancelCheckButton: Called Animation is FINISHED and Touchlistener reset");
}
@Override
public void onAnimationCancel(Animator animation) {
Log.d(LOG_TAG, "CancelCheckButton: Called Animation is CANCELED and Touchlistener reset");
}
@Override
public void onAnimationRepeat(Animator animation) {
}
}
Notes
When you click on the button I want the blue part to appear and disappear when the finger is released. As it is a very short animation I decided to not deactivate the OnTouchListener. No matter how fast I tipped I could not see a difference.
For the green or red part I deactivated the onTouchListener to avoid an accidental restart of the animation.
It actually works perfectly but even though I tried to keep the code clean I am not happy with it. Is there a more effective or at least a more common way to do it?
java android animation
New contributor
I have a question about my implementation of a "special" Next-Button.
First I want to show you my AfterEffects file:
So This Animation has 3 parts
- Green: Entry correct
- Red: Entry incorrect
- Blue: Button has been pressed (visual feedback)
As I could not work this out with AVD and states I decided to use the Lottie library and play the different segments.
Main Activity - Only TestMethod, nothing really to review actually
private void initButtonTwo(){
mNext = findViewById(R.id.next);
mNextButton = new CancelCheckButton(mNext, new NextButtonListener() {
@Override
public void onClick() {
if(enableVibration){
vibrateFeedback();
}
switch (mNextCounter){
//This is just a Test-Method, i want Tick and Cross to alternate
case 1:
case 3:
mNextButton.showTick();
break;
case 2:
case 4:
mNextButton.showCross();
break;
case 5:
mNextButton.showTickEnd();
break;
}
if(mNextCounter >= 5){
mNextCounter = 1;
}else{
mNextCounter = mNextCounter + 1;
}
}
});
}
Interface for Communication Main -> Custom Button C
public interface NextButtonListener {
public void onClick();
}
Custom Class CancelCheckButton
public class CancelCheckButton implements View.OnTouchListener, Animator.AnimatorListener {
private LottieAnimationView mAnimationView;
private NextButtonListener mListener;
private final String LOG_TAG = this.getClass().getSimpleName();
public CancelCheckButton(LottieAnimationView mView, final NextButtonListener mListener){
this.mAnimationView = mView;
this.mListener = mListener;
this.setTouchListener();
this.setAnimatorListener();
Log.d(LOG_TAG, "CancelCheckButton: called");
}
private void setAnimatorListener(){
mAnimationView.addAnimatorListener(this);
Log.d(LOG_TAG, "CancelCheckButton: AnimatorListener called");
}
private void setTouchListener(){
mAnimationView.setOnTouchListener(this);
Log.d(LOG_TAG, "CancelCheckButton: TouchListener called");
}
/*****TOUCH INTERACTION ANIMATION*****/
public void showPressed(){
mAnimationView.setMinAndMaxFrame(452,462);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: PressAnimation played");
}
public void showReleased(){
mAnimationView.setMinAndMaxFrame(485,495);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: RelleaseAnimation played");
}
/*****FEDBACK CONTROL ANIMATION*****/
public void showTick(){
mAnimationView.setOnTouchListener(null);
mAnimationView.setMinAndMaxFrame(58,181);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: TickAnimation played, Touchlistener deactivated");
}
public void showTickEnd(){
mAnimationView.setOnTouchListener(null);
mAnimationView.setMinAndMaxFrame(58,94);
mAnimationView.setSpeed(1.8f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: TickEndAnimation played, Touchlistener deactivated");
}
public void showCross(){
mAnimationView.setOnTouchListener(null);
mAnimationView.setMinAndMaxFrame(300,431);
mAnimationView.setSpeed(2.0f);
mAnimationView.playAnimation();
Log.d(LOG_TAG, "CancelCheckButton: CrossAnimation played, Touchlistener deactivated");
}
/*****LISTENER*****/
@Override
public boolean onTouch(View v, MotionEvent event) {
if(v.getId() == mAnimationView.getId()){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
showPressed();
Log.d(LOG_TAG, "CancelCheckButton: View is touched");
break;
case MotionEvent.ACTION_UP:
showReleased();
v.performClick();
mListener.onClick();
Log.d(LOG_TAG, "CancelCheckButton: View is relleased, OnClick is fired");
break;
}
}
return true;
}
@Override
public void onAnimationStart(Animator animation) {
Log.d(LOG_TAG, "CancelCheckButton: Called Animation is STARTED and Touchlistener deactivated");
}
@Override
public void onAnimationEnd(Animator animation) {
setTouchListener();
Log.d(LOG_TAG, "CancelCheckButton: Called Animation is FINISHED and Touchlistener reset");
}
@Override
public void onAnimationCancel(Animator animation) {
Log.d(LOG_TAG, "CancelCheckButton: Called Animation is CANCELED and Touchlistener reset");
}
@Override
public void onAnimationRepeat(Animator animation) {
}
}
Notes
When you click on the button I want the blue part to appear and disappear when the finger is released. As it is a very short animation I decided to not deactivate the OnTouchListener. No matter how fast I tipped I could not see a difference.
For the green or red part I deactivated the onTouchListener to avoid an accidental restart of the animation.
It actually works perfectly but even though I tried to keep the code clean I am not happy with it. Is there a more effective or at least a more common way to do it?
java android animation
java android animation
New contributor
New contributor
edited yesterday
mdfst13
17.4k52156
17.4k52156
New contributor
asked yesterday
J. Lo
62
62
New contributor
New contributor
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
J. Lo is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210949%2fanimated-button-on-android-using-aftereffects-and-lottie%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
J. Lo is a new contributor. Be nice, and check out our Code of Conduct.
J. Lo is a new contributor. Be nice, and check out our Code of Conduct.
J. Lo is a new contributor. Be nice, and check out our Code of Conduct.
J. Lo is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210949%2fanimated-button-on-android-using-aftereffects-and-lottie%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown