133 lines
5.1 KiB
Java
133 lines
5.1 KiB
Java
/*
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
*
|
|
* 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 com.android.messaging.ui.conversation;
|
|
|
|
import android.animation.Animator;
|
|
import android.animation.Animator.AnimatorListener;
|
|
import android.animation.ObjectAnimator;
|
|
import android.content.Context;
|
|
import android.util.AttributeSet;
|
|
import android.view.ViewGroup;
|
|
import android.widget.LinearLayout;
|
|
|
|
import com.android.messaging.R;
|
|
import com.android.messaging.annotation.VisibleForAnimation;
|
|
import com.android.messaging.datamodel.data.ConversationMessageBubbleData;
|
|
import com.android.messaging.datamodel.data.ConversationMessageData;
|
|
import com.android.messaging.util.UiUtils;
|
|
|
|
/**
|
|
* Shows the message bubble for one conversation message. It is able to animate size changes
|
|
* by morphing when the message content changes size.
|
|
*/
|
|
// TODO: Move functionality from ConversationMessageView into this class as appropriate
|
|
public class ConversationMessageBubbleView extends LinearLayout {
|
|
private int mIntrinsicWidth;
|
|
private int mMorphedWidth;
|
|
private ObjectAnimator mAnimator;
|
|
private boolean mShouldAnimateWidthChange;
|
|
private final ConversationMessageBubbleData mData;
|
|
private int mRunningStartWidth;
|
|
private ViewGroup mBubbleBackground;
|
|
|
|
public ConversationMessageBubbleView(final Context context, final AttributeSet attrs) {
|
|
super(context, attrs);
|
|
mData = new ConversationMessageBubbleData();
|
|
}
|
|
|
|
@Override
|
|
protected void onFinishInflate() {
|
|
super.onFinishInflate();
|
|
mBubbleBackground = (ViewGroup) findViewById(R.id.message_text_and_info);
|
|
}
|
|
|
|
@Override
|
|
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
|
|
final int newIntrinsicWidth = getMeasuredWidth();
|
|
if (mIntrinsicWidth == 0 && newIntrinsicWidth != mIntrinsicWidth) {
|
|
if (mShouldAnimateWidthChange) {
|
|
kickOffMorphAnimation(mIntrinsicWidth, newIntrinsicWidth);
|
|
}
|
|
mIntrinsicWidth = newIntrinsicWidth;
|
|
}
|
|
|
|
if (mMorphedWidth > 0) {
|
|
mBubbleBackground.getLayoutParams().width = mMorphedWidth;
|
|
} else {
|
|
mBubbleBackground.getLayoutParams().width = LayoutParams.WRAP_CONTENT;
|
|
}
|
|
mBubbleBackground.requestLayout();
|
|
}
|
|
|
|
@VisibleForAnimation
|
|
public void setMorphWidth(final int width) {
|
|
mMorphedWidth = width;
|
|
requestLayout();
|
|
}
|
|
|
|
public void bind(final ConversationMessageData data) {
|
|
final boolean changed = mData.bind(data);
|
|
// Animate width change only when we are binding to the same message, so that we may
|
|
// animate view size changes on the same message bubble due to things like status text
|
|
// change.
|
|
// Don't animate width change when the bubble contains attachments. Width animation is
|
|
// only suitable for text-only messages (where the bubble size change due to status or
|
|
// time stamp changes).
|
|
mShouldAnimateWidthChange = !changed && !data.hasAttachments();
|
|
if (mAnimator == null) {
|
|
mMorphedWidth = 0;
|
|
}
|
|
}
|
|
|
|
public void kickOffMorphAnimation(final int oldWidth, final int newWidth) {
|
|
if (mAnimator != null) {
|
|
mAnimator.setIntValues(mRunningStartWidth, newWidth);
|
|
return;
|
|
}
|
|
mRunningStartWidth = oldWidth;
|
|
mAnimator = ObjectAnimator.ofInt(this, "morphWidth", oldWidth, newWidth);
|
|
mAnimator.setDuration(UiUtils.MEDIAPICKER_TRANSITION_DURATION);
|
|
mAnimator.addListener(new AnimatorListener() {
|
|
@Override
|
|
public void onAnimationStart(Animator animator) {
|
|
}
|
|
|
|
@Override
|
|
public void onAnimationEnd(Animator animator) {
|
|
mAnimator = null;
|
|
mMorphedWidth = 0;
|
|
// Allow the bubble to resize if, for example, the status text changed during
|
|
// the animation. This will snap to the bigger size if needed. This is intentional
|
|
// as animating immediately after looks really bad and switching layout params
|
|
// during the original animation does not achieve the desired effect.
|
|
mBubbleBackground.getLayoutParams().width = LayoutParams.WRAP_CONTENT;
|
|
mBubbleBackground.requestLayout();
|
|
}
|
|
|
|
@Override
|
|
public void onAnimationCancel(Animator animator) {
|
|
}
|
|
|
|
@Override
|
|
public void onAnimationRepeat(Animator animator) {
|
|
}
|
|
});
|
|
mAnimator.start();
|
|
}
|
|
}
|