Android; xamarin: LayoutParams are beeing ignored...? - android

I've got a bit of a problem here ( as you could probably figure... :D)
This is the code in question:
var imageView = new ImageView(context);
param = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MatchParent, LinearLayout.LayoutParams.MatchParent);
imageView.LayoutParameters = param;
imageView.SetImageResource(treeCatalog[position].imageId);
var viewPager = container.JavaCast<ViewPager>();
viewPager.AddView(imageView, param);
return imageView;
So, as you can see, I have an imageView, that I need to adjust programatically. I then set LayoutParams and handed them over (2x!) to the ImageView. However, no matter how I set them - nothing happens. The ImageView still is the same as before. This is driving my crazy.
Any help?
THANKS!

Based on your code viewPager.AddView(imageView, param);, you want to add image to your ViewPager, then the LayoutParams should be ViewPager.LayoutParams, which should be supplied for views added to a ViewPager.
But I don't think set the LayoutParams of ImageView here should fix your problem, I guess that you want to fill the whole item of ViewPager with image. Then you need to stretch the image.
So, you can try to change your code like this:
var imageView = new ImageView(context);
imageView.SetImageResource(treeCatalog[position].imageId);
imageView.SetScaleType(ScaleType.FitXy);
// Add the image to the ViewPager:
var viewPager = container.JavaCast<ViewPager>();
viewPager.AddView(imageView);
return imageView;

Related

Adding views dynamically in a for loop results in haphazard positioning - Android

I am adding views dynamically to a relative layout (let's say container) in a for loop. There is some thing strange I am noticing. When adding rows one below the other in a relative layout in a for loop, I see that the first time a few of the views are overlapping. But when I lock and unlock the screen, I can see that the views are placed correctly.
Should I be aware of something when adding views dynamically to a relative layout?
Edit
I have found a solution as to how to get rid of this (please check my answer). But I would be more than glad to accept an answer that analyses this problem and tells me why this happens.
I have simplified to code and the comments should give a good idea as to what I am doing.
int prev_id=ID_OF_THE_ELEMENT_ABOVE;
/*Empty RelativeView with width and height as MATCH_PARENT and WRAP_CONTENT respectively*/
RelativeLayout container=(RelativeLayout) findViewById(R.id.container);
while(ThereIsData){
/*GET THE DATA HERE THAT HAS TO BE ASSIGNED TO EACH TEXTVIEW*/
...
/* ADD TEXTVIEW #1 below prev_id/
...
...
/*ADD TEXTVIEW #2 (WITH BASELINE OF TEXTVIEW#
...
...
/*TEXTVIEW #3 (BELOW TEXTVIEW#1)*/
...
...
/*TEXTVIEW #4 (BELOW TEXTVIEW#2)*/
...
...
/*ASSIGN THE ID OF TEXTVIEW#3 TO prev_id SO THAT
IN THE NEXT ITERATION TEXTVIEW#1 CAN USE prev_id
*/
prev_id=ID(TEXTVIEW#2);
/*ADD TEXTVIEWS CREATED IN THIS ITERATION*/
container.addView(TEXTVIEW#1);
container.addView(TEXTVIEW#2);
container.addView(TEXTVIEW#3);
container.addView(TEXTVIEW#4);
}
It is due to the fact that you are having a RelativeLayout with height as WRAP_CONTENT, and adding a view doesn't refresh the whole container at that time.. so as you answered you can add a line to measure the dimensions explicitly or invalidate the view to recreate it completely.
In any case LinearLayout would be better to opt-for as it will automatically arrange the children in horizontal or vertical manner and you can even add the new view in any place other than last position and it will automatically be updated..
I used to struggle against common issues a year ago, when I was working on a library for dynamically creating layouts from XML files (as Android does not support this). So when you dynamically add views to a RelativeLayout you have to take in mind a few things:
Create the container View (in this case the RelativeLayout)
Create all views without assigning any layout parameters.
Add all child views to the container.
Iterate over the container's children and populate each child's layout parameters. This is needed because when the relational constraints are applied an Excpetion is thrown if the relative View is missing (was not previously added to the container).
This is an example code taken from the project I used to work on. Take in mind that it is just a single part so it contains references to classes that are not defined in the Android API. I am sure it will give you the basic idea of dynamically creating RelativeLayot:
private void setChildren(RelativeLayout layout, T widget,
InflaterContext inflaterContext, Context context,
Factory<Widget, View> factory) {
List<Widget> children = widget.getChildren();
if (Utils.isEmpty(children))) {
return;
}
// 1. create all children
for (Widget child : children) {
View view = factory.create(inflaterContext, context, child);
layout.addView(view);
}
// 2. Set layout parameters. This is done all children are created
// because there are relations between children.
for (Widget child : children) {
try {
View view = ViewIdManager.getInstance().findViewByName(layout, child.getId());
if (view != null) {
populateLayoutParmas(child, view);
}
} catch (IndexNotFoundException e) {
Log.e(LOG_TAG, "Cannot find a related view for " + child.getId(), e);
}
}
}
I have not yet found the answer to why this is happening. But I have found a solution. After adding each row in the loop, call container.measure(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
This seems to solve the problem. But I really think that container.addView() should also be calling measure().
/*ADD TEXTVIEWS CREATED IN THIS ITERATION*/
container.addView(TEXTVIEW#1);
container.addView(TEXTVIEW#2);
container.addView(TEXTVIEW#3);
container.addView(TEXTVIEW#4);
//---------------------------------------------------------------------
container.measure(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
//Declare globally
LinearLayout[] layout;
ImageView[] imageView1;
ImageView[] imageView2;
ImageView[] imageView3;
// Initialize your layout. It would be RelativeLayout too. Just reference to it.
LinearLayout ll = (LinearLayout) findViewById(R.id.mylinear);
// set listview row size as your demand
layout = new LinearLayout[200];
imageView1 = new ImageView[200];
imageView2 = new ImageView[200];
imageView3 = new ImageView[200];
for (int i = 0; i < 200; i++) {
layout[i] = new LinearLayout(this);
layout[i].setBackgroundResource(R.drawable.book_shelf);
// layout[i].setLayoutParams(new
// LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.FILL_PARENT,
// 120));
layout[i].setLayoutParams(new LinearLayout.LayoutParams(
android.widget.LinearLayout.LayoutParams.FILL_PARENT, 220));
imageView1[i] = new ImageView(this);
imageView2[i] = new ImageView(this);
imageView3[i] = new ImageView(this);
imageView1[i].setLayoutParams(new LinearLayout.LayoutParams(0, 200,
0.33f));
imageView1[i].setPadding(0, 20, 0, 0);
imageView1[i].setImageResource(R.drawable.bibid_one_bankim);
imageView2[i].setLayoutParams(new LinearLayout.LayoutParams(0, 200,
0.33f));
imageView2[i].setPadding(0, 20, 0, 0);
imageView2[i].setImageResource(R.drawable.bibid_two_bankim);
imageView3[i].setLayoutParams(new LinearLayout.LayoutParams(0, 200,
0.33f));
imageView3[i].setImageResource(R.drawable.dena_pawna);
imageView3[i].setPadding(0, 20, 0, 0);
layout[i].setId(i);
layout[i].setClickable(true);
final int j = i;
layout[i].addView(imageView1[i]);
layout[i].addView(imageView2[i]);
layout[i].addView(imageView3[i]);
ll.addView(layout[i]);
}
}
Try adding your views in vertical Linear Layout.
Following link might help you
http://www.myandroidsolutions.com/2012/06/19/android-layoutinflater-turorial/
Inflate your layout in for loop.

Views are not redrawing after the new width and height are set

I am killing myself with this problem so I am in desperate need of help.
I have a fragment with custom layout which is populated programmatically with linear layout which consists of an imageview and a textview.
User can dynamically change size of the fragment and here lies the problem.
I have onLayoutChange listener set on the fragment view where i change the size of the textview in respect to the size of the container and everything is correctly set when the container size changes but the views don't redraw themself and after the change all that i can see are the old views with their old width and height as if new width and height have never been applied.
I tried to invalidate the textview and i tried to call requestlayout on the parent view to no avail.
Its as if the new views are set but the old ones are shown.
Heres the code:
private void GenerateViews(View view) {
for (final Item artikl : listaArtikala) {
LinearLayout l_artikl = new LinearLayout(getActivity());
l_artikl.setPadding(10, 5, 0, 5);
final ImageView img = new ImageView(getActivity());
img.setMinimumWidth(image_width);
img.setMinimumHeight(image_height);
img.setScaleType(ScaleType.FIT_CENTER);
l_artikl.addView(img);
final TextView txv = new TextView(getActivity());
// dummy if to trigger after container size changes.
if(txv_artikl_width > 265)
txv.setWidth(300);
else
txv.setWidth(100);
txv.setWidth(300);
txv.setHeight(txv_artikl_height);
txv.setText(artikl.getName());
txv.setTextSize(15);
txv.setClickable(true);
txv.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
txv.setBackgroundColor(getResources().getColor(
R.color.LightSteelBlue));
txv.setPadding(5, 0, 10, 5);
l_artikl.addView(txv);
((ViewGroup) view).addView(l_artikl);
}
view.requestLayout();
}
All the help is appreciated.
After your if statement you reset the width of your textview:
if(txv_artikl_width > 265)
txv.setWidth(300);
else
txv.setWidth(100);
txv.setWidth(300);
You probably don't want to do that, right?

How to show data after Intent.ACTION_VIEW?

I'm creating search for my app and one of the last things I need to do is to "extract" the data when the user clicks on search-suggestion. Ive set Intent.ACTION_VIEW and got data by intent.getData(); in my searchable activity. But what should i do now to view the objects such as TextViews and ImageView "packaged" in the data? I have no big experience with this, so could you give me any advice please?
Thanks a lot
My example of code:
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
setContentView(R.layout.activity_more);
intent.getData();
final ProgressBar progress = (ProgressBar) findViewById(R.id.more_progress);
progress.setVisibility(View.VISIBLE);
TextView about = (TextView)findViewById(R.id.more_about);
TextView animal = (TextView)findViewById(R.id.more_animal);
final ImageView imgUrl = (ImageView)findViewById(R.id.more_imgUrl);
//now do i need to set Text etc., but how?
}
Just add them to any layout in your activity, and they will be shown in it.
How to Programmatically Add Views to Views
For expample, you have a LinearLayout with id mylayout.
LinearLayout layout = (LinearLayout) findViewById("mylayout");
LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layout.addView(myView, lp);
Alternatively, you can dispose of views and use only data from them - text from TextView, drawable from ImageView and etc.

Android programmatic relative layout: BELOW rule not working?

I want to create a layout (see class RosterPlayerView below) that comprises an image with text below it and then instantiate that view multiple times in a relative layout. I used relative layout instead of linear as the layout will become more complex.
When I first ran the code below (but without the setId calls) the text appeared above the image. Thanks to this stack overflow article I discovered that relative layout needs unique widget ids to work. But when I added the setId() calls the text view is not displayed at all.
What am I doing wrong?
public class RosterPlayerView extends RelativeLayout {
ImageView imageView;
TextView textView;
static int layoutId = 100;
public RosterPlayerView(Context context, int playerId, Drawable photo) {
super(context);
imageView = new ImageView(context);
textView = new TextView(context);
addView(imageView, new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
imageView.setId(layoutId++);
RelativeLayout.LayoutParams timeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
timeLayoutParams.addRule(RelativeLayout.BELOW, imageView.getId());
addView(textView, timeLayoutParams);
imageView.setImageDrawable(photo);
textView.setId(layoutId++);
textView.setText("0:00");
}
}
a LinearLayout would be an awful lot simpler for what you are trying to do. So would inflating an XML layout, for that matter.
Try to set the Id of you imageView before adding it to the layout.
You can also create a LinearLayout with the imageView and textView inside before adding it to the RelativeLayout

How do you setLayoutParams() for an ImageView?

I want to set the LayoutParams for an ImageView but cant seem to find out the proper way to do it.
I can only find documentation in the API for the various ViewGroups, but not an ImageView. Yet the ImageView seems to have this functionality.
This code doesn't work...
myImageView.setLayoutParams(new ImageView.LayoutParams(30,30));
How do I do it?
You need to set the LayoutParams of the ViewGroup the ImageView is sitting in. For example if your ImageView is inside a LinearLayout, then you create a
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(30, 30);
yourImageView.setLayoutParams(layoutParams);
This is because it's the parent of the View that needs to know what size to allocate to the View.
Old thread but I had the same problem now. If anyone encounters this he'll probably find this answer:
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(30, 30);
yourImageView.setLayoutParams(layoutParams);
This will work only if you add the ImageView as a subView to a LinearLayout. If you add it to a RelativeLayout you will need to call:
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(30, 30);
yourImageView.setLayoutParams(layoutParams);
If you're changing the layout of an existing ImageView, you should be able to simply get the current LayoutParams, change the width/height, and set it back:
android.view.ViewGroup.LayoutParams layoutParams = myImageView.getLayoutParams();
layoutParams.width = 30;
layoutParams.height = 30;
myImageView.setLayoutParams(layoutParams);
I don't know if that's your goal, but if it is, this is probably the easiest solution.
An ImageView gets setLayoutParams from View which uses ViewGroup.LayoutParams. If you use that, it will crash in most cases so you should use getLayoutParams() which is in View.class. This will inherit the parent View of the ImageView and will work always. You can confirm this here: ImageView extends view
Assuming you have an ImageView defined as 'image_view' and the width/height int defined as 'thumb_size'
The best way to do this:
ViewGroup.LayoutParams iv_params_b = image_view.getLayoutParams();
iv_params_b.height = thumb_size;
iv_params_b.width = thumb_size;
image_view.setLayoutParams(iv_params_b);
In order not to lose the rest of the parameters, you need to do as shown below:
Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.checked, null);
preview.setImageDrawable(drawable);
ViewGroup.LayoutParams layoutParams = preview.getLayoutParams();
layoutParams.width = 100;
layoutParams.height = 98;
preview.setLayoutParams(layoutParams);

Categories

Resources