Adding ImageView to LinnearLayout dynamically goes wrong - android

I wrote a small function
private void addTabIndicators(int tabCount){
LinearLayout indicatorsContainer = (LinearLayout)findViewById(R.id.indicators_container);
for(int i = 0; i<tabCount; i++){
ImageView indicator = (ImageView)this.getLayoutInflater().inflate(R.layout.tab_indicator, null);
indicatorsContainer.addView(indicator);
}
}
that is supposed to add circles to the linearlayout in my activity based on how many tabs are in the pager adapter. Everything would be cool BUT, the imageviews i add instead of beeing the size declared in the xml layout, are being resized to 1x1px... Any ideas where i could go wrong? Here are the layouts for the indicator and linear layout
tab_indicator.xml:
<?xml version="1.0" encoding="utf-8"?>
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_margin="8dp"
android:src="#drawable/floating_button_background"/>
The indicators container:
<LinearLayout
android:layout_marginBottom="16dp"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:id="#+id/indicators_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</LinearLayout>

The fault might be here
ImageView indicator = (ImageView)this.getLayoutInflater().inflate(R.layout.tab_indicator, null);
You need to pass the root view of your image view to provide the layouts defined in your XML. If you pass null instead, default layoutparams are set.
Place
ImageView indicator = (ImageView)this.getLayoutInflater().inflate(R.layout.tab_indicator, your root view of image view,false);
This is a very common mistake. Never pass null except you really know what you are doing.
Read more here:
http://developer.android.com/reference/android/view/LayoutInflater.html
Hope it helps

Related

xml layout visibly different to code generated layout

Items will be displayed in a GridView:
<GridView
android:id="#+id/month_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="#dimen/activity_half_horizontal_margin"
android:paddingRight="#dimen/activity_half_horizontal_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:stretchMode="columnWidth"
android:horizontalSpacing="4dp"
android:verticalSpacing="4dp"/>
The layout for the items used to be generated in code:
private LinearLayout getMonthImageView() {
LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL);
TextView text = new TextView(context);
text.setGravity(Gravity.CENTER);
text.setSingleLine();
layout.addView(text, 0);
ImageView image = new ImageView(context);
image.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
image.setAdjustViewBounds(true);
layout.addView(image, 1);
return layout;
}
I've refactored that part to come from an xml layout file instead:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/month_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:singleLine="true"/>
<ImageView
android:id="#+id/month_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:adjustViewBounds="true"/>
</LinearLayout>
This had an unwanted visible effect: the gap between the items in the GridView has grown larger, as if the items had acquired some padding or margin (which is clearly not the case). Why is that? What is the difference of the items being generated in code versus coming from an xml layout file? How can I make the items scale up again?
Before (code layout):
After (xml layout):
I see some potential issues, but it's hard for me to say exactly what, without an image description of your problem.
You might wanna check out these few things:
If you're inflating LinearLayout, you should probably avoid android:layout_height="match_parent", because it takes up maximum space (usually the whole screen) even though you might not need it.
I'm thinking ImageView probably shouldn't be equal to parent, but have a distinct size.
This way also, it takes up maximum space in its parent, which it might not need.
My advice is, try a RelativeLayout, with the android:layout_width="match_parent" and android:layout_height="wrap_content.
Then use different layout_align options to align everything on top, and give some specific dimensions to your ImageView.
That's just my guess, I might be wrong though.

Adding items to the ScrollView dynamically make it doesn't scroll

I have a simple layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="300dp"
android:padding="15dp">
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/scrollLayout">
</LinearLayout>
</ScrollView>
</RelativeLayout>
Now, I inflate the outer RelativeLayout to retrieve the inner LinearLayout to put items in it.
RelativeLayout relative = (RelativeLayout) LayoutInflater.from(activity).inflate(R.layout.gradient_pick_view, null);
LinearLayout view = (LinearLayout) relative.findViewById(R.id.scrollLayout);
After that I created a method to add some buttons to it:
for(int i=0;i<10;i++){
LinearLayout wrapper = (LinearLayout) LayoutInflater.from(activity).inflate(R.layout.button_wrapper, null);
Button button = (Button)wrapper .findViewById(R.id.button);
view.addView(layout);
}
Everything works fine, but it doesn't scroll.
What am I doing wrong here?
Here's the screenshot (displaying 7 of 10 buttons):
I forgot to mention - I'm using a MaterialDialog library and add this RelativeLayout as a custom view to a dialog.
Try to set the following attribute to your scrollview,
android:fillViewport="true"
above attribute is used to make your scrollview to use entire screen of your application.
I had a false parameter passed to a customView in a MaterialDialog.
dialog = new MaterialDialog.Builder(activity)
.title(R.string.about)
.customView(view, true)
.positiveText(R.string.changing_fragments)
.show();
As doc says:
If wrapInScrollView is true, then the library will place your custom view inside of a ScrollView for you. This allows users to scroll your custom view if necessary (small screens, long content, etc.). However, there are cases when you don't want that behavior. This mostly consists of cases when you'd have a ScrollView in your custom layout, including ListViews, RecyclerViews, WebViews, GridViews, etc. The sample project contains examples of using both true and false for this parameter.
Now it's working.

Findviewbyid always returns null

I am Programmatically adding views to a linear layout (works fine). However when I try to get 1 specific imageview, ivBsquadBroken, that image view always returns null. All of the other viewes return correctly. I have simplified it down to just the two imageviews and nothing I have tried will return that view. The other imageview returns correctly and I can set the image, set visibility, etc.
Also, not sure why but if I declare R.layout.rowbridge_squads as the correct relative layout instead of a linear layout, it breaks.
Thanks for the help!
Code to Programmatically add the relative layout to the linear layout.
ArrayList<Squadron> tmpships = ((ExtendedApp) getActivity().getApplication()).getCurrentSquad();
LinearLayout tmpLL = (LinearLayout) mainView.findViewById(R.id.llBSquadList);
tmpLL.removeAllViews();
for(int i = 0; i <= tmpships.size() - 1; i++){
LinearLayout shiplayout = (LinearLayout) getActivity().getLayoutInflater().inflate(R.layout.rowbridge_squads, tmpLL, false);
ImageView tmpIB = (ImageView) shiplayout.findViewById(R.id.ivBsquadicon);
***!! always returns null - - >*** ImageView blasted = (ImageView) shiplayout.findViewById(R.id.ivBsquadBroken);
Squadron tmpsquad = tmpships.get(i);
Layout being inflated
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:id="#+id/llBrowsquaditem"
android:background="#color/bridge_cream">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/ivBsquadicon"
android:src="#android:drawable/ic_delete"
android:adjustViewBounds="true"/>
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/ivBsquadBroken"
android:src="#android:drawable/ic_delete"
android:adjustViewBounds="true"/>
</RelativeLayout>
Never mind. I have multiple configuration for landscape and portrait that I hadn't updated.
User error...

RelativeLayout takes fullscreen with layout_height="80dp"

I'm trying to create a fragment with height of 80dp, and at Design section it seems to work pretty well, but when I run the app on my device, RelativeLayout somehow takes a fullscreen. I use android:layout_alignParentBottom="true" for the SeekBar, but as far as I know it shouldn't take fullscreen if Layout's height isn't wrap_content. Here is the XML code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#bbbbff">
<SeekBar
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/progressBar"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="#+id/playButton"/>
<Button
android:layout_width="60dp"
android:layout_height="60dp"
android:text="play"
android:layout_alignParentRight="true"
android:id="#+id/playButton"/>
</RelativeLayout>
EDIT 1: I just tried to use this layout for an activity and it doesn't take fullscreen anymore, but I still have a problem with fragment. Also, I don't change Layout's height programmatically.
EDIT 2: I use fragmentTransaction.add(R.id.musicBarContainer, musicProgressBar) to add the fragment to activity, where musicProgressBar is an instance of fragment java class. The musicBarContainer XML code is
<FrameLayout
android:id="#+id/musicBarContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
</FrameLayout>
In onCreateView I use View view = inflater.inflate(R.layout.music_progress_bar, null);
From the RelativeLayout doc:
Class Overview
A Layout where the positions of the children can be described in relation to each other or to the parent.
Note that you cannot have a circular dependency between the size of the RelativeLayout and the position of its children. For example, you cannot have a RelativeLayout whose height is set to WRAP_CONTENT and a child set to ALIGN_PARENT_BOTTOM
Class documentation
Which is exactly your case. RelativeLayout can not do that.
for more detail visit this answer : RelativeLayout is taking fullscreen for wrap_content
In MusicProgressBar fragment class, instead of
View view = inflater.inflate(R.layout.music_progress_bar, null);
you should write
View view = inflater.inflate(R.layout.music_progress_bar, container, false);
Try setting the height of seekbar to 20dp and check. I think its wrap_content is overriding the parents height parameter somehow.

Compound layout

I want to create a custom layout to reduce redundancy in the code. Currently every layoutfile has about 30 Lines of code which are identical.
My goal was to create a custom layout/view which can hold in itself children.
<BaseLayout xmlns:...>
<!-- Normal Content -->
<Button />
<Label />
</BaseLayout>
While the above xml holds most of the content, the BaseLayout is in itself an xml containing other views and functionality:
<FrameLayout xmlns:...>
<LinearLayout><!-- contains the Header--></LinearLayout>
<LinearLayout><!-- INDIVIDUAL CONTENT HERE--></LinearLayout>
<FrameLayout><!-- contains the loading screen overlay --></FrameLayout>
</FrameLayout>
So all children from the above xml should be inserted into second linear-layout. I have already succeeded into doing so. But am confronted with layout problems (match parents does not match parents and only wraps)
My approach was extending the LinearLayout with following logic:
/**
* extracting all children and adding them to the inflated base-layout
*/
#Override
protected void onFinishInflate() {
super.onFinishInflate();
View view = LayoutInflater.from(getContext()).inflate(R.layout.base_layout, null);
LinearLayout linearLayout = (LinearLayout) view.findViewById(R.id.base_layout_children);
while(0 < getChildCount())
{
View child = getChildAt(0);
LinearLayout.MarginLayoutParams layoutParams = (MarginLayoutParams) child.getLayoutParams();
removeViewAt(0);
linearLayout.addView(child, layoutParams);
}
this.addView(view);
}
Is there a better, cleaner approach to capsule the xml and reuse a basis layout? How do I fix the match_parent issue?
While writing this post and thinking hard how to explain best, the solution for the match_parent issue became clear. Though the question remains if there is a better approach for the whole problem.
//Solution:
this.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
//wrong:
this.addView(view);
Suppose you have two layout files. common_views.xml and layout_main.xml. You can include content of one layout file into another like this.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<include
android:id="#+id/common"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
layout="#layout/common_views" />
<WebView
android:id="#+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#+id/common"
>
</WebView>
</RelativeLayout>

Categories

Resources