In the past, whenever I create a custom table layout, I create the children views in java and then add them to the table using tableRow.addView(childView). Presently, instead of creating all my children views by hand, I created them in xml and then inflate them into the tableRow.
So for example I do
RelativeLayout gameView = (RelativeLayout) mInflater.inflate(R.layout.my_game,
new RelativeLayout(context));
… //edits to gameView
gameView.requestLayout();
((ViewGroup) gameView.getParent()).removeAllViews();
tableRow.addView(gameView);
addView(tableRow);
My problem however is this: If I leave out the line ((ViewGroup) gameView.getParent()).removeAllViews() then I get an error that the view already has a parent and that I must first call revomeView on the child's parent. Not able to find any method called removeView, I use removeAllViews. But then when I do, I get a NullPointerException on the parent.
So the question: how do I inflate a view and then add it to a table layout?
Try changing this line
RelativeLayout gameView = (RelativeLayout) mInflater.inflate(R.layout.my_game,
new RelativeLayout(context));
to
RelativeLayout gameView = (RelativeLayout) mInflater.inflate(R.layout.my_game,
null);
Related
I am creating some views programmatically using ViewStubs, as shown below.
RelativeLayout allCommissionsContainer = (RelativeLayout) mBaseLayout.findViewById(R.id.allCommissionsContainer);
ViewStub viewStubCommission = new ViewStub(mActivity);
viewStubCommission.setLayoutResource(R.layout.viewstub_commission_container);
allCommissionsContainer.addView(viewStubCommission);
viewStubCommission.inflate();
But how do I find that inflated view (a RelativeLayout) later in the code? If I use viewStubCommission.setTag("MyTag"); won't it be applied to the actual ViewStub and not the inflated View? I tried this but it gave me a null pointer exception.
I need something like allCommissionsContainer.findViewById(R.id.someId) or allCommissionsContainer.findViewWithTag("MyTag").
After some testing I realized I can use
RelativeLayout myRelativeLayout = (RelativeLayout) viewStubCommission.inflate();
and then set a tag or id
myRelativeLayout.setTag("MyTag");
What I am attempting to do is take a custom view (which is a constructor & onDraw method) and a set of controls in a RelativeLayout and display them together with-in a FrameLayout. My code currently gets to adding the overlay and crashes with a Null Pointer Execption but if I directly add the overlay and cut out the FrameLayout & custom view it works.
FrameLayout layout = new FrameLayout(this);
SampleView sv = new SampleView(this, objectA, objectB, ObjectC), RESULTS);
RelativeLayout overlay = (RelativeLayout) findViewById(R.layout.analysis_overlay);
layout.addView(sv);
layout.addView(overlay);
setContentView(layout);
I assume there is a better way to do this and I've seen examples of a FrameLayout existing in xml but I didn't see anyway of setting the constructor via that method... So is there a better way of doing this that still allows custom view to have a constructor or did I mess somthing up with my current code?
You are attempting to find an id of a layout resource. Instead, inflate your relative layout (the layout resource) and then add it.
FrameLayout layout = new FrameLayout(this);
SampleView sv = new SampleView(this, objectA, objectB, ObjectC), RESULTS);
RelativeLayout overlay = (RelativeLayout) LayoutInflater.from(this).inflate(R.layout.analysis_overlay, layout, false);
layout.addView(sv);
layout.addView(overlay);
setContentView(layout);
RelativeLayout overlay = (RelativeLayout) findViewById(R.layout.analysis_overlay);
You can never find anything with id from R.layout. Use R.id.
You can never find anything before setContentView() when using Activity findViewById().
Call findViewById() on a view hierarchy that actually contains the overlay you want to find.
If you just want to inflate an XML layout, use LayoutInflater.
I want to set a ScrollView for some views. I need to merge some view into one view and add to ScrollView.
The three views are listView, custorm view and Gallery.
Who knows how to merge the three views into a blank view and display?
In XML you can structure your app like the following snippet:
<ScrollView>
<LinearLayout>
<CustomView/>
<ListView/>
<Gallery/>
</LinearLayout>
</ScrollView>
Alternatively in code, you can do it like so:
ScrollView SV = (ScrollView) findViewById(R.id.my_scrollview);
LinearLayout LL = (LinearLayout) findViewById(R.id.my_linear_layout);
LL.addView(my_customView)
LL.addView(my_istView)
LL.addView(my_gallery)
SV.addView(LL);
hope that gives you some pointers in how to achieve what you'd like to
You can create those objects and assign them inflated elements. I mean, if the listView is in listView.xml you can inflate it with getLayoutInflater().inflate(R.layout.listView,null) and put in a ListView object. Then you can add it to a ViewGroup.
Inflate the ScrollView, you can create programmatically too. ScrollView scroll=new ScrollView(this). Don't forget adding LayoutParams to the view if you do it programmatically.
ViewGroup scrollView = (ViewGroup) getLayoutInflater().inflate(R.layout.scrollView, null);
Then you inflate or create the other views the same way. Or you can get it from an activity with findViewById(R.id.idOfView1).
Finally just add the views you've created, inflated... with scrollView.addView(View child).
You need a ViewGroup to add views as childs.
I have a LinearLayout View with a OnClickhandler and I want to add a View after the LinearLayout programatically when the OnClick event is fired.
public void onClick(View view) {
LayoutInflater li = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout info = (LinearLayout) li.inflate(R.layout.infolayer, null);
// view.addViewAfter(info)
}
info is the View i want to add. view is the View on which the click goes and after which I want to add info.
How can I do that?
IF u want add a view after the current linear layout then first get the id of the parent layout in which the linear layout is .
for example let u have the the Linear Layout with id "ll" in relative layout(having id parentlayout) and on a button click u want add the text view under the liner layout
public void onClick(View view) {
RelativeLayout rl=new RelativeLayout(this);
TextView tv=new TextView(this)
//set param value ur requirement
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.BELOW,R.id.ll);
}
Assuming you have a known amount of linearlayouts could you just place them inside the XML resource and mark them as 'GONE'. When the event occurs make them visible. When they are marked as gone they shouldnt be taking any screen space up.
You can insert through coding and you don't need to inflate. You can create a view of any type calling the constructor and passing the context. A reference to the context can be stored on the view as a field, when the view is being constructed. This way you can always create your view on the fly.
To add the view to the LinearLayout, you just need to call addView. And afterwards, if you would want to remove it, just call removeView.
But the onClick event is inside the LinearLayout object? This might be a problem because the views inside the the LinearLayout might consume the event before it reaches your method. See this post to learn about that.
Let's say I have a LinearLayout, and I want to add a View to it, in my program from the Java code. What method is used for this? I'm not asking how it's done in XML, which I do know, but rather, how can I do something along the lines of this sample code?
(One View).add(Another View)
Like one can do in Swing.
Calling addView is the correct answer, but you need to do a little more than that to get it to work.
If you create a View via a constructor (e.g., Button myButton = new Button();), you'll need to call setLayoutParams on the newly constructed view, passing in an instance of the parent view's LayoutParams inner class, before you add your newly constructed child to the parent view.
For example, you might have the following code in your onCreate() function assuming your LinearLayout has id R.id.main:
LinearLayout myLayout = findViewById(R.id.main);
Button myButton = new Button(this);
myButton.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
myLayout.addView(myButton);
Making sure to set the LayoutParams is important. Every view needs at least a layout_width and a layout_height parameter. Also getting the right inner class is important. I struggled with getting Views added to a TableRow to display properly until I figured out that I wasn't passing an instance of TableRow.LayoutParams to the child view's setLayoutParams.
The best way I found is to use the inflate static method of View.
View inflatedView = View.inflate(context, yourViewXML, yourLinearLayout);
where yourViewXML is something like R.layout.myView
please notice that you need a ViewGroup in order to add a view (which is any layout you can think of)
so as an example lets say you have a fragment which it view already been inflated and you know that the root view is a layout, and you want to add a view to it:
View view = getView(); // returns base view of the fragment
if (view == null)
return;
if (!(view instanceof ViewGroup))
return;
ViewGroup viewGroup = (ViewGroup) view;
View popup = View.inflate(viewGroup.getContext(), R.layout.someView, viewGroup);
EDIT:
Kotlin code for the example above (view is the getView() of a fragment)
(view as? ViewGroup)?.let {
View.inflate(context, R.layout.add_credit_card, it)
}
To add the view programmatically, you can do:
LinearLayout rlmain = new LinearLayout(this);
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);
LinearLayout ll1 = new LinearLayout (this);
ImageView iv = new ImageView(this);
iv.setImageResource(R.drawable.logo);
LinearLayout .LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
iv.setLayoutParams(lp);
ll1.addView(iv);
rlmain.addView(ll1);
setContentView(rlmain, llp);
You can also add any number of views.
LinearLayout is a subclass of ViewGroup, which has a method called addView. The addView method should be what you are after.
The idea of programmatically setting constraints can be tiresome. This solution below will work for any layout whether constraint, linear, etc. Best way would be to set a placeholder i.e. a FrameLayout with proper constraints (or proper placing in other layout such as linear) at position where you would expect the programmatically created view to have.
All you need to do is inflate the view programmatically and it as a child to the FrameLayout by using addChild() method. Then during runtime your view would be inflated and placed in right position. Per Android recommendation, you should add only one childView to FrameLayout [link].
Here is what your code would look like, supposing you wish to create TextView programmatically at a particular position:
Step 1:
In your layout which would contain the view to be inflated, place a FrameLayout at the correct position and give it an id, say, "container".
Step 2
Create a layout with root element as the view you want to inflate during runtime, call the layout file as "textview.xml" :
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
</TextView>
BTW, set the layout-params of your frameLayout to wrap_content always else the frame layout will become as big as the parent i.e. the activity i.e the phone screen.
android:layout_width="wrap_content"
android:layout_height="wrap_content"
If not set, because a child view of the frame, by default, goes to left-top of the frame layout, hence your view will simply fly to left top of the screen.
Step 3
In your onCreate method, do this :
FrameLayout frameLayout = findViewById(R.id.container);
TextView textView = (TextView) View.inflate(this, R.layout.textview, null);
frameLayout.addView(textView);
(Note that setting last parameter of findViewById to null and adding view by calling addView() on container view (frameLayout) is same as simply attaching the inflated view by passing true in 3rd parameter of findViewById(). For more, see this.)
One more way to add view from Activity
ViewGroup rootLayout = findViewById(android.R.id.content);
rootLayout.addView(view);
You guys should also make sure that when you override onLayout you HAVE to call super.onLayout with all of the properties, or the view will not be inflated!