Trouble laying out ImageViews programmatically in RelativeLayout - java

I'm trying to add five or so ImageViews to a RelativeLayout, with each new one being to the right of the previous one. However, what I get is (apparently) all of them stacked up on each other, as if they were all ALIGN_PARENT_LEFT. Relevant code snippet:
ImageView[] foo = new ImageView[levels];
for (int i = 0; i < levels; i++) {
foo[i] = new ImageView(context);
layoutFoo.addView(foo[i]);
foo[i].setId(10 + i);
if (i == 0) {
RelativeLayout.LayoutParams fooParams = (RelativeLayout.LayoutParams) foo[i].getLayoutParams();
fooParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
foo[i].setLayoutParams(fooParams);
} else {
RelativeLayout.LayoutParams fooParams = (RelativeLayout.LayoutParams) foo[i].getLayoutParams();
fooParams.addRule(RelativeLayout.RIGHT_OF, foo[i-1].getId());
foo[i].setLayoutParams(fooParams);
}
}
Any hints what I'm doing wrong? It shouldn't matter that the ImageViews don't have any width (because I haven't assigned a bitmap to them) yet, right?
Edit: the problem turned out to be not setting a height and width for the ImageView. Solution is to set them either with setLayoutParams() or with the constructor as in JustWork's example.

You must add your ImageViews after setting properties them.
Move this code to end of the for loop:
layoutFoo.addView(foo[i]);
By the way you don't need to ImageView[]. You can accomplish it with one ImageView.
UPDATE:
Here is the code you can do same thing with:
ImageView foo;
RelativeLayout.LayoutParams fooParams;
for (int i = 0; i < levels; i++) {
foo = new ImageView(context);
foo.setId(10 + i);
fooParams = (RelativeLayout.LayoutParams) foo.getLayoutParams(); // I don't understand why you are trying to get params of which hasn't been specified before.
// If I were you, I would do like:
fooParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
if (i == 0) {
fooParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
} else {
fooParams.addRule(RelativeLayout.RIGHT_OF, foo.getId()-1);
}
foo.setImageBitmap(yourBitmap); // Set bitmap.
foo.setLayoutParams(fooParams);
layoutFoo.addView(foo);
}

I think the easiest way to place those images will be using a gallery. Although it's deprecated, I think it's a better idea to do it that way.

Related

How can I programmatically generate textviews inside layout

I need to generate TextView inside a layout from a random, API generated, ArrayList. I cant seem to find a way in which they appear in one line, like a String, one after the other and also shift below once the line has reached the max layout width limit. I want each TextView to be sperate as I want to click them.
Would like to achieve something like this...
This is the current code but the line stops and I don't know how to shift it below. Currently I am using a relative layout as the base layout but it is not necessary.
for (int i = 0; i < abc.size(); i++) {
titleText = new TextView(this);
titleText.setId(i);
titleText.setText(abc.get(i));
relativeLayout.addView(titleText, i);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(10, 10, 10, 10);
layoutParams.addRule(RelativeLayout.RIGHT_OF, titleText.getId() - 1);
titleText.setLayoutParams(layoutParams);
titleText.setTextColor(getResources().getColor(R.color.teal_700));
tvArray.add(titleText);
}
Example
In your xml
<LinearLayout
android:id="#+id/my_ll"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
</LinearLayout>
And write code in yourjava.class
LinearLayout my_ll = (LinearLayout) findViewById(R.id.my_ll);
for(int i=0;i<your_number_of_textviews;i++)
{
TextView text = new TextView(this);
text.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
text.setText(""+i);
my_ll.addView(text);
}
I think this solution would have solved it. First before the loop retrieve somewhere the width of the screen by using -
Point screenSizePoint = new Point();
// this gives you the furthest point from 0,0 e.g. 1440x3168
getWindowManager().getDefaultDisplay().getSize(screenSizePoint);
int sum = 0;
Then you retrieve your abc list somewhere.
And then you always compute the width of the current TextView by using this
titleText.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int width = titleText.getMeasuredWidth();
sum += width;
if (sum >= screenSizePoint.x) {
// shift to next line
}
and sum it up with the width of text views placed before and if the width is bigger than the screen width you just begin on another line.

Is there any possibility to set scale of multiple imageviews in a loop?

I want to set the ScaleX and ScaleY of multiple imageviews to the same value.
Is there a possibility to do it in a loop?
for(int i=1;i<=9;i++){
String img = "imageview" + i;
(imageview + i).setScaleX(x);
}
// x is the variable
I have not tested, but this should work
You could set a tag for each ImageView, making sure to increment each, for example:
//first ImageView
android:tag="#string/one" //one = 1
//second ImageView
android:tag="#string/two" //two = 2
Then in your for loop:
for(int i=1;i<=9;i++){
ImageView img = findViewWithTag(String.valueOf(i));
img.setScaleX(x);
}
But I would not recommend this. Instead, just set the setScaleX(x) to each individually. It's not that much code.

Reduce redundant code with ImageViews and switch cases

I have 7 ImageView's having each a switch case of 7 different cases that have the same behavior of setting images for all 7 ImageView's. Is there any way to shorten the code for this, right now I have to call each ImageView's by its name in the switch case for all the ImageView's separately and it makes the code lengthy and amateur. Like the following switch code for all imageviews being called each with their imageview names.
ImageView1 = (ImageView) v.findViewById(R.id.ImageView1);
ImageView2 = (ImageView) v.findViewById(R.id.ImageView2);
ImageView3 = (ImageView) v.findViewById(R.id.ImageView3);
ImageView4 = (ImageView) v.findViewById(R.id.ImageView4);
ImageView5 = (ImageView) v.findViewById(R.id.ImageView5);
ImageView6 = (ImageView) v.findViewById(R.id.ImageView6);
ImageView7 = (ImageView) v.findViewById(R.id.ImageView7);
switch(x){
case1:
ImageView1.setImageDrawable(getResources().getDrawable(R.drawable.Image1));
break;
case2:
ImageView1.setImageDrawable(getResources().getDrawable(R.drawable.Image2));
break;
case3:
ImageView1.setImageDrawable(getResources().getDrawable(R.drawable.Image3));
break;
case4:
ImageView1.setImageDrawable(getResources().getDrawable(R.drawable.Image4));
break;
case5:
ImageView1.setImageDrawable(getResources().getDrawable(R.drawable.Image5));
break;
case6:
ImageView1.setImageDrawable(getResources().getDrawable(R.drawable.Image6));
break;
case7:
ImageView1.setImageDrawable(getResources().getDrawable(R.drawable.Image7));
break;
}
For this case, you could create an Array of ImageView and another one, with the id's of the drawables. Something like that:
int[] idOfDrawables= {R.drawable.image1, R.drawable.image2,...,R.drawable.image7};
ImageView[] bundleImageView= {ImageView1, ImageView2, ...,ImageView7};
After that you could create a method, where the logic will happen, like this:
public void setImageToImageView(ImageView[] bundleImageView, int[] idOfDrawables)
{
for (int i=0; i< bundleImageView.length; i++)
{
bundleImageView[i].setImageResource(idOfDrawables[i]);
}
}
As the others suggested, create two arrays:
int[] ids = {R.drawable.Image1, R.drawable.Image2,...,R.drawable.Image7};
ImageView[] imageViews = {ImageView1, ImageView2, ...,ImageView7};
then use this:
private void showImage(int x, ImageView iv) {
iv.setImageDrawable(getResources().getDrawable(ids[x - 1]));
}
if you want to put the image for ImageView3 call showImage(x, ImageView3)
or if you want to show the image for all:
for (int i = 0; i < imageViews.length; i++) {
showImage(x, imageViews[i])
}
Put all your images as well as your imageViews in two separate arrays in a way that corresponds to each other, then use a for loop to loop through it.
findViewById...
int[] imageIds = {R.drawable.image1, R.drawable.image2,...,R.drawable.image7};
ImageView[] imageViews = {image1, image2, ...,image7};
for (int i = 0; i < imageViews.length; i++) {
imageViews[i].setImageResource(imageIds[i]);
}
you can use butterknife open source project which helps you to decrease adding findviewbyId in your code.
Find the link for it
Butterknife open source project

How can I dynamically achieve a multiple image layering effect?

Here's a picture of what I want to do:
where all the pictures are different and I could have between 2-10.
The code I have now is:
(flag is # of pictures)
(picUris[] is my array of Uri's)
RelativeLayout imgLayout = (RelativeLayout) findViewById(R.id.RelativeLayoutPictures);
for (int i = 0; i < flag; i++)
{
ImageView iv = new ImageView(this);
iv.setImageURI(picUris[i]);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
lp.setMargins(50*i, 50*i, 0, 0);
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
imgLayout.addView(iv, lp);
}
and the result:
The problems are that it's getting resized and doesn't get cut off by the screen like I want, and there's something weird going on at the bottom.
Why not using the Stackview? basically it will achieve the exact smae result without making you creating the view progrimatically....you don't have to re-invent the wheel...
where all the pictures are different and I could have between 2-10
I think you should use LayerDrawable and offsetting each layer by for example setLayerInset. Or creating all of the background in xml and set it to your viewgroup. I do not recommend you use FrameLayout and RelativeLayout because they both use much RAM in your situation.

programmatically edit images for puzzle usage

I'm making a sliding puzzle ( 3x3/4x4/5x5 with the lower-right corner cut out ). However I can't figure out where to start with programmatically cutting images ( which will be loaded from own gallery in sdcard or database from app ) in the puzzle pieces.
I've been looking over the internet and nothing really helped me.
What is the best way to cut up this image and store it in a new database (and still will be able to slide them)? Just a push in the right direction would be appreciated.
Check the PhotoGaffe app..
Its available on Google code here.
It allows user to choose between 3x3, 4x4, 5x5, and 6x6 puzzles.
This may help you in doing your task.
Straight from something I'm working on at the moment!
Bitmap main = BitmapFactory.decodeResource(getResources(), R.drawable.puzzle);
if( main.getHeight() > main.getWidth() ){
rescalefactor =((float)screenHeight)/main.getHeight();}
else {
rescalefactor = ( (float)screenWidth)/main.getWidth();
}
main = Bitmap.createScaledBitmap(main,(int)(main.getWidth()*rescalefactor),(int)(main.getHeight()*rescalefactor), false);
Bitmap cropped;
LinearLayout layout[] = new LinearLayout[rows];
int x=0,y=0,i=0,j=0,width=main.getWidth()/column,height=main.getHeight()/rows;
int count = 1;
for(i=0;i<rows;++i)
{
layout[i] = new LinearLayout(this);
for(j=0;j<column;++j)
{
cropped = Bitmap.createBitmap(main,x,y,width,height);
image[i][j] = new Tile(this);
image[i][j].setImageBitmap(cropped);
image[i][j].row =i;image[i][j].column =j;
image[i][j].setPadding(1, 1, 1, 1);
image[i][j].setOnClickListener(this);
image[i][j].setDrawingCacheEnabled(true);
image[i][j].setId(count); count++;
layout[i].addView(image[i][j]);
x += width;
}
x = 0; y += height;
root.addView(layout[i]);
}
This is the line where the work is really done:
cropped = Bitmap.createBitmap(main,x,y,width,height);
The Tile class is super simple. Just an extended ImageView with row and column fields:
public class Tile extends ImageView {
public int row, column;
public Tile(Context context)
{ super(context);}
}

Categories