1 /* 2 * Copyright (C) 2010 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 17 package com.android.camera.ui; 18 19 import com.android.camera.R; 20 import com.android.camera.Util; 21 22 import android.app.Activity; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.ActivityInfo; 27 import android.content.pm.PackageManager; 28 import android.content.pm.ResolveInfo; 29 import android.content.res.Resources; 30 import android.graphics.Bitmap; 31 import android.graphics.drawable.ColorDrawable; 32 import android.graphics.drawable.Drawable; 33 import android.net.Uri; 34 import android.view.Gravity; 35 import android.view.LayoutInflater; 36 import android.view.MotionEvent; 37 import android.view.View; 38 import android.view.ViewGroup; 39 import android.view.ViewGroup.LayoutParams; 40 import android.view.WindowManager; 41 import android.widget.AdapterView; 42 import android.widget.FrameLayout; 43 import android.widget.GridView; 44 import android.widget.ImageView; 45 import android.widget.PopupWindow; 46 import android.widget.SimpleAdapter; 47 48 import java.util.ArrayList; 49 import java.util.HashMap; 50 import java.util.List; 51 import java.util.Map; 52 53 // A popup window that contains a big thumbnail and a list of apps to share. 54 public class SharePopup extends PopupWindow implements View.OnClickListener, 55 View.OnTouchListener, AdapterView.OnItemClickListener, Rotatable { 56 private static final String TAG = "SharePopup"; 57 private static final String ADAPTER_COLUMN_ICON = "icon"; 58 private Context mContext; 59 private Uri mUri; 60 private String mMimeType; 61 private ImageView mThumbnail; 62 private int mBitmapWidth; 63 private int mBitmapHeight; 64 private int mOrientation; 65 private int mActivityOrientation; 66 // A view that contains a list of application icons and the share view. 67 private View mRootView; 68 // The list of the application icons. 69 private GridView mShareList; 70 // A rotated view that contains the thumbnail and the play icon. 71 private RotateLayout mThumbnailRotateLayout; 72 private RotateLayout mGotoGalleryRotate; 73 private View mPreviewFrame; 74 private ArrayList<ComponentName> mComponent = new ArrayList<ComponentName>(); 75 private View mImageViewFrame; 76 77 private class MySimpleAdapter extends SimpleAdapter { 78 public MySimpleAdapter(Context context, List<? extends Map<String, ?>> data, 79 int resource, String[] from, int[] to) { 80 super(context, data, resource, from, to); 81 } 82 83 @Override 84 public View getView(int position, View convertView, ViewGroup parent) { 85 View v = super.getView(position, convertView, parent); 86 RotateLayout r = (RotateLayout) v.findViewById(R.id.share_icon_rotate_layout); 87 r.setOrientation(mOrientation); 88 return v; 89 } 90 } 91 92 private final SimpleAdapter.ViewBinder mViewBinder = 93 new SimpleAdapter.ViewBinder() { 94 @Override 95 public boolean setViewValue(final View view, final Object data, 96 final String text) { 97 if (view instanceof ImageView) { 98 ((ImageView) view).setImageDrawable((Drawable) data); 99 return true; 100 } 101 return false; 102 } 103 }; 104 105 public SharePopup(Activity activity, Uri uri, Bitmap bitmap, int orientation, 106 View previewFrame) { 107 super(activity); 108 109 mActivityOrientation = activity.getRequestedOrientation(); 110 111 // Initialize variables 112 mContext = activity; 113 mUri = uri; 114 mMimeType = mContext.getContentResolver().getType(mUri); 115 mPreviewFrame = previewFrame; 116 LayoutInflater inflater = activity.getLayoutInflater(); 117 ViewGroup sharePopup = (ViewGroup) inflater.inflate(R.layout.share_popup, null, false); 118 // This is required because popup window is full screen. 119 sharePopup.setOnTouchListener(this); 120 mThumbnailRotateLayout = 121 (RotateLayout) sharePopup.findViewById(R.id.thumbnail_rotate_layout); 122 mShareList = (GridView) sharePopup.findViewById(R.id.share_list); 123 mThumbnail = (ImageView) sharePopup.findViewById(R.id.thumbnail); 124 mThumbnail.setImageBitmap(bitmap); 125 mImageViewFrame = 126 (View) sharePopup.findViewById(R.id.thumbnail_image_frame); 127 mImageViewFrame.setOnClickListener(this); 128 129 130 mGotoGalleryRotate = 131 (RotateLayout) sharePopup.findViewById(R.id.goto_gallery_button_rotate); 132 sharePopup.findViewById(R.id.goto_gallery_button).setOnClickListener(this); 133 134 mBitmapWidth = bitmap.getWidth(); 135 mBitmapHeight = bitmap.getHeight(); 136 137 // Show play button if this is a video thumbnail. 138 if (mMimeType.startsWith("video/")) { 139 sharePopup.findViewById(R.id.play).setVisibility(View.VISIBLE); 140 } 141 mBitmapWidth = bitmap.getWidth(); 142 mBitmapHeight = bitmap.getHeight(); 143 144 Resources res = mContext.getResources(); 145 146 // Initialize popup window size. 147 mRootView = sharePopup.findViewById(R.id.root); 148 LayoutParams params = mRootView.getLayoutParams(); 149 params.width = previewFrame.getWidth(); 150 params.height = previewFrame.getHeight(); 151 mRootView.setLayoutParams(params); 152 153 // Initialize popup window. 154 setWidth(WindowManager.LayoutParams.MATCH_PARENT); 155 setHeight(WindowManager.LayoutParams.MATCH_PARENT); 156 setBackgroundDrawable(new ColorDrawable()); 157 setContentView(sharePopup); 158 setOrientation(orientation); 159 setFocusable(true); 160 setAnimationStyle(R.style.AnimationPopup); 161 createShareMenu(); 162 163 adjustThumbnailPosition(); 164 } 165 166 private void adjustThumbnailPosition() { 167 FrameLayout.LayoutParams lpOld = 168 (FrameLayout.LayoutParams) mThumbnailRotateLayout.getLayoutParams(); 169 FrameLayout.LayoutParams lpNew = 170 new FrameLayout.LayoutParams(lpOld.width, lpOld.height); 171 172 mRootView.setBackgroundDrawable(null); 173 if (mBitmapWidth > mBitmapHeight * 2 || mBitmapHeight > mBitmapWidth * 2) { 174 // panorama image 175 lpNew.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL; 176 177 // panorama images block the preview from showing in the background 178 // use a special color here for that. 179 mRootView.setBackgroundColor( 180 mContext.getResources().getColor(R.color.share_popup_blackout)); 181 } else { 182 // landscape or portrait image 183 if (mActivityOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { 184 lpNew.gravity = Gravity.BOTTOM; 185 } else { 186 lpNew.gravity = Gravity.RIGHT; 187 } 188 } 189 190 mThumbnailRotateLayout.setLayoutParams(lpNew); 191 } 192 193 public void setOrientation(int orientation) { 194 mOrientation = orientation; 195 196 int hPaddingRootView = mRootView.getPaddingLeft() + mRootView.getPaddingRight(); 197 int vPaddingRootView = mRootView.getPaddingTop() + mRootView.getPaddingBottom(); 198 199 // Calculate the width and the height of the thumbnail. Reserve the 200 // space for paddings. 201 float maxWidth = mPreviewFrame.getWidth() - hPaddingRootView; 202 float maxHeight = mPreviewFrame.getHeight() - vPaddingRootView; 203 // Swap the width and height if it is portrait mode. 204 if (orientation == 90 || orientation == 270) { 205 float temp = maxWidth; 206 maxWidth = maxHeight; 207 maxHeight = temp; 208 } 209 float actualAspect = maxWidth / maxHeight; 210 float desiredAspect = (float) mBitmapWidth / mBitmapHeight; 211 212 if (mMimeType.startsWith("video/")) { 213 desiredAspect = 4F / 3F; 214 mThumbnail.setScaleType(ImageView.ScaleType.CENTER_CROP); 215 } else { 216 mThumbnail.setScaleType(ImageView.ScaleType.FIT_CENTER); 217 } 218 219 LayoutParams params = mThumbnail.getLayoutParams(); 220 if (actualAspect > desiredAspect) { 221 params.width = Math.round(maxHeight * desiredAspect); 222 params.height = Math.round(maxHeight); 223 } else { 224 params.width = Math.round(maxWidth); 225 params.height = Math.round(maxWidth / desiredAspect); 226 } 227 mThumbnail.setLayoutParams(params); 228 229 if (mThumbnailRotateLayout != null) mThumbnailRotateLayout.setOrientation(orientation); 230 231 int count = mShareList.getChildCount(); 232 for (int i = 0; i < count; i++) { 233 ViewGroup f = (ViewGroup) mShareList.getChildAt(i); 234 RotateLayout r = (RotateLayout) f.findViewById(R.id.share_icon_rotate_layout); 235 r.setOrientation(orientation); 236 } 237 238 mGotoGalleryRotate.setOrientation(orientation); 239 240 adjustThumbnailPosition(); 241 } 242 243 @Override 244 public void showAtLocation(View parent, int gravity, int x, int y) { 245 super.showAtLocation(parent, gravity, x, y); 246 // Inform other popup to dismiss if exit 247 PopupManager.getInstance(mContext).notifyShowPopup(null); 248 } 249 250 @Override 251 public void onClick(View v) { 252 switch (v.getId()) { 253 case R.id.goto_gallery_button: 254 case R.id.thumbnail_image_frame: 255 Util.viewUri(mUri, mContext); 256 break; 257 } 258 } 259 260 @Override 261 public boolean onTouch(View v, MotionEvent event) { 262 if (event.getAction() == MotionEvent.ACTION_DOWN) { 263 dismiss(); 264 return true; 265 } 266 return false; 267 } 268 269 public void createShareMenu() { 270 PackageManager packageManager = mContext.getPackageManager(); 271 List<ResolveInfo> infos = packageManager.queryIntentActivities( 272 new Intent(Intent.ACTION_SEND).setType(mMimeType), 0); 273 274 ArrayList<HashMap<String, Object>> items = new ArrayList<HashMap<String, Object>>(); 275 for (ResolveInfo info : infos) { 276 ComponentName component = new ComponentName( 277 info.activityInfo.packageName, info.activityInfo.name); 278 HashMap<String, Object> map = new HashMap<String, Object>(); 279 map.put(ADAPTER_COLUMN_ICON, info.loadIcon(packageManager)); 280 items.add(map); 281 mComponent.add(component); 282 } 283 284 // On phone UI, we have to know how many icons in the grid view before 285 // the view is measured. 286 if (mActivityOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { 287 mShareList.setNumColumns(items.size()); 288 int width = mContext.getResources().getDimensionPixelSize(R.dimen.share_item_width); 289 mShareList.setColumnWidth(width); 290 } 291 292 SimpleAdapter listItemAdapter = new MySimpleAdapter(mContext, items, 293 R.layout.share_icon, 294 new String[] {ADAPTER_COLUMN_ICON}, 295 new int[] {R.id.icon}); 296 297 listItemAdapter.setViewBinder(mViewBinder); 298 mShareList.setAdapter(listItemAdapter); 299 mShareList.setOnItemClickListener(this); 300 } 301 302 public Uri getUri() { 303 return mUri; 304 } 305 306 @Override 307 public void onItemClick(AdapterView<?> parent, View view, int index, long id) { 308 Intent intent = new Intent(Intent.ACTION_SEND); 309 intent.setType(mMimeType); 310 intent.putExtra(Intent.EXTRA_STREAM, mUri); 311 intent.setComponent(mComponent.get(index)); 312 mContext.startActivity(intent); 313 } 314 } 315