MessageListItem.java revision c81bef672089654e6da3babbeb0172bd636564b2
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.email.activity; 18 19import com.android.email.R; 20import com.android.email.provider.EmailProvider; 21import com.android.email.provider.EmailContent.Message; 22 23import android.content.ClipData; 24import android.content.Context; 25import android.content.res.Resources; 26import android.graphics.Bitmap; 27import android.graphics.BitmapFactory; 28import android.graphics.Canvas; 29import android.graphics.Point; 30import android.graphics.Typeface; 31import android.graphics.drawable.Drawable; 32import android.text.TextPaint; 33import android.util.AttributeSet; 34import android.view.MotionEvent; 35import android.view.View; 36import android.widget.RelativeLayout; 37 38/** 39 * This custom View is the list item for the MessageList activity, and serves two purposes: 40 * 1. It's a container to store message metadata (e.g. the ids of the message, mailbox, & account) 41 * 2. It handles internal clicks such as the checkbox or the favorite star 42 */ 43public class MessageListItem extends RelativeLayout { 44 private static final String TAG = "MessageListItem"; 45 // Note: messagesAdapter directly fiddles with these fields. 46 /* package */ long mMessageId; 47 /* package */ long mMailboxId; 48 /* package */ long mAccountId; 49 /* package */ boolean mRead; 50 /* package */ boolean mFavorite; 51 52 private MessagesAdapter mAdapter; 53 54 private boolean mDownEvent; 55 private boolean mCachedViewPositions; 56 private int mDragRight = -1; 57 private int mCheckRight; 58 private int mStarLeft; 59 60 // Padding to increase clickable areas on left & right of each list item 61 private final static float CHECKMARK_PAD = 20.0F; 62 private final static float STAR_PAD = 20.0F; 63 64 public static final String MESSAGE_LIST_ITEMS_CLIP_LABEL = 65 "com.android.email.MESSAGE_LIST_ITEMS"; 66 67 public MessageListItem(Context context) { 68 super(context); 69 } 70 71 public MessageListItem(Context context, AttributeSet attrs) { 72 super(context, attrs); 73 } 74 75 public MessageListItem(Context context, AttributeSet attrs, int defStyle) { 76 super(context, attrs, defStyle); 77 } 78 79 /** 80 * Called by the adapter at bindView() time 81 * 82 * @param adapter the adapter that creates this view 83 */ 84 public void bindViewInit(MessagesAdapter adapter) { 85 mAdapter = adapter; 86 mCachedViewPositions = false; 87 } 88 89 // This is tentative drag & drop UI 90 // STOPSHIP this entire class needs to be rewritten based on the actual UI design 91 private static class ThumbnailBuilder extends DragThumbnailBuilder { 92 private static Drawable sBackground; 93 private static TextPaint sPaint; 94 95 private View mView; 96 private static final int mWidth = 250; 97 private final Bitmap mDragHandle; 98 private final float mDragHandleX; 99 private final float mDragHandleY; 100 private String mDragDesc; 101 private float mDragDescX; 102 private float mDragDescY; 103 104 public ThumbnailBuilder(View view, int count) { 105 super(view); 106 Resources resources = view.getResources(); 107 mView = view; 108 mDragHandle = BitmapFactory.decodeResource(resources, R.drawable.drag_handle); 109 mDragHandleY = view.getHeight() - (mDragHandle.getHeight() / 2); 110 View handleView = view.findViewById(R.id.handle); 111 mDragHandleX = handleView.getLeft() + handleView.getPaddingLeft(); 112 mDragDesc = resources.getQuantityString(R.plurals.move_messages, count, count); 113 mDragDescX = handleView.getRight() + 50; 114 // Use height of this font?? 115 mDragDescY = view.getHeight() / 2; 116 if (sBackground == null) { 117 sBackground = resources.getDrawable(R.drawable.drag_background_holo); 118 sBackground.setBounds(0, 0, mWidth, view.getHeight()); 119 sPaint = new TextPaint(); 120 sPaint.setTypeface(Typeface.DEFAULT_BOLD); 121 sPaint.setTextSize(18); 122 } 123 } 124 125 @Override 126 public void onProvideThumbnailMetrics(Point thumbnailSize, Point thumbnailTouchPoint) { 127 //float width = mView.getWidth(); 128 float height = mView.getHeight(); 129 thumbnailSize.set(mWidth, (int) height); 130 thumbnailTouchPoint.set((int) mDragHandleX, (int) mDragHandleY / 2); 131 } 132 133 @Override 134 public void onDrawThumbnail(Canvas canvas) { 135 super.onDrawThumbnail(canvas); 136 sBackground.draw(canvas); 137 canvas.drawBitmap(mDragHandle, mDragHandleX, mDragHandleY, sPaint); 138 canvas.drawText(mDragDesc, mDragDescX, mDragDescY, sPaint); 139 } 140 } 141 142 /** 143 * Overriding this method allows us to "catch" clicks in the checkbox or star 144 * and process them accordingly. 145 */ 146 @Override 147 public boolean onTouchEvent(MotionEvent event) { 148 boolean handled = false; 149 int touchX = (int) event.getX(); 150 151 if (!mCachedViewPositions) { 152 final float paddingScale = getContext().getResources().getDisplayMetrics().density; 153 final int checkPadding = (int) ((CHECKMARK_PAD * paddingScale) + 0.5); 154 final int starPadding = (int) ((STAR_PAD * paddingScale) + 0.5); 155 View dragHandle = findViewById(R.id.handle); 156 if (dragHandle != null) { 157 mDragRight = dragHandle.getRight(); 158 } 159 mCheckRight = findViewById(R.id.selected).getRight() + checkPadding; 160 mStarLeft = findViewById(R.id.favorite).getLeft() - starPadding; 161 mCachedViewPositions = true; 162 } 163 164 switch (event.getAction()) { 165 case MotionEvent.ACTION_DOWN: 166 if (touchX < mDragRight) { 167 Context context = getContext(); 168 // Drag 169 ClipData data = ClipData.newUri(context.getContentResolver(), 170 MessageListItem.MESSAGE_LIST_ITEMS_CLIP_LABEL, null, 171 Message.CONTENT_URI.buildUpon() 172 .appendPath(Long.toString(mMessageId)) 173 .appendQueryParameter( 174 EmailProvider.MESSAGE_URI_PARAMETER_MAILBOX_ID, 175 Long.toString(mMailboxId)) 176 .build()); 177 startDrag(data, new ThumbnailBuilder(this, 1), false); 178 handled = true; 179 } else { 180 mDownEvent = true; 181 if ((touchX < mCheckRight) || (touchX > mStarLeft)) { 182 handled = true; 183 } 184 } 185 break; 186 187 case MotionEvent.ACTION_CANCEL: 188 mDownEvent = false; 189 break; 190 191 case MotionEvent.ACTION_UP: 192 if (mDownEvent) { 193 if (touchX < mCheckRight) { 194 mAdapter.toggleSelected(this); 195 handled = true; 196 } else if (touchX > mStarLeft) { 197 mFavorite = !mFavorite; 198 mAdapter.updateFavorite(this, mFavorite); 199 handled = true; 200 } 201 } 202 break; 203 } 204 205 if (handled) { 206 postInvalidate(); 207 } else { 208 handled = super.onTouchEvent(event); 209 } 210 211 return handled; 212 } 213} 214