What is the use of LayoutInflater in Android?
The LayoutInflater class is used to instantiate the contents of layout XML files into their corresponding View objects.
In other words, it takes an XML file as input and builds the View objects from it.
What does LayoutInflator do?
When I first started Android programming, I was really confused by LayoutInflater and findViewById. Sometimes we used one and sometimes the other.
LayoutInflater is used to create a new View (or Layout) object from one of your xml layouts.
findViewById just gives you a reference to a view than has already been created. You might think that you haven't created any views yet, but whenever you call setContentView in onCreate, the activity's layout along with its subviews gets inflated (created) behind the scenes.
So if the view already exists, then use findViewById. If not, then create it with a LayoutInflater.
Example
Here is a mini project I made that shows both LayoutInflater and findViewById in action. With no special code, the layout looks like this.
The blue square is a custom layout inserted into the main layout with include (see here for more). It was inflated automatically because it is part of the content view. As you can see, there is nothing special about the code.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Now let's inflate (create) another copy of our custom layout and add it in.
LayoutInflater inflater = getLayoutInflater();
View myLayout = inflater.inflate(R.layout.my_layout, mainLayout, false);
To inflate the new view layout, all I did was tell the inflater the name of my xml file (my_layout), the parent layout that I want to add it to (mainLayout), and that I don't actually want to add it yet (false). (I could also set the parent to null, but then the layout parameters of my custom layout's root view would be ignored.)
Here it is again in context.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// inflate the main layout for the activity
setContentView(R.layout.activity_main);
// get a reference to the already created main layout
LinearLayout mainLayout = (LinearLayout) findViewById(R.id.activity_main_layout);
// inflate (create) another copy of our custom layout
LayoutInflater inflater = getLayoutInflater();
View myLayout = inflater.inflate(R.layout.my_layout, mainLayout, false);
// make changes to our custom layout and its subviews
myLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.colorAccent));
TextView textView = (TextView) myLayout.findViewById(R.id.textView);
textView.setText("New Layout");
// add our custom layout to the main layout
mainLayout.addView(myLayout);
}
}
Notice how findViewById is used only after a layout has already been inflated.
Supplemental Code
Here is the xml for the example above.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_main_layout"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<!-- Here is the inserted layout -->
<include layout="#layout/my_layout"/>
</LinearLayout>
my_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#color/colorPrimary">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:padding="5dp"
android:textColor="#android:color/white"
android:text="My Layout"/>
</RelativeLayout>
When do you need LayoutInflater
The most common time most people use it is in a RecyclerView. (See these RecyclerView examples for a list or a grid.) You have to inflate a new layout for every single visible item in the list or grid.
You also can use a layout inflater if you have a complex layout that you want to add programmatically (like we did in our example). You could do it all in code, but it is much easier to define it in xml first and then just inflate it.
When you use a custom view in a ListView you must define the row layout.
You create an xml where you place android widgets and then in the adapter's code you have to do something like this:
public MyAdapter(Context context, List<MyObject> objects) extends ArrayAdapter {
super(context, 1, objects);
/* We get the inflator in the constructor */
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
/* We inflate the xml which gives us a view */
view = mInflater.inflate(R.layout.my_list_custom_row, parent, false);
/* Get the item in the adapter */
MyObject myObject = getItem(position);
/* Get the widget with id name which is defined in the xml of the row */
TextView name = (TextView) view.findViewById(R.id.name);
/* Populate the row's xml with info from the item */
name.setText(myObject.getName());
/* Return the generated view */
return view;
}
Read more in the official documentation.
LayoutInflater.inflate() provides a means to convert a res/layout/*.xml file defining a view into an actual View object usable in your application source code.
basic two steps: get the inflater and then inflate the resource
How do you get the inflater?
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
How do you get the view assuming the xml file is "list_item.xml"?
View view = inflater.inflate(R.layout.list_item, parent, false);
Here is another example similar to the previous one, but extended to further demonstrate inflate parameters and dynamic behavior it can provide.
Suppose your ListView row layout can have variable number of TextViews. So first you inflate the base item View (just like the previous example), and then loop dynamically adding TextViews at run-time. Using android:layout_weight additionally aligns everything perfectly.
Here are the Layouts resources:
list_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/field1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"/>
<TextView
android:id="#+id/field2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
</LinearLayout>
schedule_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
Override getView method in extension of BaseAdapter class
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = activity.getLayoutInflater();
View lst_item_view = inflater.inflate(R.layout.list_layout, null);
TextView t1 = (TextView) lst_item_view.findViewById(R.id.field1);
TextView t2 = (TextView) lst_item_view.findViewById(R.id.field2);
t1.setText("some value");
t2.setText("another value");
// dinamically add TextViews for each item in ArrayList list_schedule
for(int i = 0; i < list_schedule.size(); i++){
View schedule_view = inflater.inflate(R.layout.schedule_layout, (ViewGroup) lst_item_view, false);
((TextView)schedule_view).setText(list_schedule.get(i));
((ViewGroup) lst_item_view).addView(schedule_view);
}
return lst_item_view;
}
Note different inflate method calls:
inflater.inflate(R.layout.list_layout, null); // no parent
inflater.inflate(R.layout.schedule_layout, (ViewGroup) lst_item_view, false); // with parent preserving LayoutParams
This class is used to instantiate layout XML file into its corresponding View objects. It is never be used directly -- use getLayoutInflater() or getSystemService(String) to retrieve a standard LayoutInflater instance that is already hooked up to the current context and correctly configured for the device you are running on. For example:
LayoutInflater inflater = (LayoutInflater)context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
Reference: http://developer.android.com/reference/android/view/LayoutInflater.html
LayoutInflater is a class used to instantiate layout XML file into its corresponding view objects which can be used in Java programs.
In simple terms, there are two ways to create UI in android. One is a static way and another is dynamic or programmatically.
Suppose we have a simple layout main.xml having one textview and one edittext as follows.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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/layout1"
>
<TextView
android:id="#+id/namelabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Enter your name"
android:textAppearance="?android:attr/textAppearanceLarge" >
</TextView>
<EditText
android:id="#+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginTop="14dp"
android:ems="10">
</EditText>
</LinearLayout>
We can display this layout in static way by
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
A dynamic way of creating a view means the view is not mentioned in our main.xml but we want to show with this in run time. For example, we have another XML in layout folder as footer.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/TextView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="Add your record"
android:textSize="24sp" >
</TextView>
We want to show this textbox in run time within our main UI. So here we will inflate text.xml. See how:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
TextView t = (TextView)inflater.inflate(R.layout.footer,null);
lLayout = (LinearLayout)findViewById(R.id.layout1);
lLayout.addView(t);
Here I have used getSystemService (String) to retrieve a LayoutInflater instance. I can use getLayoutInflator() too to inflate instead of using getSystemService (String) like below:
LayoutInflator inflater = getLayoutInflater();
TextView t = (TextView) inflater.inflate(R.layout.footer, null);
lLayout.addView(t);
Inflating means reading the XML file that describes a layout (or GUI element) and to create the actual objects that correspond to it, and thus make the object visible within an Android app.
final Dialog mDateTimeDialog = new Dialog(MainActivity.this);
// Inflate the root layout
final RelativeLayout mDateTimeDialogView = (RelativeLayout) getLayoutInflater().inflate(R.layout.date_time_dialog, null);
// Grab widget instance
final DateTimePicker mDateTimePicker = (DateTimePicker) mDateTimeDialogView.findViewById(R.id.DateTimePicker);
This file could saved as date_time_dialog.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/DateTimeDialog" android:layout_width="100px"
android:layout_height="wrap_content">
<com.dt.datetimepicker.DateTimePicker
android:id="#+id/DateTimePicker" android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<LinearLayout android:id="#+id/ControlButtons"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_below="#+id/DateTimePicker"
android:padding="5dip">
<Button android:id="#+id/SetDateTime" android:layout_width="0dip"
android:text="#android:string/ok" android:layout_weight="1"
android:layout_height="wrap_content"
/>
<Button android:id="#+id/ResetDateTime" android:layout_width="0dip"
android:text="Reset" android:layout_weight="1"
android:layout_height="wrap_content"
/>
<Button android:id="#+id/CancelDialog" android:layout_width="0dip"
android:text="#android:string/cancel" android:layout_weight="1"
android:layout_height="wrap_content"
/>
</LinearLayout>
This file could saved as date_time_picker.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content" `enter code here`
android:padding="5dip" android:id="#+id/DateTimePicker">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="true"
android:orientation="horizontal">
<LinearLayout
android:id="#+id/month_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="1dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="#+id/month_plus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="#drawable/image_button_up_final"/>
<EditText
android:id="#+id/month_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="#drawable/picker_middle"
android:focusable="false"
android:gravity="center"
android:singleLine="true"
android:textColor="#000000">
</EditText>
<Button
android:id="#+id/month_minus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="#drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
android:id="#+id/date_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0.5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="#+id/date_plus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="#drawable/image_button_up_final"/>
<EditText
android:id="#+id/date_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="#drawable/picker_middle"
android:gravity="center"
android:focusable="false"
android:inputType="number"
android:textColor="#000000"
android:singleLine="true"/>
<Button
android:id="#+id/date_minus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="#drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
android:id="#+id/year_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0.5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="#+id/year_plus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="#drawable/image_button_up_final"/>
<EditText
android:id="#+id/year_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="#drawable/picker_middle"
android:gravity="center"
android:focusable="false"
android:inputType="number"
android:textColor="#000000"
android:singleLine="true"/>
<Button
android:id="#+id/year_minus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="#drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
android:id="#+id/hour_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="#+id/hour_plus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="#drawable/image_button_up_final"/>
<EditText
android:id="#+id/hour_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="#drawable/picker_middle"
android:gravity="center"
android:focusable="false"
android:inputType="number"
android:textColor="#000000"
android:singleLine="true">
</EditText>
<Button
android:id="#+id/hour_minus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="#drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
android:id="#+id/min_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0.35dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="#+id/min_plus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="#drawable/image_button_up_final"/>
<EditText
android:id="#+id/min_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="#drawable/picker_middle"
android:gravity="center"
android:focusable="false"
android:inputType="number"
android:textColor="#000000"
android:singleLine="true"/>
<Button
android:id="#+id/min_minus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="#drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
android:id="#+id/meridiem_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0.35dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<ToggleButton
android:id="#+id/toggle_display"
style="#style/SpecialToggleButton"
android:layout_width="40dp"
android:layout_height="32dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="45dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:padding="5dp"
android:gravity="center"
android:textOn="#string/meridiem_AM"
android:textOff="#string/meridiem_PM"
android:checked="true"/>
<!-- android:checked="true" -->
</LinearLayout>
</LinearLayout>
</RelativeLayout>
The MainActivity class saved as MainActivity.java:
public class MainActivity extends Activity {
EditText editText;
Button button_click;
public static Activity me = null;
String meridiem;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText)findViewById(R.id.edittext1);
button_click = (Button)findViewById(R.id.button1);
button_click.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view){
final Dialog mDateTimeDialog = new Dialog(MainActivity.this);
final RelativeLayout mDateTimeDialogView = (RelativeLayout) getLayoutInflater().inflate(R.layout.date_time_dialog, null);
final DateTimePicker mDateTimePicker = (DateTimePicker) mDateTimeDialogView.findViewById(R.id.DateTimePicker);
// mDateTimePicker.setDateChangedListener();
((Button) mDateTimeDialogView.findViewById(R.id.SetDateTime)).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mDateTimePicker.clearFocus();
int hour = mDateTimePicker.getHour();
String result_string = mDateTimePicker.getMonth() +" "+ String.valueOf(mDateTimePicker.getDay()) + ", " + String.valueOf(mDateTimePicker.getYear())
+ " " +(mDateTimePicker.getHour()<=9? String.valueOf("0"+mDateTimePicker.getHour()) : String.valueOf(mDateTimePicker.getHour())) + ":" + (mDateTimePicker.getMinute()<=9?String.valueOf("0"+mDateTimePicker.getMinute()):String.valueOf(mDateTimePicker.getMinute()))+" "+mDateTimePicker.getMeridiem();
editText.setText(result_string);
mDateTimeDialog.dismiss();
}
});
// Cancel the dialog when the "Cancel" button is clicked
((Button) mDateTimeDialogView.findViewById(R.id.CancelDialog)).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
mDateTimeDialog.cancel();
}
});
// Reset Date and Time pickers when the "Reset" button is clicked
((Button) mDateTimeDialogView.findViewById(R.id.ResetDateTime)).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
mDateTimePicker.reset();
}
});
// Setup TimePicker
// No title on the dialog window
mDateTimeDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
// Set the dialog content view
mDateTimeDialog.setContentView(mDateTimeDialogView);
// Display the dialog
mDateTimeDialog.show();
}
});
}
}
What inflater does
It takes a xml layout as input (say) and converts it to View object.
Why needed
Let us think a scenario where we need to create a custom listview. Now each row should be custom. But how can we do it. Its not possible to assign a xml layout to a row of listview. So, we create a View object. Thus we can access the elements in it (textview,imageview etc) and also assign the object as row of listview
So, whenever we need to assign view type object somewhere and we have our custom xml design we just convert it to object by inflater and use it.
here is an example for geting a refrence for the root View of a layout ,
inflating it and using it with setContentView(View view)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater li=getLayoutInflater();
View rootView=li.inflate(R.layout.activity_main,null);
setContentView(rootView);
}
Layout inflater is a class that reads the xml appearance description and convert them into java based View objects.
LayoutInflater creates View objects based on layouts defined in XML. There are several different ways to use LayoutInflater, including creating custom Views, inflating Fragment views into Activity views, creating Dialogs, or simply inflating a layout file View into an Activity.
There are a lot of misconceptions about how the inflation process works. I think this comes from poor of the documentation for the inflate() method. If you want to learn about the inflate() method in detail, I wrote a blog post about it here:
https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/
my customize list hope it illustrate concept
public class second extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
// TextView textview=(TextView)findViewById(R.id.textView1);
// textview.setText(getIntent().getExtras().getString("value"));
setListAdapter(new MyAdapter(this,R.layout.list_item,R.id.textView1, getResources().getStringArray(R.array.counteries)));
}
private class MyAdapter extends ArrayAdapter<String>{
public MyAdapter(Context context, int resource, int textViewResourceId,
String[] objects) {
super(context, resource, textViewResourceId, objects);
// TODO Auto-generated constructor stub
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater=(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row=inflater.inflate(R.layout.list_item,parent,false);
String[]items=getResources().getStringArray(R.array.counteries);
ImageView iv=(ImageView) row.findViewById(R.id.imageView1);
TextView tv=(TextView) row.findViewById(R.id.textView1);
tv.setText(items[position]);
if(items[position].equals("unitedstates")){
iv.setImageResource(R.drawable.usa);
}else if(items[position].equals("Russia")){
iv.setImageResource(R.drawable.russia);
}else if(items[position].equals("Japan")){
iv.setImageResource(R.drawable.japan);
}
// TODO Auto-generated method stub
return row;
}
}
}
LayoutInflater is a fundamental component in Android. You must use it all the time to turn xml files into view hierarchies.
Inflater actually some sort of convert to data, views, instances, to visible UI representation.. ..thus it make use of data feed into from maybe adapters, etc. programmatically. then integrating it with an xml you defined, that tells it how the data should be represented in UI
Related
Upon clicking each TextView they should lead to another layout file to help the user learn about human trafficking. In the onCreate method I have setOnClickListener to my text view. Inflating it is an issue though. Is this called inflating a view? I've seen people recommending the use of fragments for this, using setContentView (from what I've found this shouldn't be used), and using the layout inflater while passing in the layout I want and null. However that doesn't work. How should this code look?
The XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.piatt.worksafe.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Work Safe!"
android:textSize="36sp"
android:layout_centerHorizontal="true"
android:paddingBottom="32dp"
android:id="#+id/title"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="What is Human Trafficing?"
android:layout_below="#+id/title"
android:layout_centerHorizontal="true"
android:textSize="24sp"
android:padding="16dp"
android:id="#+id/whatIsHumanTrafficing"
android:clickable="true"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="How do I get safe labor?"
android:layout_below="#+id/whatIsHumanTrafficing"
android:layout_centerHorizontal="true"
android:textSize="24sp"
android:padding="16dp"
android:id="#+id/howDoIGetSafeLabor"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="How do I check that my job / job offer is legal?"
android:layout_below="#+id/howDoIGetSafeLabor"
android:layout_centerHorizontal="true"
android:textSize="24sp"
android:padding="16dp"
android:gravity="center"
android:id="#+id/checkLegality"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="How can I get help?"
android:layout_below="#+id/checkLegality"
android:layout_centerHorizontal="true"
android:textSize="24sp"
android:padding="16dp"
android:id="#+id/getHelp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="About us"
android:layout_below="#+id/getHelp"
android:layout_centerHorizontal="true"
android:textSize="16sp"
android:layout_alignParentBottom="true"
android:gravity="bottom"
android:id="#+id/aboutUs"
/>
</RelativeLayout>
The java class:
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView whatIsHumanTrafficing = (TextView) findViewById(R.id.whatIsHumanTrafficing);
whatIsHumanTrafficing.setOnClickListener(new View.OnClickListener(){
public void onClick(View view){
//What is this context, why do I need it and where does it come from?
//What is the ViewGroup, why do I need it and where does it come from?
view.inflate(Context context, R.layout.what_is_human_trafficing, ViewGroup root);
}
});
}
Aside: You could read the documentation for View.inflate
What is this context, why do I need it and where does it come from?
What: YourActivity.this (replace with your actual class name)
Why: You need it as a parameter to inflate a View.
What is the ViewGroup, why do I need it and where does it come from?
You probably don't need it; it can be null. It is the ViewGroup to inflate the View into. Like for a ListView, you would load each row into the list as the "group".
Anyways, if you want to dynamically show different layout file based upon what is clicked, yes Fragment's are one way to do that, and so are ViewStub's.
And you aren't actually calling inflate on the TextView because it is a static method. It is equivalent to doing this with a LayoutInflater
View v = LayoutInflater.from(YourActivity.this).inflate(R.layout.your_layout, null);
// TODO: Do something with v
The final code should look like:
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final RelativeLayout rl = (RelativeLayout) findViewById(R.id.splashScreenId);
TextView whatIsHumanTrafficing = (TextView) findViewById(R.id.whatIsHumanTrafficing);
whatIsHumanTrafficing.setOnClickListener(new View.OnClickListener(){
public void onClick(View view){
MainActivity.this.setContentView(R.layout.what_is_human_trafficing);
}
});
}
Set an on click listener to the text view then within it on MainActivity.this set the content view to the layout you want.
I'm beginner in android development and i a have question about Listview and android:onclick attribute.
I try to use attribute android:onclick ="myMethod" on each element of my listview instead of define OnItemClickListener/onItemClick (too much verbose for me)
MyMethod is executed but how can i get clicked element (current context) ?
Thanks in advance
As a beginner, setting an OnItemClickListener might seem a bit scary, but it's really not a big deal at all (and a core concept you should be learning anyway!).
So if you have a simple layout with a ListView in it like this...
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/containerView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/myListview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
You can set up an OnItemClickListener with just this code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_listview_layout);
listView = (ListView)findViewById(R.id.myListview);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Every time an item is clicked, you can handle it right here.
}
});
}
So every time an item in your list is clicked, the onItemClick method is fired, and you can figure out which item was clicked by using the int position argument that comes in.
If i am right your question is about implementing on click listener on each listrow item instead of list row.
If that is correct this is how you should implement:
1.In your adapter of getView() method you might be inflating a layout for list row like below:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_row_layout, parent, false);
return convertView;
}
In the above code list_row_layout is the xml file i'm inflating.
Go to that layout and add the following line android:descendantFocusability="blocksDescendants" to the root level of the xml layout like below:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_margin="4dp"
android:descendantFocusability="blocksDescendants"<!--This is the line i'm talking about-->
android:background="#drawable/rounded_border_layout"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:layout_width="40dp"
android:layout_marginRight="10dp"
android:id="#+id/review_main_user_image_layout"
android:layout_marginLeft="10dp"
android:layout_height="54dp">
<ImageView
android:layout_width="40dp"
android:id="#+id/review_main_user_image"
android:background="#drawable/reviews_x_trail_user_image_border"
android:layout_height="40dp"
android:src="#drawable/ic_help_user" />
<TextView
android:typeface="monospace"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Me"
android:textSize="10sp"
android:layout_gravity="center"
android:singleLine="true"
android:id="#+id/review_main_user_name"
android:layout_below="#+id/review_main_user_image" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/review_main_user_image_layout"
android:layout_toEndOf="#+id/review_main_user_image_layout">
<TextView
android:layout_marginLeft="8dp"
android:layout_width="wrap_content"
android:textColor="#color/black"
android:layout_height="wrap_content"
android:singleLine="true"
android:id="#+id/review_main_title"
android:text="Good Product For The Price"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:orientation="horizontal">
<RatingBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/review_main_rating"
android:progressDrawable="#drawable/apptheme_ratingbar_small_holo_light"
android:numStars="5"
style="?android:attr/ratingBarStyleSmall" />
<TextView
android:layout_marginLeft="8dp"
android:text="12-Jun-1993"
android:id="#+id/review_main_date"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
That't it now in your adapter getView method you can implement on click listener for each widget you have in that layout.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ReviewsXTrailViewHolder reviewsXTrailViewHolder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_row_review_main, parent, false);
TextView title = (TextView)convertView.findViewById(R.id.review_main_user_image);
//title.setOnclickListener()
return convertView;
}
In that above code i have added on click listener for textview.I hope it will work
Comment below if that doesn't work
I'm stumped. This one IS simple and I'm missing something simple but I'm just not getting anywhere.
I have a ListView that contains pretty simple items - TextView's that contain text of the form "N. name", where N is the position in the list and name is the name of the associated objects. I've created a ListAdapter that presents that information into the ListView.
The presentation stuff seems to work fine. It's the part where when I tap on a row that's not working. I just don't get a notification. If I set a onClickListener on the item (when it's generated in the Adapter) I do get a notification, but it's convoluted to make that work the way I'd like it to. I've tried a bunch of stuff - changing descendent focusability, enabling, disabling, setting itemsCanFocus to false, ... - but no luck on any of them.
I've included relevant code for configuring the view and the elements in the ListView.
In particular, what I'm trying to do is get that OnItemClickLister.onItemClick() to get invoked when I tap on a row. Any thoughts on what I'm doing wrong?
Activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model = FZMModel.getInstance(this);
setContentView(R.layout.activity_deploy);
TextView viewTitle = (TextView) findViewById(R.id.deploy_header);
if (model.getProfiles().size() == 0) {
viewTitle.setText(R.string.deploy_header_create);
} else {
viewTitle.setText(R.string.deploy_header_choose);
}
profileListView = (ListView) findViewById(R.id.profileListView);
profileListAdapter = new ProfileListAdapter(this, model);
profileListView.setAdapter(profileListAdapter);
profileListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Log.d(TAG, String.format("Item %d selected (with id=0x%x)", position, id));
}
});
}
Adapter:
... relevant code from getView():
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final Profile profile = model.getProfileAtIndex(position);
final int rowNum = position;
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.profile_list_layout, parent, false);
}
TextView profileIndexView;
TextView profileNameView;
profileIndexView = (TextView) convertView.findViewById(R.id.profileIndexLabel);
profileNameView = (TextView) convertView.findViewById(R.id.profileNameLabel);
profileIndexView.setText(String.format("%d.", position));
profileNameView.setText(profile.getName());
// convertView.setOnClickListener(new View.OnClickListener() {
// #Override
// public void onClick(View view) {
// Toast.makeText(context, String.format("Did select row #%d (index=%d)",rowNum, profile.getPosition()), Toast.LENGTH_SHORT).show();
// }
// });
return convertView;
}
activity layout:
<RelativeLayout 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"
tools:context="com.nsn.flexizonemobile.FZMConcreteActionDeploy"
tools:ignore="MergeRootFrame" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="#string/deploy_header_choose"
android:id="#+id/deploy_header"
android:layout_margin="10dp"
android:layout_centerHorizontal="true" />
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/profileListView"
android:layout_gravity="left|top"
android:layout_alignParentLeft="true"
android:layout_marginLeft="0dp"
android:choiceMode="none"
android:layout_below="#+id/deploy_header"
android:divider="#android:color/darker_gray"
android:dividerHeight="2dp"
android:clickable="true"
android:descendantFocusability="beforeDescendants" />
</RelativeLayout>
profile_list_layout layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="#dimen/profile_index_width"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="A. "
android:id="#+id/profileIndexLabel"
android:gravity="center_vertical|right"
android:layout_centerVertical="true"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:textSize="24sp"
android:textIsSelectable="true"
android:layout_alignParentStart="false"
android:layout_alignParentTop="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Profile Name"
android:id="#+id/profileNameLabel"
android:layout_alignParentLeft="false"
android:layout_alignParentTop="false"
android:gravity="center_vertical"
android:layout_toRightOf="#+id/profileIndexLabel"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:textSize="24sp"
android:paddingTop="10dp"
android:paddingBottom="10dp" />
</RelativeLayout>
in the textview of your inflator layout just add:
android:focusable="false"
android:focusableInTouchMode="false"
and in parent layout of your inflator i.e in relative layout of inflator add:
android:descendantFocusability="blocksDescendants"
remove :
android:descendantFocusability="beforeDescendants"
from your listview. and set height of your listview to match_parent will solve your issue.
remove following attributes from your ListView:
android:choiceMode="none"
android:clickable="true"
android:descendantFocusability="beforeDescendants"
also
android:layout_width="wrap_content"
android:layout_height="wrap_content"
makes no sense in this context (especially height)
I have design like this
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.20"
android:orientation="horizontal" >
<Button
android:id="#+id/backbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Back" />
<Button
android:id="#+id/nextbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="next" />
</LinearLayout>
<!-- the two columns part -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="0.80"
android:orientation="horizontal" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="0.80"
android:id="#+id/submenue"
>
<!-- this will be the menue list -->
<ListView
android:id="#+id/MyHiddenListView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
>
</ListView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/contents"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="First Name" />
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="0.20"
android:id="#+id/mainLayout"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="second Name" />
</LinearLayout>
</LinearLayout>
I added the following code to the next button such that it display and fill the list
this.next = (Button)this.findViewById(R.id.nextbutton);
this.next.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String[] MainMenue = new String[] { "aaaa", "bbb", "ccc"};
menueview = (ListView)findViewById(R.id.MyHiddenListView);
menueview.setVisibility(ListView.VISIBLE);
menueview.setAdapter(new submenueadapter(getApplicationContext(), MainMenue));
}
});
and the adaptor class is
package com.appnetics;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class submenueadapter extends ArrayAdapter<String> {
private final Context context;
private final String[] values;
public submenueadapter(Context context,String[] objects)
{
super(context, R.layout.main, objects);
this.context = context;
this.values = objects;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.main, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.contents);
textView.setText(values[position]);
// Change icon based on name
String s = values[position];
System.out.println(s);
return rowView;
}
}
the problem is that the list be populated with the array plus the other controls in the page (the 2 buttons )
the layout before clicking next
the layout after clicking
any idea to fix that please
Best regards
Best regards
The main problem is that you are including everything in one main.xml layout.
And due to this problem, you are getting back/next button for every listitem (Actually whole layout is being repeating as Listitem).
Soluition:
Instead, Try to define separate layout for the ListItem and inflate that layout inside the getView() method. so there must be 2 XML layouts file, one is having main design with ListView only, and another one with only views that you want for every list item.
for example, (1) main.xml (2) row_item.xml
Now, you just need to make correction in code of inflating layout:
View rowView = inflater.inflate(R.layout.row_item, parent, false); // row_item.xml is inflated here
ViewGroup class do offers various methods to add view anywhere and using LayoutParams classes you can pass the various parent container class specific attributes to applied over the child view to be added in the container.
That you can google and is easily doable.
I can also think of putting a ListView in the XML with the Visibility GONE.
And on specific action trigger make it visible. That will prevent me doing various programing stuff required to add view at a perticular position.
And i also don't feel any harm of this approach.
e.g
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="#+id/backbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Back" />
<ListView
android:id="#+id/MyHiddenListView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
</Linearlayout>
In the .java file
btnBack = (Button)findViewById(R.id.backbutton);
myListView = (ListView)findViewById(R.id.MyHiddenListView);
btnBack.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
myListView.setVisibility(ListView.VISIBLE);
myListView.setAdaptor(new MyListViewAdaptor());
}
});
Hope it helps :)
I'm trying to get a reference to an ImageView object and for whatever reason, it keeps coming back as null.
XML:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="6dip">
<ImageView android:id="#+id/application_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" />
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="#+id/label" android:text="Application Name" />
<CheckBox android:id="#+id/check" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" />
</LinearLayout>
Java:
ImageView img = (ImageView) v.findViewById(R.id.application_icon);
I don't feel like I'm doing anything wrong yet my img var always comes back as null. What's wrong with this picture?
Sat's answer is correct, i.e., you need a proper layout, but setContentView() is not the only way to reference a View. You can use a LayoutInflater to inflate a parent layout of the View (even if it is not shown) and use that newly inflated layout to reference the View.
public class MyActivity extends Activity {
Context context;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
// the rest of yout code
private void someCallback() {
LayoutInflater inflater = (LayoutInflater) context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout ll = (LinearLayout) inflater.inflate(R.layout.iconLayout, null);
ImageView img = (ImageView) ll.findViewById(R.id.application_icon);
// you can do whatever you need with the img (get the Bitmap, maybe?)
The only change you need to your xml file is to add an ID to the parent layout, so you can use it with the LayoutInflater:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="iconLayout"
<!-- all the rest of your layout -->
<ImageView android:id="#+id/application_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" />
<!-- all the rest of your layout -->
</LinearLayout>
When you are referencing the imageView , make sure that you are using the proper layout, i.e. setContentView(R.layout.yourIntendedXmlLayout);
That xml should contain your imageView. Then you can refer to your imageView.
use
ImageView img = (ImageView)findViewById(R.id.application_icon);