1079d02b6021c640213888d446434e2c925756e29Jin Cao/*
2079d02b6021c640213888d446434e2c925756e29Jin Cao * Copyright (C) 2014 The Android Open Source Project
3079d02b6021c640213888d446434e2c925756e29Jin Cao *
4079d02b6021c640213888d446434e2c925756e29Jin Cao * Licensed under the Apache License, Version 2.0 (the "License");
5079d02b6021c640213888d446434e2c925756e29Jin Cao * you may not use this file except in compliance with the License.
6079d02b6021c640213888d446434e2c925756e29Jin Cao * You may obtain a copy of the License at
7079d02b6021c640213888d446434e2c925756e29Jin Cao *
8079d02b6021c640213888d446434e2c925756e29Jin Cao *      http://www.apache.org/licenses/LICENSE-2.0
9079d02b6021c640213888d446434e2c925756e29Jin Cao *
10079d02b6021c640213888d446434e2c925756e29Jin Cao * Unless required by applicable law or agreed to in writing, software
11079d02b6021c640213888d446434e2c925756e29Jin Cao * distributed under the License is distributed on an "AS IS" BASIS,
12079d02b6021c640213888d446434e2c925756e29Jin Cao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13079d02b6021c640213888d446434e2c925756e29Jin Cao * See the License for the specific language governing permissions and
14079d02b6021c640213888d446434e2c925756e29Jin Cao * limitations under the License.
15079d02b6021c640213888d446434e2c925756e29Jin Cao */
16079d02b6021c640213888d446434e2c925756e29Jin Cao
17079d02b6021c640213888d446434e2c925756e29Jin Caopackage com.android.mail.ui;
18079d02b6021c640213888d446434e2c925756e29Jin Cao
19079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.animation.ObjectAnimator;
20079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.app.LoaderManager;
21079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.content.Context;
22079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.content.res.Resources;
23079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.os.Bundle;
24079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.support.annotation.LayoutRes;
25079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.util.AttributeSet;
26079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.view.LayoutInflater;
27079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.view.View;
28079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.view.ViewGroup;
29079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.view.animation.DecelerateInterpolator;
305f9b22e817528d08813a2dfe031649e79f28fb2eRohan Shahimport android.widget.AbsListView;
31079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.widget.ImageView;
32079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.widget.LinearLayout;
33079d02b6021c640213888d446434e2c925756e29Jin Caoimport android.widget.TextView;
34079d02b6021c640213888d446434e2c925756e29Jin Cao
35079d02b6021c640213888d446434e2c925756e29Jin Caoimport com.android.mail.R;
36079d02b6021c640213888d446434e2c925756e29Jin Caoimport com.android.mail.browse.ConversationCursor;
37079d02b6021c640213888d446434e2c925756e29Jin Caoimport com.android.mail.providers.Folder;
38079d02b6021c640213888d446434e2c925756e29Jin Caoimport com.android.mail.utils.LogTag;
39079d02b6021c640213888d446434e2c925756e29Jin Cao
40079d02b6021c640213888d446434e2c925756e29Jin Cao/**
41079d02b6021c640213888d446434e2c925756e29Jin Cao * Base class to display tip teasers in the thread list.
42079d02b6021c640213888d446434e2c925756e29Jin Cao * Supports two-line text and start/end icons.
43079d02b6021c640213888d446434e2c925756e29Jin Cao */
44079d02b6021c640213888d446434e2c925756e29Jin Caopublic abstract class ConversationTipView extends LinearLayout
45079d02b6021c640213888d446434e2c925756e29Jin Cao        implements ConversationSpecialItemView, SwipeableItemView, View.OnClickListener {
46079d02b6021c640213888d446434e2c925756e29Jin Cao    protected static final String LOG_TAG = LogTag.getLogTag();
47079d02b6021c640213888d446434e2c925756e29Jin Cao
48079d02b6021c640213888d446434e2c925756e29Jin Cao    protected Context mContext;
49079d02b6021c640213888d446434e2c925756e29Jin Cao    protected AnimatedAdapter mAdapter;
50079d02b6021c640213888d446434e2c925756e29Jin Cao
51079d02b6021c640213888d446434e2c925756e29Jin Cao    private int mScrollSlop;
52079d02b6021c640213888d446434e2c925756e29Jin Cao    private int mShrinkAnimationDuration;
53079d02b6021c640213888d446434e2c925756e29Jin Cao    private int mAnimatedHeight = -1;
54079d02b6021c640213888d446434e2c925756e29Jin Cao
55079d02b6021c640213888d446434e2c925756e29Jin Cao    protected View mSwipeableContent;
56079d02b6021c640213888d446434e2c925756e29Jin Cao    private View mContent;
57079d02b6021c640213888d446434e2c925756e29Jin Cao    private TextView mText;
58079d02b6021c640213888d446434e2c925756e29Jin Cao
59079d02b6021c640213888d446434e2c925756e29Jin Cao    public ConversationTipView(Context context) {
60079d02b6021c640213888d446434e2c925756e29Jin Cao        this(context, null);
61079d02b6021c640213888d446434e2c925756e29Jin Cao    }
62079d02b6021c640213888d446434e2c925756e29Jin Cao
63079d02b6021c640213888d446434e2c925756e29Jin Cao    public ConversationTipView(Context context, AttributeSet attrs) {
64079d02b6021c640213888d446434e2c925756e29Jin Cao        super(context, attrs);
65079d02b6021c640213888d446434e2c925756e29Jin Cao        mContext = context;
66079d02b6021c640213888d446434e2c925756e29Jin Cao
67079d02b6021c640213888d446434e2c925756e29Jin Cao        final Resources resources = context.getResources();
68079d02b6021c640213888d446434e2c925756e29Jin Cao        mScrollSlop = resources.getInteger(R.integer.swipeScrollSlop);
69079d02b6021c640213888d446434e2c925756e29Jin Cao        mShrinkAnimationDuration = resources.getInteger(
70079d02b6021c640213888d446434e2c925756e29Jin Cao                R.integer.shrink_animation_duration);
71079d02b6021c640213888d446434e2c925756e29Jin Cao
72079d02b6021c640213888d446434e2c925756e29Jin Cao        // Inflate the actual content and add it to this view
73079d02b6021c640213888d446434e2c925756e29Jin Cao        mContent = LayoutInflater.from(mContext).inflate(getChildLayout(), this, false);
74079d02b6021c640213888d446434e2c925756e29Jin Cao        addView(mContent);
75079d02b6021c640213888d446434e2c925756e29Jin Cao        setupViews();
76079d02b6021c640213888d446434e2c925756e29Jin Cao    }
77079d02b6021c640213888d446434e2c925756e29Jin Cao
78b62192b13a871f71cd9eafeac295e6ecb1d5953dJin Cao    @Override
79b62192b13a871f71cd9eafeac295e6ecb1d5953dJin Cao    public ViewGroup.LayoutParams getLayoutParams() {
80b62192b13a871f71cd9eafeac295e6ecb1d5953dJin Cao        ViewGroup.LayoutParams params = super.getLayoutParams();
81b62192b13a871f71cd9eafeac295e6ecb1d5953dJin Cao        if (params != null) {
82b62192b13a871f71cd9eafeac295e6ecb1d5953dJin Cao            params.width = ViewGroup.LayoutParams.MATCH_PARENT;
83b62192b13a871f71cd9eafeac295e6ecb1d5953dJin Cao            params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
84b62192b13a871f71cd9eafeac295e6ecb1d5953dJin Cao        }
85b62192b13a871f71cd9eafeac295e6ecb1d5953dJin Cao        return params;
86b62192b13a871f71cd9eafeac295e6ecb1d5953dJin Cao    }
87b62192b13a871f71cd9eafeac295e6ecb1d5953dJin Cao
88079d02b6021c640213888d446434e2c925756e29Jin Cao    protected @LayoutRes int getChildLayout() {
89079d02b6021c640213888d446434e2c925756e29Jin Cao        // Should override setupViews as well if this is overridden.
90079d02b6021c640213888d446434e2c925756e29Jin Cao        return R.layout.conversation_tip_view;
91079d02b6021c640213888d446434e2c925756e29Jin Cao    }
92079d02b6021c640213888d446434e2c925756e29Jin Cao
93079d02b6021c640213888d446434e2c925756e29Jin Cao    protected void setupViews() {
94079d02b6021c640213888d446434e2c925756e29Jin Cao        // If this is overridden, child classes cannot rely on setText/getStartIconAttr/etc.
95079d02b6021c640213888d446434e2c925756e29Jin Cao        mSwipeableContent = mContent.findViewById(R.id.conversation_tip_swipeable_content);
96079d02b6021c640213888d446434e2c925756e29Jin Cao        mText = (TextView) mContent.findViewById(R.id.conversation_tip_text);
97079d02b6021c640213888d446434e2c925756e29Jin Cao        final ImageView startImage = (ImageView) mContent.findViewById(R.id.conversation_tip_icon1);
98079d02b6021c640213888d446434e2c925756e29Jin Cao        final ImageView dismiss = (ImageView) mContent.findViewById(R.id.dismiss_icon);
99079d02b6021c640213888d446434e2c925756e29Jin Cao
100079d02b6021c640213888d446434e2c925756e29Jin Cao        // Bind content (text content must be bound by calling setText(..))
101079d02b6021c640213888d446434e2c925756e29Jin Cao        bindIcon(startImage, getStartIconAttr());
102079d02b6021c640213888d446434e2c925756e29Jin Cao
103079d02b6021c640213888d446434e2c925756e29Jin Cao        // Bind listeners
104079d02b6021c640213888d446434e2c925756e29Jin Cao        dismiss.setOnClickListener(this);
105079d02b6021c640213888d446434e2c925756e29Jin Cao        mText.setOnClickListener(getTextAreaOnClickListener());
106079d02b6021c640213888d446434e2c925756e29Jin Cao    }
107079d02b6021c640213888d446434e2c925756e29Jin Cao
108079d02b6021c640213888d446434e2c925756e29Jin Cao    /**
109079d02b6021c640213888d446434e2c925756e29Jin Cao     * Helper function to bind the additional attributes to the icon, or make the icon GONE.
110079d02b6021c640213888d446434e2c925756e29Jin Cao     */
111079d02b6021c640213888d446434e2c925756e29Jin Cao    private void bindIcon(ImageView image, ImageAttrSet attr) {
112079d02b6021c640213888d446434e2c925756e29Jin Cao        if (attr != null) {
113079d02b6021c640213888d446434e2c925756e29Jin Cao            image.setVisibility(VISIBLE);
114079d02b6021c640213888d446434e2c925756e29Jin Cao            image.setContentDescription(attr.contentDescription);
115079d02b6021c640213888d446434e2c925756e29Jin Cao            // Must override resId for the actual icon, so no need to check -1 here.
116079d02b6021c640213888d446434e2c925756e29Jin Cao            image.setImageResource(attr.resId);
117079d02b6021c640213888d446434e2c925756e29Jin Cao            if (attr.background != -1) {
118079d02b6021c640213888d446434e2c925756e29Jin Cao                image.setBackgroundResource(attr.background);
119079d02b6021c640213888d446434e2c925756e29Jin Cao            }
120079d02b6021c640213888d446434e2c925756e29Jin Cao        } else {
121079d02b6021c640213888d446434e2c925756e29Jin Cao            image.setVisibility(GONE);
122079d02b6021c640213888d446434e2c925756e29Jin Cao        }
123079d02b6021c640213888d446434e2c925756e29Jin Cao    }
124079d02b6021c640213888d446434e2c925756e29Jin Cao
125079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
126079d02b6021c640213888d446434e2c925756e29Jin Cao    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
127079d02b6021c640213888d446434e2c925756e29Jin Cao        if (mAnimatedHeight == -1) {
128079d02b6021c640213888d446434e2c925756e29Jin Cao            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
129079d02b6021c640213888d446434e2c925756e29Jin Cao        } else {
130079d02b6021c640213888d446434e2c925756e29Jin Cao            setMeasuredDimension(View.MeasureSpec.getSize(widthMeasureSpec), mAnimatedHeight);
131079d02b6021c640213888d446434e2c925756e29Jin Cao        }
132079d02b6021c640213888d446434e2c925756e29Jin Cao    }
133079d02b6021c640213888d446434e2c925756e29Jin Cao
134079d02b6021c640213888d446434e2c925756e29Jin Cao    protected ImageAttrSet getStartIconAttr() {
135079d02b6021c640213888d446434e2c925756e29Jin Cao        return null;
136079d02b6021c640213888d446434e2c925756e29Jin Cao    }
137079d02b6021c640213888d446434e2c925756e29Jin Cao
138079d02b6021c640213888d446434e2c925756e29Jin Cao    protected void setText(CharSequence text) {
139079d02b6021c640213888d446434e2c925756e29Jin Cao        mText.setText(text);
140079d02b6021c640213888d446434e2c925756e29Jin Cao    }
141079d02b6021c640213888d446434e2c925756e29Jin Cao
142079d02b6021c640213888d446434e2c925756e29Jin Cao    protected OnClickListener getTextAreaOnClickListener() {
143079d02b6021c640213888d446434e2c925756e29Jin Cao        return null;
144079d02b6021c640213888d446434e2c925756e29Jin Cao    }
145079d02b6021c640213888d446434e2c925756e29Jin Cao
146079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
147079d02b6021c640213888d446434e2c925756e29Jin Cao    public void onClick(View view) {
148079d02b6021c640213888d446434e2c925756e29Jin Cao        // Default on click for the default dismiss button
149079d02b6021c640213888d446434e2c925756e29Jin Cao        dismiss();
150079d02b6021c640213888d446434e2c925756e29Jin Cao    }
151079d02b6021c640213888d446434e2c925756e29Jin Cao
152079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
153079d02b6021c640213888d446434e2c925756e29Jin Cao    public void onUpdate(Folder folder, ConversationCursor cursor) {
154079d02b6021c640213888d446434e2c925756e29Jin Cao        // Do nothing by default
155079d02b6021c640213888d446434e2c925756e29Jin Cao    }
156079d02b6021c640213888d446434e2c925756e29Jin Cao
157079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
158079d02b6021c640213888d446434e2c925756e29Jin Cao    public void onGetView() {
159079d02b6021c640213888d446434e2c925756e29Jin Cao        // Do nothing by default
160079d02b6021c640213888d446434e2c925756e29Jin Cao    }
161079d02b6021c640213888d446434e2c925756e29Jin Cao
162079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
163079d02b6021c640213888d446434e2c925756e29Jin Cao    public int getPosition() {
164079d02b6021c640213888d446434e2c925756e29Jin Cao        // By default the tip teasers go on top of the list.
165079d02b6021c640213888d446434e2c925756e29Jin Cao        return 0;
166079d02b6021c640213888d446434e2c925756e29Jin Cao    }
167079d02b6021c640213888d446434e2c925756e29Jin Cao
168079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
169079d02b6021c640213888d446434e2c925756e29Jin Cao    public void setAdapter(AnimatedAdapter adapter) {
170079d02b6021c640213888d446434e2c925756e29Jin Cao        mAdapter = adapter;
171079d02b6021c640213888d446434e2c925756e29Jin Cao    }
172079d02b6021c640213888d446434e2c925756e29Jin Cao
173079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
174079d02b6021c640213888d446434e2c925756e29Jin Cao    public void bindFragment(LoaderManager loaderManager, Bundle savedInstanceState) {
175079d02b6021c640213888d446434e2c925756e29Jin Cao        // Do nothing by default
176079d02b6021c640213888d446434e2c925756e29Jin Cao    }
177079d02b6021c640213888d446434e2c925756e29Jin Cao
178079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
179079d02b6021c640213888d446434e2c925756e29Jin Cao    public void cleanup() {
180079d02b6021c640213888d446434e2c925756e29Jin Cao        // Do nothing by default
181079d02b6021c640213888d446434e2c925756e29Jin Cao    }
182079d02b6021c640213888d446434e2c925756e29Jin Cao
183079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
184079d02b6021c640213888d446434e2c925756e29Jin Cao    public void onConversationSelected() {
185079d02b6021c640213888d446434e2c925756e29Jin Cao        // Do nothing by default
186079d02b6021c640213888d446434e2c925756e29Jin Cao    }
187079d02b6021c640213888d446434e2c925756e29Jin Cao
188079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
189079d02b6021c640213888d446434e2c925756e29Jin Cao    public void onCabModeEntered() {
190079d02b6021c640213888d446434e2c925756e29Jin Cao        // Do nothing by default
191079d02b6021c640213888d446434e2c925756e29Jin Cao    }
192079d02b6021c640213888d446434e2c925756e29Jin Cao
193079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
194079d02b6021c640213888d446434e2c925756e29Jin Cao    public void onCabModeExited() {
195079d02b6021c640213888d446434e2c925756e29Jin Cao        // Do nothing by default
196079d02b6021c640213888d446434e2c925756e29Jin Cao    }
197079d02b6021c640213888d446434e2c925756e29Jin Cao
198079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
199079d02b6021c640213888d446434e2c925756e29Jin Cao    public boolean acceptsUserTaps() {
200079d02b6021c640213888d446434e2c925756e29Jin Cao        return true;
201079d02b6021c640213888d446434e2c925756e29Jin Cao    }
202079d02b6021c640213888d446434e2c925756e29Jin Cao
203079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
204079d02b6021c640213888d446434e2c925756e29Jin Cao    public void onConversationListVisibilityChanged(boolean visible) {
205079d02b6021c640213888d446434e2c925756e29Jin Cao        // Do nothing by default
206079d02b6021c640213888d446434e2c925756e29Jin Cao    }
207079d02b6021c640213888d446434e2c925756e29Jin Cao
208079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
209079d02b6021c640213888d446434e2c925756e29Jin Cao    public void saveInstanceState(Bundle outState) {
210079d02b6021c640213888d446434e2c925756e29Jin Cao        // Do nothing by default
211079d02b6021c640213888d446434e2c925756e29Jin Cao    }
212079d02b6021c640213888d446434e2c925756e29Jin Cao
213079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
214079d02b6021c640213888d446434e2c925756e29Jin Cao    public boolean commitLeaveBehindItem() {
215079d02b6021c640213888d446434e2c925756e29Jin Cao        // Tip has no leave-behind by default
216079d02b6021c640213888d446434e2c925756e29Jin Cao        return false;
217079d02b6021c640213888d446434e2c925756e29Jin Cao    }
218079d02b6021c640213888d446434e2c925756e29Jin Cao
219079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
220079d02b6021c640213888d446434e2c925756e29Jin Cao    public SwipeableView getSwipeableView() {
221079d02b6021c640213888d446434e2c925756e29Jin Cao        return SwipeableView.from(mSwipeableContent);
222079d02b6021c640213888d446434e2c925756e29Jin Cao    }
223079d02b6021c640213888d446434e2c925756e29Jin Cao
224079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
225079d02b6021c640213888d446434e2c925756e29Jin Cao    public boolean canChildBeDismissed() {
226079d02b6021c640213888d446434e2c925756e29Jin Cao        return true;
227079d02b6021c640213888d446434e2c925756e29Jin Cao    }
228079d02b6021c640213888d446434e2c925756e29Jin Cao
229079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
230079d02b6021c640213888d446434e2c925756e29Jin Cao    public void dismiss() {
231079d02b6021c640213888d446434e2c925756e29Jin Cao        startDestroyAnimation();
232079d02b6021c640213888d446434e2c925756e29Jin Cao    }
233079d02b6021c640213888d446434e2c925756e29Jin Cao
234079d02b6021c640213888d446434e2c925756e29Jin Cao    @Override
235079d02b6021c640213888d446434e2c925756e29Jin Cao    public float getMinAllowScrollDistance() {
236079d02b6021c640213888d446434e2c925756e29Jin Cao        return mScrollSlop;
237079d02b6021c640213888d446434e2c925756e29Jin Cao    }
238079d02b6021c640213888d446434e2c925756e29Jin Cao
239079d02b6021c640213888d446434e2c925756e29Jin Cao    private void startDestroyAnimation() {
240079d02b6021c640213888d446434e2c925756e29Jin Cao        final int start = getHeight();
241079d02b6021c640213888d446434e2c925756e29Jin Cao        final int end = 0;
242079d02b6021c640213888d446434e2c925756e29Jin Cao        mAnimatedHeight = start;
243079d02b6021c640213888d446434e2c925756e29Jin Cao        final ObjectAnimator heightAnimator =
244079d02b6021c640213888d446434e2c925756e29Jin Cao                ObjectAnimator.ofInt(this, "animatedHeight", start, end);
245079d02b6021c640213888d446434e2c925756e29Jin Cao        heightAnimator.setInterpolator(new DecelerateInterpolator(2.0f));
246079d02b6021c640213888d446434e2c925756e29Jin Cao        heightAnimator.setDuration(mShrinkAnimationDuration);
247079d02b6021c640213888d446434e2c925756e29Jin Cao        heightAnimator.start();
248079d02b6021c640213888d446434e2c925756e29Jin Cao
249079d02b6021c640213888d446434e2c925756e29Jin Cao        /*
250079d02b6021c640213888d446434e2c925756e29Jin Cao         * Ideally, we would like to call mAdapter.notifyDataSetChanged() in a listener's
251079d02b6021c640213888d446434e2c925756e29Jin Cao         * onAnimationEnd(), but we are in the middle of a touch event, and this will cause all the
252079d02b6021c640213888d446434e2c925756e29Jin Cao         * views to get recycled, which will cause problems.
253079d02b6021c640213888d446434e2c925756e29Jin Cao         *
254079d02b6021c640213888d446434e2c925756e29Jin Cao         * Instead, we'll just leave the item in the list with a height of 0, and the next
255079d02b6021c640213888d446434e2c925756e29Jin Cao         * notifyDatasetChanged() will remove it from the adapter.
256079d02b6021c640213888d446434e2c925756e29Jin Cao         */
257079d02b6021c640213888d446434e2c925756e29Jin Cao    }
258079d02b6021c640213888d446434e2c925756e29Jin Cao
259079d02b6021c640213888d446434e2c925756e29Jin Cao    /**
260079d02b6021c640213888d446434e2c925756e29Jin Cao     * This method is used by the animator.  It is explicitly kept in proguard.flags to prevent it
261079d02b6021c640213888d446434e2c925756e29Jin Cao     * from being removed, inlined, or obfuscated.
262079d02b6021c640213888d446434e2c925756e29Jin Cao     * Edit ./vendor/unbundled/packages/apps/UnifiedGmail/proguard.flags
263079d02b6021c640213888d446434e2c925756e29Jin Cao     * In the future, we want to use @Keep
264079d02b6021c640213888d446434e2c925756e29Jin Cao     */
265079d02b6021c640213888d446434e2c925756e29Jin Cao    public void setAnimatedHeight(final int height) {
266079d02b6021c640213888d446434e2c925756e29Jin Cao        mAnimatedHeight = height;
267079d02b6021c640213888d446434e2c925756e29Jin Cao        requestLayout();
268079d02b6021c640213888d446434e2c925756e29Jin Cao    }
269079d02b6021c640213888d446434e2c925756e29Jin Cao
270079d02b6021c640213888d446434e2c925756e29Jin Cao    public static class ImageAttrSet {
271079d02b6021c640213888d446434e2c925756e29Jin Cao        // -1 for these resIds to not override the default value.
272079d02b6021c640213888d446434e2c925756e29Jin Cao        public int resId;
273079d02b6021c640213888d446434e2c925756e29Jin Cao        public int background;
274079d02b6021c640213888d446434e2c925756e29Jin Cao        public String contentDescription;
275079d02b6021c640213888d446434e2c925756e29Jin Cao
276079d02b6021c640213888d446434e2c925756e29Jin Cao        public ImageAttrSet(int resId, int background, String contentDescription) {
277079d02b6021c640213888d446434e2c925756e29Jin Cao            this.resId = resId;
278079d02b6021c640213888d446434e2c925756e29Jin Cao            this.background = background;
279079d02b6021c640213888d446434e2c925756e29Jin Cao            this.contentDescription = contentDescription;
280079d02b6021c640213888d446434e2c925756e29Jin Cao        }
281079d02b6021c640213888d446434e2c925756e29Jin Cao    }
282079d02b6021c640213888d446434e2c925756e29Jin Cao}
283