Android Open Source - HockeySDK-Android Attachment View






From Project

Back to project page HockeySDK-Android.

License

The source code is released under:

Apache License

If you think the Android project HockeySDK-Android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package net.hockeyapp.android.views;
//from   ww w . j av a 2 s . c o m
import java.io.File;

import net.hockeyapp.android.Constants;
import net.hockeyapp.android.objects.FeedbackAttachment;
import net.hockeyapp.android.utils.ImageUtils;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * <h3>Description</h3>
 * 
 * The view for an attachment.
 * 
 * <h3>License</h3>
 * 
 * <pre>
 * Copyright (c) 2011-2014 Bit Stadium GmbH
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * </pre>
 *
 * @author Patrick Eschenbach
 */
public class AttachmentView extends FrameLayout {

  private final static int IMAGES_PER_ROW_PORTRAIT = 3;

  private final static int IMAGES_PER_ROW_LANDSCAPE = 2;

  private final Context context;

  private final ViewGroup parent;

  private final FeedbackAttachment attachment;

  private final Uri attachmentUri;

  private final String filename;

  private ImageView imageView;

  private TextView textView;

  private int widthPortrait;

  private int maxHeightPortrait;

  private int widthLandscape;

  private int maxHeightLandscape;

  private int gap;

  private int orientation;

  public AttachmentView(Context context, ViewGroup parent, Uri attachmentUri, boolean removable) {
    super(context);

    this.context = context;
    this.parent = parent;
    this.attachment = null;
    this.attachmentUri = attachmentUri;
    this.filename = attachmentUri.getLastPathSegment();

    calculateDimensions(20);
    initializeView(context, removable);

    textView.setText(filename);
    new AsyncTask<Void, Void, Bitmap>() {
      @Override
      protected Bitmap doInBackground(Void... args) {
        Bitmap bitmap = loadImageThumbnail();
        return bitmap;
      }
        
      @Override
      protected void onPostExecute(Bitmap bitmap) {
        if (bitmap != null) {
          configureViewForThumbnail(bitmap, false);
        } else {
          configureViewForPlaceholder(false);
        }
      }
    }.execute();
  }

  public AttachmentView(Context context, ViewGroup parent, FeedbackAttachment attachment, boolean removable) {
    super(context);

    this.context = context;
    this.parent = parent;
    this.attachment = attachment;
    this.attachmentUri = Uri.fromFile(new File(Constants.getHockeyAppStorageDir(), attachment.getCacheId()));
    this.filename = attachment.getFilename();

    calculateDimensions(30);
    initializeView(context, removable);

    orientation = ImageUtils.ORIENTATION_PORTRAIT;
    textView.setText("Loading...");
    configureViewForPlaceholder(false);
  }

  public FeedbackAttachment getAttachment() {
    return attachment;
  }

  public Uri getAttachmentUri() { return attachmentUri; }

  public int getWidthPortrait() { return widthPortrait; }

  public int getMaxHeightPortrait() { return maxHeightPortrait; }

  public int getWidthLandscape() { return widthLandscape; }

  public int getMaxHeightLandscape() { return maxHeightLandscape; }

  public int getGap() { return gap; }

  public int getEffectiveMaxHeight() {
    return orientation == ImageUtils.ORIENTATION_LANDSCAPE ? maxHeightLandscape : maxHeightPortrait;
  }

  public void remove() {
    parent.removeView(this);
  }

  public void setImage(Bitmap bitmap, int orientation) {
    this.textView.setText(filename);
    this.orientation = orientation;

    if (bitmap == null) {
      configureViewForPlaceholder(true);

    } else {
      configureViewForThumbnail(bitmap, true);
    }
  }

  public void signalImageLoadingError() {
    textView.setText("Error");
  }

  private void calculateDimensions(int marginDip) {
    DisplayMetrics metrics = getResources().getDisplayMetrics();
    this.gap = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10.0f, metrics));

    int layoutMargin = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, marginDip, metrics));
    int displayWidth = metrics.widthPixels;

    int parentWidthPortrait  = displayWidth - (2 * layoutMargin) - ((IMAGES_PER_ROW_PORTRAIT  - 1) * gap);
    int parentWidthLandscape = displayWidth - (2 * layoutMargin) - ((IMAGES_PER_ROW_LANDSCAPE - 1) * gap);

    this.widthPortrait  = parentWidthPortrait / IMAGES_PER_ROW_PORTRAIT;
    this.widthLandscape = parentWidthLandscape / IMAGES_PER_ROW_LANDSCAPE;

    this.maxHeightPortrait  = widthPortrait * 2;
    this.maxHeightLandscape = widthLandscape;
  }

  private void initializeView(Context context, boolean removable) {
    setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.BOTTOM));
    setPadding(0, gap, 0, 0);

    // ImageView
    imageView = new ImageView(context);

    // LinearLayout
    LinearLayout bottomView = new LinearLayout(context);
    bottomView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, Gravity.BOTTOM));
    bottomView.setGravity(Gravity.LEFT);
    bottomView.setOrientation(LinearLayout.VERTICAL);
    bottomView.setBackgroundColor(Color.parseColor("#80262626"));

    // TextView
    textView = new TextView(context);
    textView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER));
    textView.setGravity(Gravity.CENTER);
    textView.setTextColor(Color.parseColor("#FFFFFF"));
    textView.setSingleLine();
    textView.setEllipsize(TextUtils.TruncateAt.MIDDLE);

    // Remove Button
    if (removable) {
      ImageButton imageButton = new ImageButton(context);
      imageButton.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, Gravity.BOTTOM));
      imageButton.setAdjustViewBounds(true);
      imageButton.setImageDrawable(getSystemIcon("ic_menu_delete"));
      imageButton.setBackgroundResource(0);
      imageButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
          AttachmentView.this.remove();
        }
      });

      bottomView.addView(imageButton);
    }

    bottomView.addView(textView);
    addView(imageView);
    addView(bottomView);
  }

  private void configureViewForThumbnail(Bitmap bitmap, final boolean openOnClick) {
    int width  = orientation == ImageUtils.ORIENTATION_LANDSCAPE ? widthLandscape : widthPortrait;
    int height = orientation == ImageUtils.ORIENTATION_LANDSCAPE ? maxHeightLandscape : maxHeightPortrait;

    textView.setMaxWidth(width);
    textView.setMinWidth(width);

    imageView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    imageView.setAdjustViewBounds(true);
    imageView.setMinimumWidth(width);
    imageView.setMaxWidth(width);
    imageView.setMaxHeight(height);
    imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
    imageView.setImageBitmap(bitmap);
    imageView.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View v) {
        if (!openOnClick) {
          return;
        }

        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        intent.setDataAndType(attachmentUri, "image/*");
        context.startActivity(intent);
      }
    });
  }

  private void configureViewForPlaceholder(final boolean openOnClick) {
    textView.setMaxWidth(widthPortrait);
    textView.setMinWidth(widthPortrait);

    imageView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    imageView.setAdjustViewBounds(false);
    imageView.setBackgroundColor(Color.parseColor("#eeeeee"));
    imageView.setMinimumHeight((int)(widthPortrait * 1.2f));
    imageView.setMinimumWidth(widthPortrait);
    imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
    imageView.setImageDrawable(getSystemIcon("ic_menu_attachment"));
    imageView.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View v) {
        if (!openOnClick) {
          return;
        }

        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        intent.setDataAndType(attachmentUri, "*/*");
        context.startActivity(intent);
      }
    });
  }

  private Bitmap loadImageThumbnail() {
    try {
      orientation = ImageUtils.determineOrientation(context, attachmentUri);
      int width  = orientation == ImageUtils.ORIENTATION_LANDSCAPE ? widthLandscape : widthPortrait;
      int height = orientation == ImageUtils.ORIENTATION_LANDSCAPE ? maxHeightLandscape : maxHeightPortrait;

      return ImageUtils.decodeSampledBitmap(context, attachmentUri, width, height);
    }
    catch (Throwable t) {
      return null;
    }
  }

  private Drawable getSystemIcon(String name) {
    return getResources().getDrawable(getResources().getIdentifier(name, "drawable", "android"));
  }
}




Java Source Code List

net.hockeyapp.android.Constants.java
net.hockeyapp.android.CrashManagerListener.java
net.hockeyapp.android.CrashManager.java
net.hockeyapp.android.ExceptionHandler.java
net.hockeyapp.android.ExpiryInfoActivity.java
net.hockeyapp.android.FeedbackActivityInterface.java
net.hockeyapp.android.FeedbackActivity.java
net.hockeyapp.android.FeedbackManagerListener.java
net.hockeyapp.android.FeedbackManager.java
net.hockeyapp.android.LocaleManager.java
net.hockeyapp.android.LoginActivity.java
net.hockeyapp.android.LoginManagerListener.java
net.hockeyapp.android.LoginManager.java
net.hockeyapp.android.PaintActivity.java
net.hockeyapp.android.StringListener.java
net.hockeyapp.android.Strings.java
net.hockeyapp.android.Tracking.java
net.hockeyapp.android.UpdateActivityInterface.java
net.hockeyapp.android.UpdateActivity.java
net.hockeyapp.android.UpdateFragment.java
net.hockeyapp.android.UpdateInfoListener.java
net.hockeyapp.android.UpdateManagerListener.java
net.hockeyapp.android.UpdateManager.java
net.hockeyapp.android.adapters.MessagesAdapter.java
net.hockeyapp.android.listeners.DownloadFileListener.java
net.hockeyapp.android.listeners.SendFeedbackListener.java
net.hockeyapp.android.objects.ErrorObject.java
net.hockeyapp.android.objects.FeedbackAttachment.java
net.hockeyapp.android.objects.FeedbackMessage.java
net.hockeyapp.android.objects.FeedbackResponse.java
net.hockeyapp.android.objects.Feedback.java
net.hockeyapp.android.tasks.AttachmentDownloader.java
net.hockeyapp.android.tasks.CheckUpdateTaskWithUI.java
net.hockeyapp.android.tasks.CheckUpdateTask.java
net.hockeyapp.android.tasks.DownloadFileTask.java
net.hockeyapp.android.tasks.GetFileSizeTask.java
net.hockeyapp.android.tasks.LoginTask.java
net.hockeyapp.android.tasks.ParseFeedbackTask.java
net.hockeyapp.android.tasks.SendFeedbackTask.java
net.hockeyapp.android.utils.AsyncTaskUtils.java
net.hockeyapp.android.utils.Base64.java
net.hockeyapp.android.utils.ConnectionManager.java
net.hockeyapp.android.utils.DeviceUtils.java
net.hockeyapp.android.utils.FeedbackParser.java
net.hockeyapp.android.utils.ImageUtils.java
net.hockeyapp.android.utils.PrefsUtil.java
net.hockeyapp.android.utils.SimpleMultipartEntity.java
net.hockeyapp.android.utils.UiThreadUtil.java
net.hockeyapp.android.utils.Util.java
net.hockeyapp.android.utils.VersionCache.java
net.hockeyapp.android.utils.VersionHelper.java
net.hockeyapp.android.utils.ViewHelper.java
net.hockeyapp.android.views.AttachmentListView.java
net.hockeyapp.android.views.AttachmentView.java
net.hockeyapp.android.views.ExpiryInfoView.java
net.hockeyapp.android.views.FeedbackMessageView.java
net.hockeyapp.android.views.FeedbackView.java
net.hockeyapp.android.views.LoginView.java
net.hockeyapp.android.views.PaintView.java
net.hockeyapp.android.views.UpdateView.java