I´m trying to do an easy example of an image gallery using horizontalscrollview and adding the images dynamically. I have searched examples but most are too complex. Is there a simple example of how to do it?
Here is some simple example which has implemented horizontal scroll view to look like image gallery
this will help you
Add HorizontalScrollView in layout:
<LinearLayout 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"
android:orientation="vertical">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/mygallery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
/>
</HorizontalScrollView>
</LinearLayout>
Main Java code:
package com.example.androidhorizontalscrollviewgallery;
import java.io.File;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
public class MainActivity extends Activity {
LinearLayout myGallery;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myGallery = (LinearLayout)findViewById(R.id.mygallery);
String ExternalStorageDirectoryPath = Environment
.getExternalStorageDirectory()
.getAbsolutePath();
String targetPath = ExternalStorageDirectoryPath + "/test/";
Toast.makeText(getApplicationContext(), targetPath, Toast.LENGTH_LONG).show();
File targetDirector = new File(targetPath);
File[] files = targetDirector.listFiles();
for (File file : files){
myGallery.addView(insertPhoto(file.getAbsolutePath()));
}
}
View insertPhoto(String path){
Bitmap bm = decodeSampledBitmapFromUri(path, 220, 220);
LinearLayout layout = new LinearLayout(getApplicationContext());
layout.setLayoutParams(new LayoutParams(250, 250));
layout.setGravity(Gravity.CENTER);
ImageView imageView = new ImageView(getApplicationContext());
imageView.setLayoutParams(new LayoutParams(220, 220));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageBitmap(bm);
layout.addView(imageView);
return layout;
}
public Bitmap decodeSampledBitmapFromUri(String path, int reqWidth, int reqHeight) {
Bitmap bm = null;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(path, options);
return bm;
}
public int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float)height / (float)reqHeight);
} else {
inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}
}
Note: in this example, the bitmaps in HorizontalScrollView will not be removed even not in screen. So if too much bitmaps loaded, error of java.lang.OutOfMemoryError will be thrown!
You could create a div and set the overflow to hidden then nest another inside it which has the heights or widths of all the images depends on your animation you want horizontal so go with the width times by the amount of images and remember to include the margins in this. You then code a jQuery animate to run on the larger div which will move it to the left or right again depending on your preference
eg $('pic').animate({left:'_____ <- enter width of single image together with margin here ' +'px','slow' <-- whatever speed you prefer);
and then play with it from there. your handler can be able to click on another button or on the image... preference again. It's very flexible without much coding , it's not the best option for use. If that doesn't suit you then create an array of images and loop through them rather than use those specific dimensions to scroll. Best of luck with this. Hope I have helped you out.
Related
I'm creating a GridLayout named channelView, which has bitmap icons as its views. But when the app runs on a device android 4.4.2 (only then) the first icon is smaller than the others.
Here is my code:
File file = new File(CatchupActivity.this.getApplicationContext().getFilesDir(),
Util.getFileNameFromUrl(tch.icon));
Bitmap icon;
try{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig =Bitmap.Config.ARGB_8888;
options.outHeight = 150;
options.outWidth = 150;
icon = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
}
catch(Exception e)
{
icon = Bitmap.createBitmap(120,120,Bitmap.Config.ARGB_8888);
}
channelIcon.setBackgroundResource(R.drawable.catchup_selector);
GridLayout.LayoutParams pp = new GridLayout.LayoutParams();
pp.setMargins(5, 5, 5, 5);
channelIcon.setImageBitmap(icon);
channelView.addView(channelIcon, pp);
And a screenshoot:
Why is this happening?
outWidth and outHeight are output parameters, used by inJustDecodeBounds. Setting them yourself has no meaning.
In this case, it would appear that the GridLayout cell is the right size, as the rows and columns are all set up properly. Since the default width and height for children of a GridLayout are wrap_content and wrap_content, this would suggest that the image that you are loading into the ImageView is smaller than the others.
I'm trying to get a picture from my camera device, to save it, and show a preview in a ImageView.
My ImageView (named imagePreview) is defined inside the following layout:
<LinearLayout
android:id="#+id/ll_selected_image"
android:layout_width="match_parent"
android:layout_height="300dp"
android:orientation="vertical"
android:layout_gravity="center_horizontal"
android:visibility="gone"> <!-- at first this is GONE -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imagePreview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"/>
</RelativeLayout>
</LinearLayout>
When the image is acquired from the camera, I try to scale my image following this document, which code is:
private void setPic() {
// Get the dimensions of the View
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
mImageView.setImageBitmap(bitmap);
}
The problem is that I obtain a "division by zero" mImageView.getWidth(); and mImageView.getHeight(); return zero.
Note that the visibility of the parent LinearLayout is setted to GONE. Then, my application sets programmatically it to VISIBLE.
If I remove GONE, and I add VISIBLE instead, all works good!
The strange thing is that I have tried to add in the setPic(), as first code lines, the following code:
if(ivSelectedImage.getVisibility() == View.VISIBLE)
Log.i(TAG,"IS VISIBLE!");
else if(ivSelectedImage.getVisibility() == View.GONE)
Log.i(TAG,"IS GONE!");
else if(ivSelectedImage.getVisibility() == View.INVISIBLE)
Log.i(TAG,"IS INVISIBLE!");
and this prints in my console "IS VISIBLE"!
BRIEFLY: If I set GONE in the XML, and then I set VISIBLE (programmatically) getHeight() and getWidth() can't get the correct value (also if when I call these methods the View is actually VISIBLE).
While, If I set VISIBLE in the XML, the methods getHeight() and getWidth() return me the correct values.
You don't need to use the view size at runtime for this example. Based on your code, while the view visibility is set to gone the main container, your LinearLayout, as a fixed height of 300dp. As a result, you already know one of the dimensions of your view since at best android:layout_height="match_parent" can only be equal to 300dp.
To scale properly you just need the screen width - since your main view (and nested RelativeLayout and ImageView are also set to match_parent). If you're in an activity use this
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
otherwise you can get the display using
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Just run this calculation before you need the set the image. Store the results to SharedPreferences or something and then use that ratio the 300dp height and screen width to scale the image.
Long time reader, first time poster. I'm very new to Android development and am having trouble getting images to show when using AsyncTask to insert ImageViews (containing Bitmaps) into a LinearLayout. This is all triggered in the onCreate() method of an Activity I have.
The ImageViews (+Bitmaps) are definitely getting added via AsyncTask to my LinearLayout parent. However, the images don't show properly when I start my Activity. Sometimes an image or two (out of 3+) will display and sometimes none will show. All the images display properly after I fiddle with the UI, such as by bringing up and hiding the keyboard. I suspect that the LinearLayout and/or ImageViews may not be resizing to contain and show all the new children, but I tried many combinations of invalidate() and requestLayout() at the places I marked as "LOCATION1" and "LOCATION2" in attempt to trigger redraws.
Would anyone help on ensuring all images are displayed properly after onCreate() and after each AsyncTask is complete? Thanks a bunch. I'll try to be succinct with my code snippets...
This is my layout XML. I am adding my ImageViews to the LinearLayout with id "horizontal":
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<EditText
... />
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
</HorizontalScrollView>
This is some of my onCreate() code. Where I create an AsyncTask for every image I want displayed.
protected void onCreate(Bundle savedInstanceState) {
...
LinearLayout horizontal = (LinearLayout) findViewById(R.id.horizontal);
...
//an array of absolute file paths to JPGs in storage
ArrayList<String> images = report.getImageMain();
PhotoBitmapTask task = null; //extension of AsyncTask
for (int i = 0; i < images.size(); i++) {
task = new PhotoBitmapTask(getApplicationContext(), horizontal, images);
task.execute(i);
//LOCATION1
}
...
}
This is my extension of AsyncTask.
//a bunch of imports
public class PhotoBitmapTask extends AsyncTask<Integer, Void, Bitmap> {
private Context context;
private WeakReference<ViewGroup> parent;
private ArrayList<String> images;
private int data;
public PhotoBitmapTask(Context context, ViewGroup parent, ArrayList<String> images) {
super();
this.context = context;
this.parent = new WeakReference<ViewGroup>(parent);
this.images = images;
this.data = 0;
}
#Override
protected Bitmap doInBackground(Integer... params) {
data = params[0];
return getBitmapFromFile(images.get(params[0]), 600, 600);
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if (context != null && parent != null && result != null) {
ViewGroup viewGroup = parent.get();
if (viewGroup != null) {
ImageView imageView = PhotoBitmapTask.getImageView(context);
imageView.setImageBitmap(result);
viewGroup.addView(imageView);
//LOCATION2
}
}
}
public static Bitmap getBitmapFromFile(String filePath, int maxHeight,
int maxWidth) {
// check dimensions for sample size
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
// calculate sample size
options.inSampleSize = getSampleSize(options, maxHeight, maxWidth);
// decode Bitmap with sample size
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}
public static int getSampleSize(BitmapFactory.Options options,
int maxHeight, int maxWidth) {
final int height = options.outHeight;
final int width = options.outWidth;
int sampleSize = 1;
if (height > maxHeight || width > maxWidth) {
// calculate ratios of given height/width to max height/width
final int heightRatio = Math.round((float) height / (float) maxHeight);
final int widthRatio = Math.round((float) width / (float) maxWidth);
// select smallest ratio as the sample size
if (heightRatio > widthRatio)
return heightRatio;
else
return widthRatio;
} else
return sampleSize;
}
public int getData() {
return this.data;
}
public static ImageView getImageView(Context context) {
// width and height
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
// margins
params.setMargins(20, 20, 20, 20);
final ImageView view = new ImageView(context);
view.setLayoutParams(params);
// scale type
view.setScaleType(ScaleType.CENTER);
return view;
}
}
After much headache and heartache, I found the answer. I did not mention it previously or search for it specifically because I didn't think it was relevant, but I'm using Nuance's 360 SpeechAnywhere developer SDK to include speech recognition in my app. Hopefully I'm not breaking the terms of my SDK license by saying this:
Every "recognition enabled" activity is supposed to have a custom View as the root in order to embed speech recognition controls and functionality. It turns out that this custom View does not always refresh its children, unless you instruct it to via the custom View's synchronize() function. Long story short, I called the View's synchronize() method once my AsyncTask finished, onPostExecute() ran, and Bitmap was added to the activity.
In the AsynTask you work on UI changes.you can't do changes in the UI in background work.Use runOnUIThread always do computation on UI thread.It better depend on your easy of use.look at here.
I have a problem with imageview, i have 77 picture jpg and have 126 quote text, just simple app i want is i want show all quote with background picture and i use viewflipper so when i swipe left/right get into next quote. I give you my code that i use now. Hope that anyone can help me.. Really wasting my time to fix it. My picture : 320x480.
vf = (ViewFlipper) findViewById(R.id.pages);
for (i = 0; i<totalphrase;i++) {
Log.i("ID",""+i);
var = arrayphrase.get(i);
//iv.setBackgroundColor(Color.rgb((int)Math.ceil(Math.random()*100), (int)Math.ceil(Math.random()*100), (int)Math.ceil(Math.random()*100)));
FrameLayout a = new FrameLayout(this);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.FILL_PARENT);
a.setLayoutParams(lp);
b = new ImageView(this);
LinearLayout.LayoutParams lp1 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT);
FrameLayout.LayoutParams lp2= new FrameLayout.LayoutParams(740, 800,Gravity.CENTER);
//b.setBackgroundColor(Color.rgb((int)Math.ceil(Math.random()*100), (int)Math.ceil(Math.random()*100), (int)Math.ceil(Math.random()*100)));
// i got outofmemoryerror with this, Imgid[] -> my picture in drawable there ara 77picture
b.setBackgroundResource(Imgid[(int)(Math.random()*Imgid.length)]);
// -- ERROR -- outofmemory
b.setLayoutParams(lp1);
a.addView(b);
c = new ScrollView(this);
c.setLayoutParams(lp2);
//c.setBackgroundColor(Color.CYAN);
c.setBackgroundColor(Color.argb(65, 53, 52, 52));
//idsc = c.getId();
a.addView(c);
LinearLayout d = new LinearLayout(this);
d.setLayoutParams(lp1);
//d.setBackgroundResource(R.drawable.background0);
c.addView(d);
TextView e = new TextView(this);
LinearLayout.LayoutParams lp3 = new LinearLayout.LayoutParams(730, 800);
e.setLayoutParams(lp1);
e.setText(var.phraseKey);
d.addView(e);
vf.addView(a);
}
}
The result that i want like this : example that i want to build in android
and this is xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/fl1"
>
<ViewFlipper
android:id="#+id/pages"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/transparent"
android:layout_gravity="top"
>
</ViewFlipper>
</FrameLayout>
I recommend to create an 2 dim array containing the comment and the path to the picture.
For the pictures, create a thumbnail. I am doing it with this code
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 4;
pic = BitmapFactory.decodeFile(strPicPath, options);
image.setImageBitmap(pic);
I am not sure if image gets smaller with bigger inSampleSize... You'll have to try
image is in XML:
<ImageView
android:id="#+id/imagePreview"
android:layout_width="134dp"
android:layout_height="146dp"
android:layout_weight="0.36"
android:onClick="imageClick" />
</LinearLayout>
I use the on click method to open the image in the gallery but you can do zoom or what you want.
To fix OutOfMemory you should do something like that:
this is a code i ref it's work good check it
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap=BitmapFactory.decodeStream(is,null,options);
This inSampleSize option reduces memory consumption.
Here's a complete method. First it reads image size without decoding the content itself. Then it finds the best inSampleSize value, it should be a power of 2. And finally the image is decoded.
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_SIZE=70;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
Try putting this code before changing the image:
imageView.getDrawable().getBitmap().recycle();
Is there anyway so I can align bitmap in ImageView. I have an issue with my image view. I'm setting it's source via Java Code and after bitmap is resized it's centered in ImageView, but the thing that I want is to align the bitmap.
Declaring the imageView :
<RelativeLayout
android:id="#+id/collection_background"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#+id/actionbar" >
<ImageView
android:id="#+id/collection_image_background"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:contentDescription="#string/stampii" />
// countinue ........
and here is how I'm setting the bitmap :
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inTempStorage = new byte[8*1024];
ops = BitmapFactory.decodeStream(cis,null,o2);
ImageView view = (ImageView) findViewById (R.id.collection_image_background);
view.setImageBitmap(ops);
Any ides how to do that?
Add android:scaleType="fitStart" to your ImageView. It is ok for me.
You can use android:scaleType to change the alignement in your ImageView.
You can use setLayoutParams, as shown in this answer.
EDIT
Your problem is that you've specified the view to be as wide as its parent, while the loaded bitmap may be considerably thinner.
Try to make the view only as wide as needed by using this attribute instead:
android:layout_width="wrap_content"
Actually you can scale your bitmap depending on your screen size and set it as source of your ImageView. You can use something like this :
int screenWidth = getWindow().getWindowManager().getDefaultDisplay().getWidth();
Log.e("","screen width : "+screenWidth);
//int screenHeight = getWindow().getWindowManager().getDefaultDisplay().getHeight();
int width = ops.getWidth();
Log.e("","bitmap width : "+width);
int height = ops.getHeight();
Log.e("","bitmap height : "+height);
float scale = 0;
if(width>height){
scale = (float) width / (float) height;
} else if(height>width){
scale = (float) height / (float) width;
}
Log.e("","scale : "+scale);
float newWidth = (float) screenWidth * scale;
Log.d("","new height : "+newWidth);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(ops, screenWidth, (int) newWidth, true);
Log.e("","new bitmap width : "+scaledBitmap.getWidth());
Log.e("","new bitmap height : "+scaledBitmap.getHeight());
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(screenWidth, (int)newWidth);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
view.setLayoutParams(params);
view.setImageBitmap(scaledBitmap);
Try this and just hit me up if it's working or not.
Additionally to the answers above you can set it programmatically with scaleType:
image.scaleType = ImageView.ScaleType.FIT_START