Skip to content

Instantly share code, notes, and snippets.

@frogermcs
Last active August 29, 2015 14:10
Show Gist options
  • Save frogermcs/827dfb8077af625bf2d4 to your computer and use it in GitHub Desktop.
Save frogermcs/827dfb8077af625bf2d4 to your computer and use it in GitHub Desktop.
InstaMaterial source files (comments transitions)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CommentsActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="@dimen/default_elevation">
<ImageView
android:id="@+id/ivLogo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="center"
android:src="@drawable/img_toolbar_logo" />
</android.support.v7.widget.Toolbar>
<LinearLayout
android:id="@+id/contentRoot"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"
android:background="@color/bg_comments"
android:elevation="@dimen/default_elevation"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/rvComments"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="none" />
<LinearLayout
android:id="@+id/llAddComment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/bg_comments"
android:elevation="@dimen/default_elevation">
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<Button
android:id="@+id/btnSendComment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<!--drawable/bg_comment_avar.xml-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#999999" />
</shape>
public class CommentsActivity extends ActionBarActivity {
public static final String ARG_DRAWING_START_LOCATION = "arg_drawing_start_location";
@InjectView(R.id.toolbar)
Toolbar toolbar;
@InjectView(R.id.contentRoot)
LinearLayout contentRoot;
@InjectView(R.id.rvComments)
RecyclerView rvComments;
@InjectView(R.id.llAddComment)
LinearLayout llAddComment;
private CommentsAdapter commentsAdapter;
private int drawingStartLocation;
@Override
protected void onCreate(Bundle savedInstanceState) {
//...
drawingStartLocation = getIntent().getIntExtra(ARG_DRAWING_START_LOCATION, 0);
if (savedInstanceState == null) {
contentRoot.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
contentRoot.getViewTreeObserver().removeOnPreDrawListener(this);
startIntroAnimation();
return true;
}
});
}
}
//...
private void startIntroAnimation() {
contentRoot.setScaleY(0.1f);
contentRoot.setPivotY(drawingStartLocation);
llAddComment.setTranslationY(100);
contentRoot.animate()
.scaleY(1)
.setDuration(200)
.setInterpolator(new AccelerateInterpolator())
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
animateContent();
}
})
.start();
}
private void animateContent() {
commentsAdapter.updateItems();
llAddComment.animate().translationY(0)
.setInterpolator(new DecelerateInterpolator())
.setDuration(200)
.start();
}
//...
}
public class CommentsActivity extends ActionBarActivity {
//...
@Override
public void onBackPressed() {
contentRoot.animate()
.translationY(Utils.getScreenHeight(this))
.setDuration(200)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
CommentsActivity.super.onBackPressed();
overridePendingTransition(0, 0);
}
})
.start();
}
}
public class CommentsActivity extends ActionBarActivity {
//...
private void setupComments() {
//...
rvComments.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
commentsAdapter.setAnimationsLocked(true);
}
}
});
}
@OnClick(R.id.btnSendComment)
public void onSendCommentClick() {
commentsAdapter.addItem();
commentsAdapter.setAnimationsLocked(false);
commentsAdapter.setDelayEnterAnimation(false);
rvComments.smoothScrollBy(0, rvComments.getChildAt(0).getHeight() * commentsAdapter.getItemCount());
}
}
public class CommentsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private int itemsCount = 0;
private int lastAnimatedPosition = -1;
private int avatarSize;
private boolean animationsLocked = false;
private boolean delayEnterAnimation = true;
public CommentsAdapter(Context context) {
this.context = context;
avatarSize = context.getResources().getDimensionPixelSize(R.dimen.btn_fab_size);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(context).inflate(R.layout.item_comment, parent, false);
return new CommentViewHolder(view);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
runEnterAnimation(viewHolder.itemView, position);
CommentViewHolder holder = (CommentViewHolder) viewHolder;
switch (position % 3) {
case 0:
holder.tvComment.setText("Lorem ipsum dolor sit amet, consectetur adipisicing elit.");
break;
case 1:
holder.tvComment.setText("Cupcake ipsum dolor sit amet bear claw.");
break;
case 2:
holder.tvComment.setText("Cupcake ipsum dolor sit. Amet gingerbread cupcake. Gummies ice cream dessert icing marzipan apple pie dessert sugar plum.");
break;
}
Picasso.with(context)
.load(R.drawable.ic_launcher)
.centerCrop()
.resize(avatarSize, avatarSize)
.transform(new RoundedTransformation())
.into(holder.ivUserAvatar);
}
private void runEnterAnimation(View view, int position) {
if (animationsLocked) return;
if (position > lastAnimatedPosition) {
lastAnimatedPosition = position;
view.setTranslationY(100);
view.setAlpha(0.f);
view.animate()
.translationY(0).alpha(1.f)
.setStartDelay(delayEnterAnimation ? 20 * (position) : 0)
.setInterpolator(new DecelerateInterpolator(2.f))
.setDuration(300)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
animationsLocked = true;
}
})
.start();
}
}
@Override
public int getItemCount() {
return itemsCount;
}
public void updateItems() {
itemsCount = 10;
notifyDataSetChanged();
}
public void addItem() {
itemsCount++;
notifyItemInserted(itemsCount - 1);
}
public void setAnimationsLocked(boolean animationsLocked) {
this.animationsLocked = animationsLocked;
}
public void setDelayEnterAnimation(boolean delayEnterAnimation) {
this.delayEnterAnimation = delayEnterAnimation;
}
public static class CommentViewHolder extends RecyclerView.ViewHolder {
@InjectView(R.id.ivUserAvatar)
ImageView ivUserAvatar;
@InjectView(R.id.tvComment)
TextView tvComment;
public CommentViewHolder(View view) {
super(view);
ButterKnife.inject(this, view);
}
}
}
//.. implements View.OnClickListener
public class FeedAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements View.OnClickListener {
private OnFeedItemClickListener onFeedItemClickListener;
//..
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
//...
holder.ivFeedBottom.setOnClickListener(this);
holder.ivFeedBottom.setTag(position);
}
//..
@Override
public void onClick(View v) {
if (v.getId() == R.id.ivFeedBottom) {
if (onFeedItemClickListener != null) {
onFeedItemClickListener.onCommentsClick(v, (Integer) v.getTag());
}
}
}
public void setOnFeedItemClickListener(OnFeedItemClickListener onFeedItemClickListener) {
this.onFeedItemClickListener = onFeedItemClickListener;
}
//..
public interface OnFeedItemClickListener {
public void onCommentsClick(View v, int position);
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="8dp"
android:paddingTop="8dp">
<ImageView
android:id="@+id/ivUserAvatar"
android:layout_width="@dimen/comment_avatar_size"
android:layout_height="@dimen/comment_avatar_size"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:background="@drawable/bg_comment_avatar" />
<TextView
android:id="@+id/tvComment"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:text="Lorem ipsum dolor sit amet" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="bottom"
android:layout_marginLeft="88dp"
android:background="#cccccc" />
</FrameLayout>
public class MainActivity extends ActionBarActivity implements FeedAdapter.OnFeedItemClickListener {
//...
@Override
public void onCommentsClick(View v, int position) {
final Intent intent = new Intent(this, CommentsActivity.class);
//Get location on screen for tapped view
int[] startingLocation = new int[2];
v.getLocationOnScreen(startingLocation);
intent.putExtra(CommentsActivity.ARG_DRAWING_START_LOCATION, startingLocation[1]);
startActivity(intent);
overridePendingTransition(0, 0);
}
}
//... implements FeedAdapter.OnFeedItemClickListener
public class MainActivity extends ActionBarActivity implements FeedAdapter.OnFeedItemClickListener {
//...
private void setupFeed() {
//...
feedAdapter.setOnFeedItemClickListener(this);
//...
}
//...
@Override
public void onCommentsClick(View v, int position) {
}
}
public class MainActivity extends ActionBarActivity implements FeedAdapter.OnFeedItemClickListener {
//...
@Override
public void onCommentsClick(View v, int position) {
final Intent intent = new Intent(this, CommentsActivity.class);
startActivity(intent);
//Disable enter transition for new Acitvity
overridePendingTransition(0, 0);
}
}
<?xml version="1.0" encoding="utf-8"?>
<!-- styles.xml-->
<resources>
<!--...-->
<style name="AppTheme.CommentsActivity" parent="AppTheme">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
</style>
</resources>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment