1d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang/*
2d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang * Copyright (C) 2016 The Android Open Source Project
3d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang *
4d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang * Licensed under the Apache License, Version 2.0 (the "License");
5d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang * you may not use this file except in compliance with the License.
6d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang * You may obtain a copy of the License at
7d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang *
8d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang *      http://www.apache.org/licenses/LICENSE-2.0
9d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang *
10d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang * Unless required by applicable law or agreed to in writing, software
11d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang * distributed under the License is distributed on an "AS IS" BASIS,
12d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang * See the License for the specific language governing permissions and
14d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang * limitations under the License.
15d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang */
16d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
17d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangpackage com.android.settings.display;
18d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
19d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.content.Context;
20d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.content.res.Resources;
21d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.content.res.TypedArray;
22d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.graphics.PorterDuff;
23d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.graphics.drawable.Drawable;
24d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.util.AttributeSet;
25d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.view.Gravity;
26d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.view.LayoutInflater;
27d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.view.View;
28d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.view.ViewGroup;
29d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.widget.FrameLayout;
30d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.widget.LinearLayout;
31d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport android.widget.TextView;
32d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
33d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangimport com.android.settings.R;
34d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
35d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang/**
36d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang * The view for a single entry in a conversation. This is a simplified version of
37d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang * com.android.messaging.ui.conversation.ConversationMessageView class.
38d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang */
39d51affa86a445be576c95785dc8a638e5eb0d128Noah Wangpublic class ConversationMessageView extends FrameLayout {
40d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private final boolean mIncoming;
41d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private final CharSequence mMessageText;
42d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private final CharSequence mTimestampText;
43d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private final CharSequence mIconText;
44d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private final int mIconTextColor;
45d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private final int mIconBackgroundColor;
46d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
47d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private LinearLayout mMessageBubble;
48d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private ViewGroup mMessageTextAndInfoView;
49d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private TextView mMessageTextView;
50d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private TextView mStatusTextView;
51d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private TextView mContactIconView;
52d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
53d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    public ConversationMessageView(Context context) {
54d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        this(context, null);
55d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    }
56d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
57d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    public ConversationMessageView(final Context context, final AttributeSet attrs) {
58d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        this(context, attrs, 0);
59d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    }
60d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
61d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    public ConversationMessageView(Context context, AttributeSet attrs, int defStyleAttr) {
62d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        this(context, attrs, defStyleAttr, 0);
63d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    }
64d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
65d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    public ConversationMessageView(Context context, AttributeSet attrs, int defStyleAttr,
66d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            int defStyleRes) {
67d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        super(context, attrs, defStyleAttr, defStyleRes);
68d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
69d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final TypedArray a = context.obtainStyledAttributes(attrs,
70d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                R.styleable.ConversationMessageView);
71d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
72d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mIncoming = a.getBoolean(R.styleable.ConversationMessageView_incoming, true);
73d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mMessageText = a.getString(R.styleable.ConversationMessageView_messageText);
74d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mTimestampText = a.getString(R.styleable.ConversationMessageView_timestampText);
75d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mIconText = a.getString(R.styleable.ConversationMessageView_iconText);
76d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mIconTextColor = a.getColor(R.styleable.ConversationMessageView_iconTextColor, 0);
77d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mIconBackgroundColor = a.getColor(R.styleable.ConversationMessageView_iconBackgroundColor,
78d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                0);
79d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
80d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        LayoutInflater.from(context).inflate(R.layout.conversation_message_icon, this);
81d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        LayoutInflater.from(context).inflate(R.layout.conversation_message_content, this);
82d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    }
83d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
84d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    @Override
85d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    protected void onFinishInflate() {
86d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mMessageBubble = (LinearLayout) findViewById(R.id.message_content);
87d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mMessageTextAndInfoView = (ViewGroup) findViewById(R.id.message_text_and_info);
88d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mMessageTextView = (TextView) findViewById(R.id.message_text);
89d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mStatusTextView = (TextView) findViewById(R.id.message_status);
90d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mContactIconView = (TextView) findViewById(R.id.conversation_icon);
91d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        updateViewContent();
92d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    }
93d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
94d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    @Override
95d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
96d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        updateViewAppearance();
97d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
98d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int horizontalSpace = MeasureSpec.getSize(widthMeasureSpec);
99d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
100d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int unspecifiedMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
10135a95617fd467b823a6c1c66f0f5d9651752f2efNoah Wang        int iconMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
102d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
103d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mContactIconView.measure(iconMeasureSpec, iconMeasureSpec);
10435a95617fd467b823a6c1c66f0f5d9651752f2efNoah Wang        iconMeasureSpec = MeasureSpec.makeMeasureSpec(
10535a95617fd467b823a6c1c66f0f5d9651752f2efNoah Wang                Math.max(mContactIconView.getMeasuredWidth(), mContactIconView.getMeasuredHeight()),
10635a95617fd467b823a6c1c66f0f5d9651752f2efNoah Wang                MeasureSpec.EXACTLY);
10735a95617fd467b823a6c1c66f0f5d9651752f2efNoah Wang        mContactIconView.measure(iconMeasureSpec, iconMeasureSpec);
108d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
109d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int arrowWidth =
110d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                getResources().getDimensionPixelSize(R.dimen.message_bubble_arrow_width);
111d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
112d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        // We need to subtract contact icon width twice from the horizontal space to get
113d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        // the max leftover space because we want the message bubble to extend no further than the
114d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        // starting position of the message bubble in the opposite direction.
115d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int maxLeftoverSpace = horizontalSpace - mContactIconView.getMeasuredWidth() * 2
116d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                - arrowWidth - getPaddingLeft() - getPaddingRight();
117d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int messageContentWidthMeasureSpec = MeasureSpec.makeMeasureSpec(maxLeftoverSpace,
118d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                MeasureSpec.AT_MOST);
119d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
120d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mMessageBubble.measure(messageContentWidthMeasureSpec, unspecifiedMeasureSpec);
121d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
122d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int maxHeight = Math.max(mContactIconView.getMeasuredHeight(),
123d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                mMessageBubble.getMeasuredHeight());
124d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        setMeasuredDimension(horizontalSpace, maxHeight + getPaddingBottom() + getPaddingTop());
125d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    }
126d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
127d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    @Override
128d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    protected void onLayout(final boolean changed, final int left, final int top, final int right,
129d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            final int bottom) {
130d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final boolean isRtl = isLayoutRtl(this);
131d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
132d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int iconWidth = mContactIconView.getMeasuredWidth();
133d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int iconHeight = mContactIconView.getMeasuredHeight();
134d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int iconTop = getPaddingTop();
135d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int contentWidth = (right -left) - iconWidth - getPaddingLeft() - getPaddingRight();
136d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int contentHeight = mMessageBubble.getMeasuredHeight();
137d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int contentTop = iconTop;
138d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
139d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int iconLeft;
140d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int contentLeft;
141d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
142d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        if (mIncoming) {
143d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            if (isRtl) {
144d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                iconLeft = (right - left) - getPaddingRight() - iconWidth;
145d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                contentLeft = iconLeft - contentWidth;
146d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            } else {
147d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                iconLeft = getPaddingLeft();
148d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                contentLeft = iconLeft + iconWidth;
149d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            }
150d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        } else {
151d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            if (isRtl) {
152d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                iconLeft = getPaddingLeft();
153d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                contentLeft = iconLeft + iconWidth;
154d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            } else {
155d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                iconLeft = (right - left) - getPaddingRight() - iconWidth;
156d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                contentLeft = iconLeft - contentWidth;
157d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            }
158d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        }
159d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
160d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mContactIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight);
161d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
162d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mMessageBubble.layout(contentLeft, contentTop, contentLeft + contentWidth,
163d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                contentTop + contentHeight);
164d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    }
165d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
166d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private static boolean isLayoutRtl(final View view) {
167d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        return View.LAYOUT_DIRECTION_RTL == view.getLayoutDirection();
168d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    }
169d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
170d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private void updateViewContent() {
171d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mMessageTextView.setText(mMessageText);
172d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mStatusTextView.setText(mTimestampText);
173d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mContactIconView.setText(mIconText);
174d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
175d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mContactIconView.setTextColor(mIconTextColor);
176d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final Drawable iconBase = getContext().getDrawable(R.drawable.conversation_message_icon);
177d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mContactIconView
178d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                .setBackground(getTintedDrawable(getContext(), iconBase, mIconBackgroundColor));
179d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    }
180d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
181d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private void updateViewAppearance() {
182d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final Resources res = getResources();
183d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
184d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int arrowWidth = res.getDimensionPixelOffset(
185d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                R.dimen.message_bubble_arrow_width);
186d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int messageTextLeftRightPadding = res.getDimensionPixelOffset(
187d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                R.dimen.message_text_left_right_padding);
188d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int textTopPadding = res.getDimensionPixelOffset(
189d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                R.dimen.message_text_top_padding);
190d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int textBottomPadding = res.getDimensionPixelOffset(
191d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                R.dimen.message_text_bottom_padding);
192d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
193d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int textLeftPadding, textRightPadding;
194d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
195d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        if (mIncoming) {
196d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            textLeftPadding = messageTextLeftRightPadding + arrowWidth;
197d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            textRightPadding = messageTextLeftRightPadding;
198d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        } else {
199d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            textLeftPadding = messageTextLeftRightPadding;
200d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            textRightPadding = messageTextLeftRightPadding + arrowWidth;
201d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        }
202d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
203d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        // These values do not depend on whether the message includes attachments
204d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int gravity = mIncoming ? (Gravity.START | Gravity.CENTER_VERTICAL) :
205d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                (Gravity.END | Gravity.CENTER_VERTICAL);
206d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int messageTopPadding = res.getDimensionPixelSize(
207d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                R.dimen.message_padding_default);
208d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int metadataTopPadding =  res.getDimensionPixelOffset(
209d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                R.dimen.message_metadata_top_padding);
210d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
211d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        // Update the message text/info views
212d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int bubbleDrawableResId = mIncoming ? R.drawable.msg_bubble_incoming
213d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                : R.drawable.msg_bubble_outgoing;
214d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int bubbleColorResId = mIncoming ? R.color.message_bubble_incoming
215d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                : R.color.message_bubble_outgoing;
216d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final Context context = getContext();
217d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
218d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final Drawable textBackgroundDrawable = getTintedDrawable(context,
219d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                context.getDrawable(bubbleDrawableResId),
220d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                context.getColor(bubbleColorResId));
221d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mMessageTextAndInfoView.setBackground(textBackgroundDrawable);
222d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
223d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        if (isLayoutRtl(this)) {
224d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            // Need to switch right and left padding in RtL mode
225d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            mMessageTextAndInfoView.setPadding(textRightPadding,
226d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                    textTopPadding + metadataTopPadding,
227d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                    textLeftPadding, textBottomPadding);
228d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        } else {
229d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            mMessageTextAndInfoView.setPadding(textLeftPadding,
230d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                    textTopPadding + metadataTopPadding,
231d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                    textRightPadding, textBottomPadding);
232d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        }
233d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
234d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        // Update the message row and message bubble views
235d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        setPadding(getPaddingLeft(), messageTopPadding, getPaddingRight(), 0);
236d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mMessageBubble.setGravity(gravity);
237d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
238d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        updateTextAppearance();
239d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    }
240d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
241d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private void updateTextAppearance() {
242d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int messageColorResId = (mIncoming ? R.color.message_text_incoming
243d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                : R.color.message_text_outgoing);
244d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int timestampColorResId = mIncoming ? R.color.timestamp_text_incoming
245d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                : R.color.timestamp_text_outgoing;
246d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final int messageColor = getContext().getColor(messageColorResId);
247d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
248d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mMessageTextView.setTextColor(messageColor);
249d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mMessageTextView.setLinkTextColor(messageColor);
250d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        mStatusTextView.setTextColor(timestampColorResId);
251d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    }
252d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang
253d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    private static Drawable getTintedDrawable(final Context context, final Drawable drawable,
254d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang            final int color) {
255d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        // For some reason occassionally drawables on JB has a null constant state
256d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final Drawable.ConstantState constantStateDrawable = drawable.getConstantState();
257d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        final Drawable retDrawable = (constantStateDrawable != null)
258d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                ? constantStateDrawable.newDrawable(context.getResources()).mutate()
259d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang                : drawable;
260d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        retDrawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
261d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang        return retDrawable;
262d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang    }
263d51affa86a445be576c95785dc8a638e5eb0d128Noah Wang}
264