/* * Copyright (C) 2012 Google Inc. * Licensed to 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.mail.browse; import android.content.Context; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Adapter; import android.widget.CursorAdapter; import com.android.mail.browse.ConversationViewAdapter.ConversationViewType; import com.android.mail.ui.ConversationViewFragment; import com.android.mail.utils.LogUtils; public abstract class ConversationOverlayItem { private int mHeight; // in px private int mTop; // in px private boolean mNeedsMeasure; public static final String LOG_TAG = ConversationViewFragment.LAYOUT_TAG; private int mPosition; // The view to focus when this overlay item should be focused. protected View mRootView; /** * @see Adapter#getItemViewType(int) */ public abstract @ConversationViewType int getType(); /** * Inflate and perform one-time initialization on a view for later binding. */ public abstract View createView(Context context, LayoutInflater inflater, ViewGroup parent); /** * @see CursorAdapter#bindView(View, Context, android.database.Cursor) * @param v a view to bind to * @param measureOnly true iff we are binding this view only to measure its height (so items * know they can cut certain corners that do not affect a view's height) */ public abstract void bindView(View v, boolean measureOnly); /** * Returns true if this overlay view is meant to be positioned right on top of the overlay * below. This special positioning allows {@link ConversationContainer} to stack overlays * together even when zoomed into a conversation, when the overlay spacers spread farther * apart. */ public abstract boolean isContiguous(); public View.OnKeyListener getOnKeyListener() { return null; } /** * Returns true if this overlay view is in its expanded state. */ public boolean isExpanded() { return true; } public int getGravity() { return Gravity.BOTTOM; } /** * This method's behavior is critical and requires some 'splainin. *
* Subclasses that return a zero-size height to the {@link ConversationContainer} will * cause the scrolling/recycling logic there to remove any matching view from the container. * The item should switch to returning a non-zero height when its view should re-appear. *
* It's imperative that this method stay in sync with the current height of the HTML spacer
* that matches this overlay.
*/
public int getHeight() {
return mHeight;
}
/**
* Set a new height.
*
* @param h a new height
* @return true if the value changed
*/
public boolean setHeight(int h) {
LogUtils.i(LOG_TAG, "IN setHeight=%dpx of overlay item: %s", h, this);
if (mHeight != h) {
mHeight = h;
mNeedsMeasure = true;
return true;
}
return false;
}
public int getTop() {
return mTop;
}
public void setTop(int top) {
mTop = top;
}
public boolean isMeasurementValid() {
return !mNeedsMeasure;
}
public void markMeasurementValid() {
mNeedsMeasure = false;
}
public void invalidateMeasurement() {
mNeedsMeasure = true;
}
public boolean canBecomeSnapHeader() {
return false;
}
public boolean canPushSnapHeader() {
return false;
}
public boolean belongsToMessage(ConversationMessage message) {
return false;
}
public void setMessage(ConversationMessage message) {
}
/**
* Given a view that is already bound to this item, force the view to re-render the item's
* current model data. This is typically called after a data model update, to update the
* affected view in-place.
*/
public void onModelUpdated(View v) {
}
public void setPosition(int position) {
mPosition = position;
}
public int getPosition() {
return mPosition;
}
/**
* This is a hack. Now that one view can update the
* state of another view, we need a mechanism when the
* view's associated item changes to update the state of the
* view. Typically, classes that override this class should not
* override this method.
*
* This method is used by
* {@link com.android.mail.browse.ConversationViewAdapter.BorderItem}
* to update the height of the border based on whether the neighboring messages
* are collapsed or expanded.
*
* It is also used by {@link com.android.mail.browse.ConversationViewAdapter.MessageHeaderItem}
* in the case where the snap header is tapped to collapse the message but the
* message header is still on screen. Since the message header is still on screen,
* it does not get bound but will get a rebind.
*
* The only other way to handle this case would be to call
* {@link com.android.mail.browse.ConversationViewAdapter#notifyDataSetChanged()}
* but that makes the entire screen flicker since the entire adapter performs
* a layout of the every item.
* @param view the view to be re-bound
*/
public void rebindView(View view) {
// DO NOTHING
}
public View getFocusableView() {
// Focus the root view by default
return mRootView;
}
public void registerOnKeyListeners(View... views) {
final View.OnKeyListener listener = getOnKeyListener();
if (listener != null) {
for (View v : views) {
if (v != null) {
v.setOnKeyListener(listener);
}
}
}
}
}