I'm trying to upload an Image from my API to show it as profile picture, the problem is from the first time that the user opens the navdrawer the image doesn't load and it makes the entire layout disappear, but from the second time it all works, and I notice that it happens when the width of the image is less than the height. This is the class that I'm using:
public class CircledNetworkImageView extends ImageView {
public boolean mCircled;
/**
* The URL of the network image to load
*/
private String mUrl;
/**
* Resource ID of the image to be used as a placeholder until the network image is loaded.
*/
private int mDefaultImageId;
/**
* Resource ID of the image to be used if the network response fails.
*/
private int mErrorImageId;
/**
* Local copy of the ImageLoader.
*/
private ImageLoader mImageLoader;
/**
* Current ImageContainer. (either in-flight or finished)
*/
private ImageLoader.ImageContainer mImageContainer;
public CircledNetworkImageView(Context context) {
this(context, null);
}
public CircledNetworkImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircledNetworkImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Sets URL of the image that should be loaded into this view. Note that calling this will
* immediately either set the cached image (if available) or the default image specified by
* {#link CircledNetworkImageView#setDefaultImageResId(int)} on the view.
* <p/>
* NOTE: If applicable, {#link CircledNetworkImageView#setDefaultImageResId(int)} and
* {#link CircledNetworkImageView#setErrorImageResId(int)} should be called prior to calling
* this function.
*
* #param url The URL that should be loaded into this ImageView.
* #param imageLoader ImageLoader that will be used to make the request.
*/
public void setImageUrl(String url, ImageLoader imageLoader) {
mUrl = url;
mImageLoader = imageLoader;
// The URL has potentially changed. See if we need to load it.
loadImageIfNecessary(false);
}
/**
* Sets the default image resource ID to be used for this view until the attempt to load it
* completes.
*/
public void setDefaultImageResId(int defaultImage) {
mDefaultImageId = defaultImage;
}
/**
* Sets the error image resource ID to be used for this view in the event that the image
* requested fails to load.
*/
public void setErrorImageResId(int errorImage) {
mErrorImageId = errorImage;
}
/**
* Loads the image for the view if it isn't already loaded.
*
* #param isInLayoutPass True if this was invoked from a layout pass, false otherwise.
*/
void loadImageIfNecessary(final boolean isInLayoutPass) {
int width = getWidth();
int height = getHeight();
ScaleType scaleType = getScaleType();
boolean wrapWidth = false, wrapHeight = false;
if (getLayoutParams() != null) {
wrapWidth = getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT;
wrapHeight = getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT;
}
// if the view's bounds aren't known yet, and this is not a wrap-content/wrap-content
// view, hold off on loading the image.
boolean isFullyWrapContent = wrapWidth && wrapHeight;
if (width == 0 && height == 0 && !isFullyWrapContent) {
return;
}
// if the URL to be loaded in this view is empty, cancel any old requests and clear the
// currently loaded image.
if (TextUtils.isEmpty(mUrl)) {
if (mImageContainer != null) {
mImageContainer.cancelRequest();
mImageContainer = null;
}
setDefaultImageOrNull();
return;
}
// if there was an old request in this view, check if it needs to be canceled.
if (mImageContainer != null && mImageContainer.getRequestUrl() != null) {
if (mImageContainer.getRequestUrl().equals(mUrl)) {
// if the request is from the same URL, return.
return;
} else {
// if there is a pre-existing request, cancel it if it's fetching a different URL.
mImageContainer.cancelRequest();
setDefaultImageOrNull();
}
}
// Calculate the max image width / height to use while ignoring WRAP_CONTENT dimens.
int maxWidth = wrapWidth ? 0 : width;
int maxHeight = wrapHeight ? 0 : height;
// The pre-existing content of this view didn't match the current URL. Load the new image
// from the network.
ImageLoader.ImageContainer newContainer = mImageLoader.get(mUrl,
new ImageLoader.ImageListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (mErrorImageId != 0) {
setImageResource(mErrorImageId);
}
}
#Override
public void onResponse(final ImageLoader.ImageContainer response, boolean isImmediate) {
// If this was an immediate response that was delivered inside of a layout
// pass do not set the image immediately as it will trigger a requestLayout
// inside of a layout. Instead, defer setting the image by posting back to
// the main thread.
if (isImmediate && isInLayoutPass) {
post(new Runnable() {
#Override
public void run() {
onResponse(response, false);
}
});
return;
}
if (response.getBitmap() != null) {
setImageBitmap(response.getBitmap());
} else if (mDefaultImageId != 0) {
setImageResource(mDefaultImageId);
}
}
}, maxWidth, maxHeight, scaleType);
// update the ImageContainer to be the new bitmap container.
mImageContainer = newContainer;
}
private void setDefaultImageOrNull() {
if (mDefaultImageId != 0) {
setImageResource(mDefaultImageId);
} else {
setImageBitmap(null);
}
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
loadImageIfNecessary(true);
}
#Override
protected void onDetachedFromWindow() {
if (mImageContainer != null) {
// If the view was bound to an image request, cancel it and clear
// out the image from the view.
mImageContainer.cancelRequest();
setImageBitmap(null);
// also clear out the container so we can reload the image if necessary.
mImageContainer = null;
}
super.onDetachedFromWindow();
}
#Override
protected void drawableStateChanged() {
super.drawableStateChanged();
invalidate();
}
/**
* In case the bitmap is manually changed, we make sure to
* circle it on the next onDraw
*/
#Override
public void setImageBitmap(Bitmap bm) {
mCircled = false;
super.setImageBitmap(bm);
}
/**
* In case the bitmap is manually changed, we make sure to
* circle it on the next onDraw
*/
#Override
public void setImageResource(int resId) {
mCircled = false;
super.setImageResource(resId);
}
/**
* In case the bitmap is manually changed, we make sure to
* circle it on the next onDraw
*/
#Override
public void setImageDrawable(Drawable drawable) {
mCircled = false;
super.setImageDrawable(drawable);
}
/**
* We want to make sure that the ImageView has the same height and width
*/
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable drawable = getDrawable();
if (drawable != null) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int diw = drawable.getIntrinsicWidth();
if (diw > 0) {
int height = width * drawable.getIntrinsicHeight() / diw;
setMeasuredDimension(width, height);
} else
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} else
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
#Override
protected void onDraw(Canvas canvas) {
//Let's circle the image
if (!mCircled && getDrawable() != null) {
Drawable d = getDrawable();
try {
//We use reflection here in case that the drawable isn't a
//BitmapDrawable but it contains a public getBitmap method.
Bitmap bitmap = (Bitmap) d.getClass().getMethod("getBitmap").invoke(d);
if (bitmap != null) {
Bitmap circleBitmap = getCircleBitmap(bitmap);
setImageBitmap(circleBitmap);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
//Seems like the current drawable is not a BitmapDrawable or
//that is doesn't have a public getBitmap() method.
}
//Mark as circled even if it failed, because if it fails once,
//It will fail again.
mCircled = true;
}
super.onDraw(canvas);
}
/**
* Method used to circle a bitmap.
*
* #param bitmap The bitmap to circle
* #return The circled bitmap
*/
public static Bitmap getCircleBitmap(Bitmap bitmap) {
int size = Math.min(bitmap.getWidth(), bitmap.getHeight());
Bitmap output = Bitmap.createBitmap(size,
size, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
BitmapShader shader;
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
paint.setAlpha(254);
RectF rect = new RectF(0, 0, size, size);
int radius = size / 2;
canvas.drawRoundRect(rect, radius, radius, paint);
return output;
}
}
I came up with that solution, but I didn't like it, because the image loses its quality:
public class UserActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.profile_main);
toolbar = (Toolbar) findViewById(R.id.toolbar_user);
camera = (ImageView) findViewById(R.id.camera);
fechar = (TextView) findViewById(R.id.fechar);
editar = (TextView) findViewById(R.id.editar);
membro = (TextView) findViewById(R.id.membro);
nome = (TextView) findViewById(R.id.nome_usuario);
email = (TextView) findViewById(R.id.email_usuario);
email = (TextView) findViewById(R.id.email_usuario);
profilePic = (NetworkImageView) findViewById(R.id.foto);
mImageView = (ImageView) findViewById(R.id.cropped);
progress_wheel = (ProgressWheel) findViewById(R.id.progress_wheel);
camera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder getImageFrom = new AlertDialog.Builder(UserActivity.this);
getImageFrom.setTitle("Abrir com:");
final CharSequence[] opsChars = {getResources().getString(R.string.takepic), getResources().getString(R.string.opengallery)};
getImageFrom.setItems(opsChars, new android.content.DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (which == 0) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
mImageCaptureUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(),
"tmp_avatar_" + String.valueOf(System.currentTimeMillis()) + ".jpg"));
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, mImageCaptureUri);
try {
intent.putExtra("return-data", true);
startActivityForResult(intent, PICK_FROM_CAMERA);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
} else if (which == 1) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Complete action using"), PICK_FROM_FILE);
}
dialog.dismiss();
}
});
getImageFrom.show();
}
});
profilePic.setImageUrl(GlobalModel.getPerfil().getIdDaImagem(), imageLoader);
profilePic.setDefaultImageResId(R.drawable.avatar_);
}
#Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
if (resultCode != RESULT_OK) return;
switch (requestCode) {
case PICK_FROM_CAMERA:
profilePic.setVisibility(View.GONE);
progress_wheel.setVisibility(View.VISIBLE);
selectedImagePath = ImageFilePath.getPath(getApplicationContext(), mImageCaptureUri);
Log.i("Image File Path", "" + selectedImagePath);
mImageCaptureUri = Uri.parse(selectedImagePath);
final BitmapFactory.Options option = new BitmapFactory.Options();
option.inSampleSize = 8;
Bitmap photo = BitmapFactory.decodeFile(mImageCaptureUri.getPath(), option);
photo = Bitmap.createScaledBitmap(photo, 200, 200, false);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
File f = new File(Environment.getExternalStorageDirectory()
+ File.separator + "Imagename.jpg");
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
previewCapturedImage(f.getAbsolutePath());
profilePic.setVisibility(View.VISIBLE);
progress_wheel.setVisibility(View.GONE);
profilePic.setImageBitmap(BitmapFactory.decodeFile(mImageCaptureUri.getPath()));
break;
case PICK_FROM_FILE:
profilePic.setVisibility(View.GONE);
progress_wheel.setVisibility(View.VISIBLE);
mImageCaptureUri = data.getData();
selectedImagePath = ImageFilePath.getPath(getApplicationContext(), mImageCaptureUri);
Log.i("Image File Path", "" + selectedImagePath);
mImageCaptureUri = Uri.parse(selectedImagePath);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap photoGaleria = BitmapFactory.decodeFile(mImageCaptureUri.getPath(), options);
photoGaleria = Bitmap.createScaledBitmap(photoGaleria, 200, 200, false);
ByteArrayOutputStream bytesG = new ByteArrayOutputStream();
photoGaleria.compress(Bitmap.CompressFormat.JPEG, 100, bytesG);
File fG = new File(Environment.getExternalStorageDirectory()
+ File.separator + "Imagename.jpg");
fG.createNewFile();
FileOutputStream foG = new FileOutputStream(fG);
foG.write(bytesG.toByteArray());
foG.close();
previewCapturedImage(fG.getAbsolutePath());
profilePic.setVisibility(View.VISIBLE);
progress_wheel.setVisibility(View.GONE);
profilePic.setImageBitmap(BitmapFactory.decodeFile(mImageCaptureUri.getPath()));
break;
}
} catch (Exception e)
{
e.printStackTrace();
}
}
private void previewCapturedImage(String path) {
try {
UploadFoto mUpload = new UploadFoto(path);
mUpload.setEventoListener(new IExecutarTarefa<UploadFoto>() {
#Override
public void AntesDeExecutar(UploadFoto tarefa) {
}
#Override
public void DepoisDeExecutar(UploadFoto tarefa) {
if (tarefa.getResposta()[0].equals("200")) {
GlobalModel.getPerfil().setIdDaImagem(WebService.imgURL + tarefa.getResposta()[1].replace("\"", ""));
profilePic.setImageUrl(GlobalModel.getPerfil().getIdDaImagem(), imageLoader);
}
}
});
mUpload.execute();
} catch (NullPointerException e) {
e.printStackTrace();
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
finish();
overridePendingTransition(R.anim.animation_back, R.anim.animation_back_leave);
}
#Override
protected void onResume() {
super.onResume();
CarregarPerfil mCarrega = new CarregarPerfil();
mCarrega.execute();
}
}
XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:wheel="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<include
android:id="#+id/toolbar_user"
layout="#layout/toolbaruser" />
<RelativeLayout
android:id="#+id/campoImagem"
android:layout_width="fill_parent"
android:layout_height="200dp"
android:layout_below="#+id/toolbar_user"
android:background="#color/armadillo">
<com.android.volley.toolbox.NetworkImageView
android:id="#+id/foto"
android:layout_width="200dp"
android:layout_height="fill_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:src="#drawable/user"
android:visibility="visible" />
<com.pnikosis.materialishprogress.ProgressWheel
android:id="#+id/progress_wheel"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:visibility="gone"
wheel:matProg_barColor="#color/white"
wheel:matProg_progressIndeterminate="true"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<ImageView
android:id="#+id/cropped"
android:layout_width="200dp"
android:layout_height="fill_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_gravity="center"
android:visibility="visible"/>
<ImageView
android:id="#+id/camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:padding="15dp"
android:src="#drawable/ic_camera" />
<TextView
android:id="#+id/Button_crop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:gravity="center"
android:padding="15dp"
android:text="Salvar"
android:textColor="#color/white"
android:visibility="gone" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<TextView
android:id="#+id/membro"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:gravity="center"
android:paddingBottom="10dp"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:text="Membro Retornar desde Julho de 2015"
android:textColor="#color/star_dust" />
</RelativeLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/campoImagem"
android:layout_marginBottom="30dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="15dp"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:paddingBottom="0dp"
android:paddingLeft="10dp"
android:paddingRight="0dp"
android:paddingTop="10dp"
android:text="Nome"
android:textColor="#color/star_dust"
android:textSize="#dimen/text1" />
<TextView
android:id="#+id/nome_usuario"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:paddingBottom="0dp"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:textColor="#color/armadillo"
android:textSize="#dimen/text1" />
<TextView
android:id="#+id/entrar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:paddingLeft="10dp"
android:paddingTop="10dp"
android:text="E-mail"
android:textColor="#color/star_dust"
android:textSize="#dimen/text1" />
<TextView
android:id="#+id/email_usuario"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:paddingBottom="0dp"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:text="jgvidotto#gmail.com"
android:textColor="#color/armadillo"
android:textSize="#dimen/text1" />
</LinearLayout>
</RelativeLayout>
Because you have not posted your Activity calling the Navigation Drawer, so I have used both your CircledNetworkImageView class and built-in NetworkImageView in my project. It works well. Please refer to the following:
CustomNavigationDrawer.java:
public class CustomNavigationDrawer {
private static ActionBarDrawerToggle sDrawerToggle;
public static DrawerLayout setUpDrawer(final Context context) {
final Activity activity = ((Activity) context);
DrawerLayout sDrawerLayout = (DrawerLayout) activity.findViewById(R.id.drawer_layout);
if (activity.getActionBar() != null) {
activity.getActionBar().setDisplayHomeAsUpEnabled(true);
activity.getActionBar().setHomeButtonEnabled(true);
}
sDrawerToggle = new ActionBarDrawerToggle(
activity,
sDrawerLayout,
R.drawable.ic_drawer,
R.string.drawer_open,
R.string.drawer_close
) {
public void onDrawerClosed(View view) {
activity.invalidateOptionsMenu();
syncState();
}
public void onDrawerOpened(View drawerView) {
activity.invalidateOptionsMenu();
syncState();
}
};
sDrawerLayout.setDrawerListener(sDrawerToggle);
return sDrawerLayout;
}
public static void syncState() {
sDrawerToggle.syncState();
}
public static void onConfigurationChanged(Configuration newConfig) {
sDrawerToggle.onConfigurationChanged(newConfig);
}
}
MainActivity.java:
public class MainActivity extends Activity {
final Context mContext = this;
final String mUrl = "http://.../getimage";
NetworkImageView mNetworkImageView;
CircledNetworkImageView mCircledNetworkImageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CustomNavigationDrawer.setUpDrawer(this);
mNetworkImageView = (NetworkImageView) findViewById(R.id.networkImageView);
mNetworkImageView.setImageUrl(mUrl, VolleySingleton.getInstance(mContext).getImageLoader());
mCircledNetworkImageView = (CircledNetworkImageView) findViewById(R.id.circleImageView);
mCircledNetworkImageView.setImageUrl(mUrl, VolleySingleton.getInstance(mContext).getImageLoader());
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
CustomNavigationDrawer.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
CustomNavigationDrawer.onConfigurationChanged(newConfig);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
}
activity_main.xml:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<com.android.volley.toolbox.NetworkImageView
android:id="#+id/networkImageView"
android:layout_width="300dp"
android:layout_height="wrap_content" />
<com.example.networkimageview.CircledNetworkImageView
android:id="#+id/circleImageView"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_below="#+id/networkImageView" />
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
You can create a new sample project and use my sample code. Hope this helps!
if (width == 0 && height == 0 && !isFullyWrapContent) {
I guess the first you loadImage code will return because of this condition. The width and height is equal to 0 before the whole UI load success. log before this condition return. Hope this can help you.
Related
I have a recycle view to show all photo thumbnail items. When click on item, I use transition for imageview in this item to Detail activity. The problem is that image source is gotten from internet by UIL. And sometime (not always) the images not reload correct size like this:
// on view holder item click
final Pair<View, String>[] pairs = TransitionHelper.createSafeTransitionParticipants(this, false,
new Pair<>(((ItemViewHolder) viewHolder).thumbnail, getString(R.string.TransitionName_Profile_Image)),
new Pair<>(((ItemViewHolder) viewHolder).tvName, getString(R.string.TransitionName_Profile_Name)));
ActivityOptionsCompat transitionActivityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this, pairs);
startActivityForResult(intent, requestCode, transitionActivityOptions.toBundle());
Detail activity
// try to post pone transition until UIL load finish
ActivityCompat.postponeEnterTransition(this);
getSupportFragmentManager().beginTransaction().replace(R.id.layoutContent, new DetailFragment()).commit();
Fragment Detail
ImageLoader.getInstance().displayImage(url, imageViewDetail, new ImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
finishAnimation();
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
finishAnimation();
}
#Override
public void onLoadingCancelled(String imageUri, View view) {
finishAnimation();
}
});
private void finishAnimation(){
ActivityCompat.startPostponedEnterTransition(getActivity());
imageViewDetail.invalidate();
}
fragment_detail.xml
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:transitionName="#string/TransitionName.Profile.Image"
android:id="#+id/imageViewDetail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="centerCrop"/>
</FrameLayout>
I even wait views are laid out before load image but still not work:
imageViewDetail.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
// code load image from UIL
return false;
}
});
Is there any way to avoid this issue?
this xml can handle diferent image size
<ScrollView
android:id="#+id/vScroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="51dp"
android:scrollbars="none" >
<HorizontalScrollView
android:id="#+id/hScroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="none"
android:layout_gravity="center">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/imgFullscreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY" />
</LinearLayout>
</HorizontalScrollView>
</ScrollView>
in java
fullImageView = (ImageView) findViewById(R.id.imgFullscreen);
selectedPhoto = (FeedItem) i.getSerializableExtra(TAG_SEL_IMAGE);
zoom = 1;
if (selectedPhoto != null) {
fetchFullResolutionImage();
} else {
Toast.makeText(getApplicationContext(),
getString(R.string.msg_unknown_error), Toast.LENGTH_SHORT)
.show();
}
private void fetchFullResolutionImage() {
try {
final URL url = new URL(selectedPhoto.getImge());
new Thread(new Runnable() {
#Override
public void run() {
try {
Bitmap bmp = BitmapFactory.decodeStream(url
.openStream());
if (bmp != null)
setImage(bmp);
else {
showToast("Error fetching image!");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
private void setImage(final Bitmap bmp) {
runOnUiThread(new Runnable() {
public void run() {
fullImageView.setImageBitmap(bmp);
adjustImageAspect(selectedPhoto.getWidth(),
selectedPhoto.getHeight());
}
});
}
private void adjustImageAspect(int bWidth, int bHeight) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
if (bWidth == 0 || bHeight == 0)
return;
int swidth;
if (android.os.Build.VERSION.SDK_INT >= 13) {
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
swidth = size.x;
} else {
Display display = getWindowManager().getDefaultDisplay();
swidth = display.getWidth();
}
int new_height = 0;
new_height = swidth * bHeight / bWidth;
params.width = swidth;
params.height = new_height;
saveW = swidth;
saveH = new_height;
fullImageView.setLayoutParams(params);
}
I'm really new at this and I'm trying to load profile pics from gallery and camera into ImageButton. I'm able to add image from gallery but the image does not fit completely into the ImageButton. Some space still gets left out from the imagebutton. I want the image to automatically fit into imagebutton.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.sam.sport.MainActivity" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/LL1" >
<LinearLayout
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp" >
<ImageButton
android:id="#+id/profile_pic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/ic_launcher"
android:scaleType="fitXY"
android:adjustViewBounds="true" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
Activity class is as below:-
public class MainActivity extends Activity {
ImageButton ib;
private static Bitmap Image = null;
private static final int GALLERY = 1;
private static Bitmap rotateImage = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ib = (ImageButton)findViewById(R.id.profile_pic);
ib.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
ib.setImageBitmap(null);
if (Image != null)
Image.recycle();
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), GALLERY);
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == GALLERY && resultCode != 0) {
Uri mImageUri = data.getData();
try {
Image = Media.getBitmap(this.getContentResolver(), mImageUri);
if (getOrientation(getApplicationContext(), mImageUri) != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(getOrientation(getApplicationContext(), mImageUri));
if (rotateImage != null)
rotateImage.recycle();
rotateImage = Bitmap.createBitmap(Image, 0, 0, Image.getWidth(), Image.getHeight(), matrix,
true);
ib.setImageBitmap(rotateImage);
} else
ib.setImageBitmap(Image);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static int getOrientation(Context context, Uri photoUri) {
/* it's on the external media. */
Cursor cursor = context.getContentResolver().query(photoUri,
new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null);
if (cursor.getCount() != 1) {
return -1;
}
cursor.moveToFirst();
return cursor.getInt(0);
}
}
Convert it to Drawable then use setBackgroundDrawable insted of setImageBitmap
Drawable drawable = new BitmapDrawable(rotateImage);
ib.setBackgroundDrawable(drawable);
Use below line of code for re-sizing your bitmap
Bitmap BITMAP_IMAGE = Bitmap.createBitmap(IMAGE_VIEW.getWidth(),IMAGE_VIEW.getHeight(), Bitmap.Config.RGB_565);
Bitmap resizedBitmap = Bitmap.createScaledBitmap(BITMAP_IMAGE, 100, 100, false); ////Here BITMAP_IMAGE is your bitmap which you want to resize
Get the imageButton height and width
Bitmap bitmapScaled = Bitmap.createScaledBitmap(Image, ib_width, ib_height, true);
Drawable drawable = new BitmapDrawable(bitmapScaled);
ib.setBackgroundDrawable(drawable);
Keep in mind about OOM exception.
To get imageButton height and width look into this and this
I've got the perfect solution. To resize imageview I used the below code as provided in the [Android ImageView adjusting parent's height and fitting width
public class ResizableImageView extends ImageView {
public ResizableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
Drawable d = getDrawable();
if(d!=null){
// ceil not round - avoid thin vertical gaps along the left/right edges
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
setMeasuredDimension(width, height);
}else{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
]1
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I would like to know how to make a layout, like in a Facebook App. I understand, not only me alone looking for it, but I cannot to find the correct words for the search system to find it. And may be here somebody will give me a good link with a sample code. I like a menu, which shows up from the left side in their App.
You can go for any of this link below you like, there are lots of docs and tutorial available.
Android sliding menu demo
Facebook-like slide out navigation for Android
How To Create A Slide-In MenuList, Like In Facebook App
Hope it will help you.
If you need a simple but effective one then you can see the code. I was using it in my last project.
You can download full source code here.
You can check my blog too if it helped you.
Main layout : res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<com.banglardin.test_code.SlidingView
xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width ="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/list_activity_layout" >
<!-- Just make your sliding layout here -->
<LinearLayout
android:layout_width ="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#FF34495E"
android:id="#+id/slide_bar_list_activity" >
<!-- All the layout of sliding goes here -->
</LinearLayout>
<!-- Just make your content layout here -->
<LinearLayout
android:layout_width ="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#FF112131"
android:id="#+id/content_bar_list_activity" >
<!-- All the layout of content goes here -->
<RelativeLayout
android:id = "#+id/head1"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_alignParentTop = "true"
android:background="#336699"
android:maxWidth="48dp" >
<ImageButton
android:id ="#+id/main_menu_action_left_of_lable"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_alignParentLeft = "true"
android:layout_centerVertical ="true"
android:layout_weight="1"
android:src="#drawable/option_menu"
android:background="#drawable/all_image_button_press"
android:padding="5dp"/>
<!-- Title lable Of home bar. -->
<TextView
android:id ="#+id/main_toptext"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:gravity="center"
android:layout_weight="2"
android:shadowDy=".4"
android:shadowDx=".4"
android:clickable="true"
android:shadowRadius=".7"
android:shadowColor="#000000"
android:textColor = "#ffffff"
android:layout_toRightOf="#+id/main_menu_action_left_of_lable"
android:layout_toLeftOf="#+id/main_right_of_lable"
android:layout_centerInParent ="true"
android:textSize = "18dp"
android:layout_centerVertical ="true"
android:padding="5dp"
android:text = " Shiba prasad jana "
android:singleLine = "true"/>
<!-- Search -->
<ImageButton
android:id ="#+id/main_right_of_lable"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_alignParentRight = "true"
android:layout_centerVertical ="true"
android:layout_weight="1"
android:src="#drawable/search_icon"
android:background="#drawable/all_image_button_press"
android:padding="5dp"/>
</RelativeLayout>
</LinearLayout>
MainActivity: src/package_name/MainActivity
package com.banglardin.test_code;
import android.app.*;
import android.os.*;
import android.view.*;
import android.widget.*;
public class MainActivity extends Activity implements SlidingView.Listener {
protected SlidingView mSlidingView;
protected ImageButton menu;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
mSlidingView=(SlidingView)findViewById(R.id.list_activity_layout);
mSlidingView.setListener(this);
menu = (ImageButton) findViewById(R.id.main_menu_action_left_of_lable);
menu.setOnClickListener(new View.OnClickListener(){
public void onClick(View p1){
mSlidingView.toggleSidebar();
}
}
);
}
public void onSidebarOpened() {
}
public void onSidebarClosed() {
}
public boolean onContentTouchedWhenOpening() {
return false;
}
}
SlidingView : src/package_name/SlidingView
package com.banglardin.test_code;
import android.util.*;
import android.view.*;
import android.view.animation.*;
import android.content.Context;
public class SlidingView extends ViewGroup {
public final static int DURATION = 400; // time to show slding animation
protected boolean mPlaceLeft = true;
protected boolean mOpened;
protected View mSidebar;
protected View mContent;
protected int mSidebarWidth =-1; /* assign default value. It will be overwrite
in onMeasure by Layout xml resource. */
protected Animation mAnimation;
protected OpenListener mOpenListener;
protected CloseListener mCloseListener;
protected Listener mListener;
protected boolean mPressed = false;
public SlidingView(Context context) {
this(context, null);
int mSidebarWidth = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,50, getResources().getDisplayMetrics());
}
public SlidingView
(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void onFinishInflate() {
super.onFinishInflate();
mSidebar = findViewById(R.id.slide_bar_list_activity);
mContent = findViewById(R.id.content_bar_list_activity);
if (mSidebar == null) {
throw new NullPointerException("no view id = animation_sidebar");
}
if (mContent == null) {
throw new NullPointerException("no view id = animation_content");
}
mOpenListener = new OpenListener(mSidebar, mContent);
mCloseListener = new CloseListener(mSidebar, mContent);
}
#Override
public void onLayout(boolean changed, int l, int t, int r, int b) {
/* the title bar assign top padding, drop it */
int sidebarLeft = l;
if (!mPlaceLeft) {
sidebarLeft = r - mSidebarWidth;
}
mSidebar.layout(sidebarLeft,
0,
sidebarLeft + mSidebarWidth,
0 + mSidebar.getMeasuredHeight());
if (mOpened) {
if (mPlaceLeft) {
mContent.layout(l + mSidebarWidth, 0, r + mSidebarWidth, b);
} else {
mContent.layout(l - mSidebarWidth, 0, r - mSidebarWidth, b);
}
} else {
mContent.layout(l, 0, r, b);
}
}
#Override
public void onMeasure(int w, int h) {
super.onMeasure(w, h);
super.measureChildren(w, h);
mSidebarWidth = mSidebar.getMeasuredWidth();
}
#Override
protected void measureChild(View child, int parentWSpec, int parentHSpec) {
/* the max width of Sidebar is 90% of Parent */
if (child == mSidebar) {
int mode = MeasureSpec.getMode(parentWSpec);
int width = (int)(getMeasuredWidth() * 0.9);
super.measureChild(child, MeasureSpec.makeMeasureSpec(width, mode), parentHSpec);
} else {
super.measureChild(child, parentWSpec, parentHSpec);
}
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!isOpening()) {
return false;
}
int action = ev.getAction();
if (action != MotionEvent.ACTION_UP
&& action != MotionEvent.ACTION_DOWN) {
return false;
}
/* if user press and release both on Content while
* sidebar is opening, call listener. otherwise, pass
* the event to child. */
int x = (int)ev.getX();
int y = (int)ev.getY();
if (mContent.getLeft() < x
&& mContent.getRight() > x
&& mContent.getTop() < y
&& mContent.getBottom() > y) {
if (action == MotionEvent.ACTION_DOWN) {
mPressed = false;
}
if (mPressed
&& action == MotionEvent.ACTION_UP
&& mListener != null) {
mPressed = false;
return mListener.onContentTouchedWhenOpening();
}
} else {
mPressed = false;
}
return false;
}
public void setListener(Listener l) {
mListener = l;
}
/* to see if the Sidebar is visible */
public boolean isOpening() {
return mOpened;
}
public void toggleSidebar() {
if (mContent.getAnimation() != null) {
return;
}
if (mOpened) {
/* opened, make close animation*/
if (mPlaceLeft) {
mAnimation = new TranslateAnimation(0, -mSidebarWidth, 0, 0);
} else {
mAnimation = new TranslateAnimation(0, mSidebarWidth, 0, 0);
}
mAnimation.setAnimationListener(mCloseListener);
} else {
/* not opened, make open animation */
if (mPlaceLeft) {
mAnimation = new TranslateAnimation(0, mSidebarWidth, 0, 0);
} else {
mAnimation = new TranslateAnimation(0, -mSidebarWidth, 0, 0);
}
mAnimation.setAnimationListener(mOpenListener);
}
mAnimation.setDuration(DURATION);
mAnimation.setFillAfter(true);
mAnimation.setFillEnabled(true);
mContent.startAnimation(mAnimation);
}
public void openSidebar() {
if (!mOpened) {
toggleSidebar();
}
}
public void closeSidebar() {
if (mOpened) {
toggleSidebar();
}
}
class OpenListener implements Animation.AnimationListener {
View iSidebar;
View iContent;
OpenListener(View sidebar, View content) {
iSidebar = sidebar;
iContent = content;
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
iSidebar.setVisibility(View.VISIBLE);
}
public void onAnimationEnd(Animation animation) {
iContent.clearAnimation();
mOpened = !mOpened;
requestLayout();
if (mListener != null) {
mListener.onSidebarOpened();
}
}
}
class CloseListener implements Animation.AnimationListener {
View iSidebar;
View iContent;
CloseListener(View sidebar, View content) {
iSidebar = sidebar;
iContent = content;
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
iContent.clearAnimation();
iSidebar.setVisibility(View.INVISIBLE);
mOpened = !mOpened;
requestLayout();
if (mListener != null) {
mListener.onSidebarClosed();
}
}
}
public interface Listener
{
public void onSidebarOpened();
public void onSidebarClosed();
public boolean onContentTouchedWhenOpening();
}
}
I add 2 fragments in tab host.In second fragment i can do some drawing. When i switch between these two fragments, my drawing in second fragment is removed.I don't know why??
This is second fragment.
public class DrawingFragment extends BaseFragment implements android.view.View.OnClickListener {
private Context context = null;
private Bitmap backGroundBitmap = null;
private DrawingViewHolder viewHolder = null;
/**
*
*/
#Override
public void onAttach(Activity arg0) {
super.onAttach(arg0);
this.context=arg0;
}
public DrawingFragment() {
}
public DrawingFragment(Bitmap bitmap) {
this.backGroundBitmap = bitmap;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.drawing_dialog, container,false);
viewHolder = new DrawingViewHolder();
viewHolder.initUiContents(view);
return view;
}
/**
*
* #author Qandil
*
*/
private class DrawingViewHolder{
private Button btnDoneDrawing = null;
private Button btnEraserDrawing = null;
private Button btnPencilDrawing = null;
private Button btnDeleteDrawing = null;
private LinearLayout llDrawingMain = null;
private DrawView drawingView = null;
private void initUiContents(View view){
btnDoneDrawing = (Button) view.findViewById(R.id.btn_drawing_done);
btnEraserDrawing = (Button) view.findViewById(R.id.btn_drawing_eraser);
btnPencilDrawing = (Button) view.findViewById(R.id.btn_drawing_pencil);
btnDeleteDrawing = (Button) view.findViewById(R.id.btn_drawing_delete);
llDrawingMain = (LinearLayout) view.findViewById(R.id.ll_drawing_dialog_main);
drawingView = (DrawView)view.findViewById(R.id.custom_dv2);
btnDoneDrawing.setOnClickListener(DrawingFragment.this);
btnEraserDrawing.setOnClickListener(DrawingFragment.this);
btnPencilDrawing.setOnClickListener(DrawingFragment.this);
btnDeleteDrawing.setOnClickListener(DrawingFragment.this);
Drawable dr = new BitmapDrawable(backGroundBitmap);
llDrawingMain.setBackgroundDrawable(dr);
}
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_drawing_done:
((CaseActivity) getActivity()).popFragments();
break;
case R.id.btn_drawing_delete:
((CaseActivity) getActivity()).popFragments();
break;
default:
break;
}
}
/* (non-Javadoc)
* #see android.support.v4.app.Fragment#onDestroyView()
*/
#Override
public void onDestroyView() {
super.onDestroyView();
}
/* (non-Javadoc)
* #see android.support.v4.app.Fragment#onDetach()
*/
#Override
public void onDetach() {
super.onDetach();
}
}
drawing_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ll_drawing_dialog_main"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/ll_drawing_dialog"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/img_draw_photo_bg"
android:orientation="vertical" >
<RelativeLayout
android:id="#+id/top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/img_top_bar" >
<TextView
android:id="#+id/tv_draw_picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="#string/tv_draw_picture"
android:textColor="#ffffff"
android:textSize="18sp"
android:textStyle="bold" />
</RelativeLayout>
<LinearLayout
android:id="#+id/ll_header_drawing_dialog"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/img_top_bar"
android:gravity="center" >
<Button
android:id="#+id/btn_drawing_done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/img_drawing_done" />
<Button
android:id="#+id/btn_drawing_eraser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:background="#drawable/img_drawing_eraser" />
<Button
android:id="#+id/btn_drawing_pencil"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:background="#drawable/img_drawing_pencil" />
<Button
android:id="#+id/btn_drawing_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:background="#drawable/img_drawing_dlt" />
</LinearLayout>
<RelativeLayout
android:id="#+id/rlt_drawing_component"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<view
android:id="#+id/custom_dv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
class="com.avhl.view.activity.DrawView"
android:background="#00000000" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
DrawView.java
public class DrawView extends View{
private Bitmap cache;
private Queue<PointF> points;
private PointF from;
private Context context;
private Paint paint ;
public DrawView(Context context,AttributeSet attr) {
super(context,attr);
this.context=context;
points = new ConcurrentLinkedQueue<PointF>();
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(8);
paint.setColor(Color.GRAY);
paint.setDither(true); // set the dither to true
paint.setStyle(Paint.Style.FILL_AND_STROKE); // set to STOKE
paint.setStrokeJoin(Paint.Join.ROUND); // set the join to round you want
paint.setStrokeCap(Paint.Cap.ROUND); // set the paint cap to round too
setFocusable(true);
setFocusableInTouchMode(true);
}
/***
* on touch event
*/
#Override
public boolean onTouchEvent(MotionEvent evt) {
setPressed(true);
int pointerIndex = ((evt.getAction() & MotionEvent.ACTION_POINTER_ID_MASK)
>> MotionEvent.ACTION_POINTER_ID_SHIFT);
int pointerId = evt.getPointerId(pointerIndex);
if(pointerId==0){
switch (evt.getAction()) {
case MotionEvent.ACTION_DOWN:
from = new PointF(evt.getX(), evt.getY());
break;
case MotionEvent.ACTION_MOVE:
points.add(new PointF(evt.getX(), evt.getY()));
invalidate();
break;
case MotionEvent.ACTION_UP:
break;
default:
from = null;
}
}else{
return false;
}
return true;
}
/**
*
* #param systemCanvas
*/
#Override
public void onDraw(Canvas systemCanvas) {
int w = getWidth();
int h = getHeight();
if (w == 0 || h == 0)
return;
if (cache == null)
cache = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
// Draw on the cache
Canvas canvas = new Canvas(cache);
drawPoints(points, canvas, paint);
// Draw the cache with the system canvas
systemCanvas.drawBitmap(cache, 0, 0, paint);
}
/*
* for drawing line or dot
*/
private void drawPoints(Queue<PointF> points, Canvas canvas, Paint paint) {
if (from == null)
return;
PointF to;
while ((to = points.poll()) != null) {
canvas.drawLine(from.x, from.y, to.x, to.y, paint);
from = to;
}
}
}
In MianActivity i simply replace DrawingFragment tab with my first fragment by calling ft.replace() in on tab changed.
You can try calling Fragment.setRetainInstance(true) in the onCreate of your Fragment. This ensure the same fragment instance will be reused instead of creating a new one.
Without some code to show what you are doing, it is difficult to be more helpful
there is a layout, where I have some buttons, controls and an imageView. When the layout shows up, everything is okay. But later, when the requested image (the image of the aveform) is downloaded and I try to set it to the ImageView with setImageBitmap. The whole layout become messed up. Here are some pics.
This is how the layout looks like, when image has not been downloaded:
This is after the setImageBitMap
Here is my xml (I use a custom subclass of imageView, but the error also occurs withz the original mageView)
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
>
<TableLayout
android:id="#+id/tableLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TableRow
android:id="#+id/tableRow1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center" >
<adam.czibere.WaveFormSurfaceView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</TableRow>
<TableRow
android:id="#+id/tableRow2"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<SeekBar
android:id="#+id/seekBar"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="20dp"
android:layout_gravity="center"
android:thumb="#drawable/progress_fill" />
</TableRow>
<TableRow
android:id="#+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/currentPos"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="right"
android:layout_weight="5"
android:text="00:00.000" />
<TextView
android:id="#+id/textView4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_weight="1"
android:text="/" />
<TextView
android:id="#+id/endPos"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:gravity="left"
android:text="00:00.000" />
</TableRow>
<TableRow
android:id="#+id/tableRow4"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<Button
android:id="#+id/closebtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Close" />
<Button
android:id="#+id/playButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Play" />
<ToggleButton
android:id="#+id/toggleButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="ToggleButton" />
</TableRow>
</TableLayout>
Here is the extended imageView:
public class WaveFormSurfaceView extends ImageView {
public boolean isEditMode = false;
Bitmap waveform = null;
int touchCount = 0;
List<VerbaComment> myComments = new ArrayList<VerbaComment>();
int lastTouch_x = -1;
public WaveFormSurfaceView(Context context) {
super(context);
}
public WaveFormSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WaveFormSurfaceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
// copies the given waveform to a variable
public void setWaveForm(Bitmap b) {
waveform = Bitmap.createBitmap(b.getWidth(), b.getHeight(),
b.getConfig());
// copy the pixel to it
int[] allpixels = new int[b.getHeight() * b.getWidth()];
b.getPixels(allpixels, 0, b.getWidth(), 0, 0, b.getWidth(),
b.getHeight());
waveform.setPixels(allpixels, 0, b.getWidth(), 0, 0, b.getWidth(),
b.getHeight());
}
#Override
public void setImageBitmap(Bitmap bm) {
// TODO Auto-generated method stub
super.setImageBitmap(bm);
setWaveForm(bm);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// System.out.println("waveform width: "+waveform.getWidth());
// setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight());
// setMeasuredDimension(widthMeasureSpec,heightMeasureSpec);
// setMeasuredDimension(1000,200);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
// super.onDraw(canvas);
// Create a paint object for us to draw with, and set our drawing color
// to blue.
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setAlpha(50);
Paint paint1 = new Paint();
paint1.setColor(Color.GREEN);
paint1.setAlpha(50);
// draws the rectangle
if (waveform != null) {
canvas.drawBitmap(waveform, 0, 0, null);
if (isEditMode) {
for (VerbaComment vc : myComments) {
System.out.println("drawing the comment... start: "
+ vc.start + " end: " + vc.end);
canvas.drawRect(vc.start, canvas.getHeight(), vc.end, 0,
paint);
}
}
System.out.println("waveform width, height:" + waveform.getWidth()
+ " x " + waveform.getHeight());
} else {
canvas.drawRect(0, 0, 50, 50, paint);
}
// mImageView.setImageBitmap(map);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() == MotionEvent.ACTION_UP) {
if (isEditMode) {
touchCount++;
// lastTouch_x=(int)event.getX();
// System.out.println("onTouch; touchCount: "+touchCount+" lasttouch_x: "+lastTouch_x);
if (touchCount % 2 == 0) {
VerbaComment temp = new VerbaComment(lastTouch_x,
(int) event.getX());
myComments.add(temp);
} else {
lastTouch_x = (int) event.getX();
System.out.println("onTouch; touchCount: " + touchCount
+ " lasttouch_x: " + lastTouch_x);
}
}
}
invalidate();
return true;
}
}
And here is the activity:
public class AudioPlayerActivity extends Activity{
// Hardcoded parameters for the Verba demo server
private static final String ServerURL = "http://demo.verba.com";
private static final String MediaPath = "C:\\Program%20Files\\Verba\\media\\";
// Player user interface elements
private Button mBtnPlay;
private WaveFormSurfaceView mImageView;
//private ImageView mImageView;
private SeekBar mSeekBar;
private TextView mCurrentPos;
private TextView mEndPos;
private Bitmap originalWaveForm;
// THIS IS THE MEDIAPLAYER (has no UI, only loads and plays the audio)
private MediaPlayer mMediaPlayer;
// HTTP URL for the audio waveform PNG picture
private String getWaveformURL(String pCallURL) {
return ServerURL + ":8089/a?" + MediaPath + pCallURL
+ "?10000200240240240123023048240240240240240240";
}
// HTTP URL for the audio transcoded to MP3 format
private String getMediaURL(String pCallURL) {
return ServerURL + ":10100/getMedia?file=" + MediaPath + pCallURL
+ "&format=mp3";
}
// Downloads the waveform image outside of the main GU thread
private class DownloadWaveformTask extends AsyncTask<String, Void, Bitmap> {
#Override
protected Bitmap doInBackground(String... urls) {
try {
return BitmapFactory.decodeStream((InputStream) new URL(
getWaveformURL(myCallURL))
.getContent());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Bitmap result) {
try {
Thread.sleep(50000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mImageView.setImageBitmap(result);
}
}
// Updates the seekbar outside of the main GU thread, started only after
// MediaPlayer exists
private class SeekBarUpdater extends Thread {
float p=0;
#Override
public void run() {
final SimpleDateFormat tf = new SimpleDateFormat("mm:ss.SSS");
final Calendar calendar = Calendar.getInstance();
int currentPosition = 0;
final int total = mMediaPlayer.getDuration(); // //returns in msec,
// final because we
// will use in the
// runnable
// UI update must happen on the UI thread, so we post our actions
// there in a runnable
mCurrentPos.post(new Runnable() {
public void run() {
calendar.setTimeInMillis(total);
mEndPos.setText(tf.format(calendar.getTime()));
mSeekBar.setMax(total);
}
});
while (mMediaPlayer != null && currentPosition < total) {
try {
Thread.sleep(50);
currentPosition = mMediaPlayer.getCurrentPosition(); // returns
// in
// msec
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
// we are roughly adjusting for delays due to the thread
// communication
// currentPosition -= 100;
// if (currentPosition < 0 ) currentPosition = 0;
final int currPosition = currentPosition; // final because we
// will use in the
// runnable
p=(float)currentPosition/(float)total;
// UI update must happen on the UI thread, so we post our
// actions there in a runnable
mCurrentPos.post(new Runnable() {
public void run() {
calendar.setTimeInMillis(currPosition);
mCurrentPos.setText(tf.format(calendar.getTime()));
mSeekBar.setProgress(currPosition);
System.out.println("pecent="+p);
drawRectOnWaveForm(p);
}
});
}
}
}
String myCallURL;
/**
* Create a new instance of MyFragment that will be initialized
* with the given arguments.
*/
static MediaPlayerFragment newInstance(CharSequence url) {
MediaPlayerFragment f = new MediaPlayerFragment();
Bundle args = new Bundle();
args.putCharSequence("call_url", url);
f.setArguments(args);
return f;
}
/**
* During creation, if arguments have been supplied to the fragment
* then parse those out.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
if (extras != null) {
String value1 = extras.getString("call_url");
if(value1!=null){
myCallURL=value1;
}
}
DownloadWaveformTask task = new DownloadWaveformTask();
task.execute();
setContentView(R.layout.mediaplayer);
System.out.println("AudioPlayerActivity setContentView, mycallurl: "+myCallURL);
// part of the player UI
//mImageView = (ImageView) findViewById(R.id.imageView);
mImageView = (WaveFormSurfaceView) findViewById(R.id.imageView);
mBtnPlay = (Button) findViewById(R.id.playButton);
mSeekBar = (SeekBar) findViewById(R.id.seekBar);
mCurrentPos = (TextView) findViewById(R.id.currentPos);
mEndPos = (TextView) findViewById(R.id.endPos);
ToggleButton tb=(ToggleButton) findViewById(R.id.toggleButton1);
tb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if(isChecked){
mImageView.isEditMode=true;
mImageView.invalidate();
}else{
mImageView.isEditMode=false;
mImageView.invalidate();
}
}
});
//
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if (fromUser) {
// we only update the player if the change comes from a user
// action
mMediaPlayer.seekTo(progress);
}
}
});
// IMPORTANT
// - The DownloadWaveformTask part should go into the initialization of
// the player fragment
// - currently we are NOT handling currently the end of playback
// situations, we should
// - currently we are NOT releasing the MediaPlayer resource, we should
// when a fragment closes
mBtnPlay.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (mMediaPlayer != null) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
mBtnPlay.setText("Play");
} else {
mMediaPlayer.start();
mBtnPlay.setText("Pause");
}
} else {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
// this updates the seekbar as the buffering happens
mMediaPlayer
.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
#Override
public void onBufferingUpdate(MediaPlayer mp,
int percent) {
// TODO Auto-generated method stub
mSeekBar.setSecondaryProgress((int) (mSeekBar
.getMax() * percent / 100));
}
});
try {
final String lMediaURL = getMediaURL(myCallURL);
mMediaPlayer.setDataSource(lMediaURL);
mMediaPlayer.prepare(); // might take long! (for
// buffering, etc)
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mMediaPlayer.start();
mBtnPlay.setText("Pause");
// we start the thread that updates the seekbar, based on
// the state of the player
SeekBarUpdater thread = new SeekBarUpdater();
thread.start();
}
}
});
// Close button
Button closeBtn = (Button) findViewById(R.id.closebtn);
closeBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//TODO ha megy a lejátszás, megállítjuk
if(mMediaPlayer!=null){
if(mMediaPlayer.isPlaying()){
mMediaPlayer.stop();
}
}
finish();
}
});
}
}
Okz here are some flaws i have got in your code
You are giving android:layout_gravity="center" to your SeekBar and on other hand you are giving it match_parent attribute
Why you are giving fill_parent to your id/tableRow3
and try to use fill_parent instead of match _parent because fill_parent is backword compatible