Can I convert a View to Layout? - java

In android, one can Inflate a Layout file and will get a View in return.
For Example:
LayoutInflater layoutInflater = LayoutInflater.from(context);
View myView = layoutInflater.inflate(R.layout.example_layout, null);
But I'm trying if I can get a Layout back from that inflated layout which is now a View?
Something by which I can retrieve back the original Layout from the Inflated View.

LayoutInflater layoutInflater = LayoutInflater.from(context);
LinearLayout myView = (LinearLayout)layoutInflater.inflate(R.layout.example_layout, null);
That's it!
Just be sure that the root view in your layout.example_layout is a LinearLayout or whatever layout you desire. Otherwise you'll have a ClassCastException
Every layout or ViewGroup extends View, that's why the inflate method returns a View, it's up to you then performing the right cast.

Consider the layout below. It has a text view only.
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/mediumTextSize"
android:textColor="#color/black_text_color"
/>
After inflation you can directly get the textView as its the only view contain in layout.
LayoutInflater inflater=LayoutInflater.from(this);
TextView view=(TextView)inflater.inflate(R.layout.temp,null);
Now consider the layout below .
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/txtName"
android:layout_width="match_parent"
android:layout_height="40dp"
android:textColor="#color/black_text_color"
android:textSize="#dimen/largeTExtSize" />
<TextView
android:id="#+id/csvName"
android:layout_width="match_parent"
android:layout_height="40dp"
android:textColor="#color/black_text_color"
android:textSize="#dimen/largeTExtSize" />
</LinearLayout>
On inflation.
LayoutInflater inflater=LayoutInflater.from(this);
View view=inflater.inflate(R.layout.temp,null);
//Or you can do
// LinearLayout view=(LinearLayout)inflater.inflate(R.layout.temp,null);
TextView txt=view.findViewById(R.id.txtId);

Related

Incorrect displaying FrameLayout item in listview

FrameLayout for some reason doesn't work perfectly in listview. I got this incorrect displaying in emulator. In Android Studio items looks nicely. Please help me :)
In Android Studio
In emulator
item.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp"
android:padding="10dp">
<TextView
android:id="#+id/txtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Title"
android:layout_gravity="center"
android:textSize="27sp"
android:textStyle="bold"/>
<TextView
android:id="#+id/txtGenre"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Genre"
android:layout_gravity="bottom|right"
android:textSize="18sp"
android:textStyle="italic"/>
<TextView
android:id="#+id/txtId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ID"
android:textSize="18sp"
android:textStyle="italic"
android:layout_gravity="bottom|left"/>
</FrameLayout>
Adapter code
public class MyFilmListAdapter extends ArrayAdapter<Film> {
Context context;
ArrayList<Film> films;
public MyFilmListAdapter(#NonNull Context context, ArrayList<Film> films) {
super(context, R.layout.item_film, films);
this.context = context;
this.films = films;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
Film f = films.get(position);
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.item_film, null, false);
TextView name = v.findViewById(R.id.txtName);
TextView genre = v.findViewById(R.id.txtGenre);
TextView id = v.findViewById(R.id.txtId);
name.setText(f.getName() + "");
genre.setText(f.getGenre() + "");
id.setText(f.getId() + "");
return v;
}
}
I tried to use LinerLayout and it has correct displaying, however I need FrameLayout.
According to the official documentation
FrameLayout is designed to block out an area on the screen to display a single item. Generally, FrameLayout should be used to hold a single child view, because it can be difficult to organise child views in a way that's scalable to different screen sizes without the children overlapping each other.
You can, however, add multiple children to a FrameLayout and control their position within the FrameLayout by assigning gravity to each child, using the android:layout_gravity attribute.
So you can use LinearLayout inside it.
and nowadays better is you should use Recyclerview with ConstraintLayout

Spinner is not seen properly

I have two spinner. They look like that. I don't know why dropdown menu icon is far away from texts.
(Chagned image after gravity attribute is set to "end")
In my activity_main.xml it is written:
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/map_root_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:background="#mipmap/map_bg"
android:orientation="vertical"
app:layoutDescription="#xml/map_scroll">
<FrameLayout
android:id="#+id/map_top_panel_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#mipmap/home_top"
android:orientation="vertical"
android:padding="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Spinner
android:id="#+id/map_spinner_sector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:gravity="end"/>
<Spinner
android:id="#+id/map_spinner_sorting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:gravity="end"/>
</FrameLayout>
...
</androidx.constraintlayout.motion.widget.MotionLayout>
SpinnerAdapter.java class:
public class SpinnerAdapter extends ArrayAdapter<String> {
public SpinnerAdapter(#NonNull Context context, ArrayList<String> items) {
super(context,0, items);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
return initView(position, convertView, parent);
}
#Override
public View getDropDownView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
return initView(position, convertView, parent);
}
private View initView(int position, View convertView, ViewGroup parent){
if (convertView == null){
convertView = LayoutInflater.from(getContext()).inflate(
R.layout.spinner_item, parent, false
);
}
TextView spinnerTextView = (TextView) convertView;
spinnerTextView.setText(getItem(position));
spinnerTextView.setGravity(Gravity.END); //This line is added later
return convertView;
}
}
and spinner_item.xml file, which is the layout of spinner items:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Spinner
android:id="#+id/my_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
I am not experienced with Spinners. I am learning. I wonder why i encountered such a bug.
Not: I have EDITED the spinner_item.xml file :
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/spinner_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:background="#drawable/suggestions_bg"
android:textColor="#color/blue_popular" />
I just had a similar problem, to solve this I had to set the attribute gravity in spinner.
android:gravity="end" - this helps to display items next to the dropdown icon.
Next, I had to override getDropDownView in my adapter class in this way:
public View getDropDownView(int position, View convertView,ViewGroup parent)
{
View v = super.getDropDownView(position, convertView,parent);
((TextView) v).setGravity(Gravity.END);
return v;
}
This helps to display items next to the dropdown icon when Spinner is expanded. Your spinner_item is also TextView so I think You can just copy and paste this function.
Your spinner_item.xml file shouldn't again contain Spinner, just a TextView would be enough but if you want a fancy layout, you can other widgets such ImageView. The following is the example of the simplest spinner_item.xml file.
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/custom_text_1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:textAlignment="inherit" />
Now, get rid of implementation of SpinnerAdapter class.
We can use ArrayAdapter as adapter of Spinner like this :
// bind your spinner layout from file to a spinner object
Spinner spinner = findViewById(R.id.map_spinner_sector);
// string array which is the content of the spinner
// if you already have array or list object, then this
// is not needed.
ArrayList<String> spinnerStringArray = ...; // populate the array backing your adapter
// if you have string array resources in file,
// use ArrayAdapter.createFromResource() method to get your array adapter
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this,
R.layout.spinner_item, spinnerStringArray);
spinner.setAdapter(spinnerAdapter);
// set listener to handle item selected event
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.d("Item Selected : ", spinnerStringArray[position]);
}
public void onNothingSelected(AdapterView<?> parent) {
}
});

Custom adapter won't inflate rows in list view

I have created a custom listview and a custom adapter. However, when I show the activity it appears empty (although I made sure and there are people in the array passed to the adapter).
1) Why won't it show the people list? Is there something wrong in my getView or in my onCreate function?
2) How can I make a list view that is surrounded by another view (searchbar on top list at the bottom)?
Here is the adapters getView function:
#Override
public View getView(int postion, View convertView, ViewGroup parent)
{
View rowView = convertView;
if (rowView == null)//set the convert view and the viewholder
{
LayoutInflater inflater = _context.getLayoutInflater();
rowView = inflater.inflate(_layoutResourceId, null,false);
ViewHolder viewHolder = new ViewHolder();
viewHolder._personName = (LargeTest) rowView.findViewById(R.id.personName);
viewHolder._personBirthDate = (TextView) rowView.findViewById(R.id.personBirthDate);
viewHolder._icon = (ImageView) rowView.findViewById(R.id.personPic);
rowView.setTag(viewHolder);
}
ViewHolder holder = (ViewHolder) rowView.getTag();
Person person=_persons.get(postion);//get current person for the list row
String personName = person.get_firstName()+" "+person.get_lastName();
((TextView) holder._personName).setText(personName);
String birthDate=person.get_birthDate()+";"+person.get_hebBirthDate();
holder._personBirthDate.setText(birthDate);
//TODO change icon to a real image for each Person
holder._icon.setImageResource(R.drawable.about_me);//test icon
return rowView;
}
Here is the listview onCreate function:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//TODO remove the test case
//addTestPersons();//add a test case
//setContentView(R.layout.person_list_activity);
PersonDbHelper dbHelper=new PersonDbHelper(this);
ArrayList<Person> persons =dbHelper.getAllPeopleAsPersonList();//get list to display
PersonListAdapter adapter=new PersonListAdapter(this, R.layout.person_list_row, persons);
setListAdapter(adapter);
}
And the XML for list_row:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<ImageView
android:id="#+id/personPic"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/about_me" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/personName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Person Name"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/personBirthDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1990-2001" />
</LinearLayout>
</LinearLayout>
Implement the getCount method in the adapter:
public int getCount(){
return _persons.size();
}
For the second part, add the headerview, create an XML layout for the view that you want to show on top of listview. Inflate it and add as headerview to your listview:
LayoutInflater inflater = this.getLayoutInflater();
View headerView = inflater.inflate(R.layout.header_view, null,false);
getListView().addHeaderView(headerView,null,false);
Because of the naming of the layout, you are passing "R.layout.person_list_row" to your adapter. I assume that you are passing the layout for one item in the array on which the adapter operates on instead of passing the ListView.
The constructor needs the ListView to be passed while in its getView, the layout for the row is constructed (inflated).

How to stretch image of Spinner?

I have a Spinner with only image inside.
Can I stretch the image all over the spinner?
row.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/country_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/image"/>
</LinearLayout>
CustomAdapter
public View getCustomView(int position, View convertView,ViewGroup parent)
{
LayoutInflater inflater = (LayoutInflater) m_Contex.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.row, parent, false);
ImageView icon = (ImageView) row.findViewById(R.id.country_icon);
icon.setImageResource(m_CountryImages.get(position));
return row;
}
Try this instead:
<ImageView
android:id="#+id/country_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/image"/>
If its API 7 or lower use fill_parent instead match_parent. Also make sure, that the icon is properly stretched inside itself, and there is no unnecessary transparent bacground that makes icon larger than you actually need
If you use
android:scaleType="fitXY"
your image will stretch over the entire display area.

android Toast and View help

I am trying to create a Helper class to display Toasts in my android app, as follows.
public class ToastHelper{
final static Toast toastAlert(String msg) {
LayoutInflater inflater = LayoutInflater.from(Main.self.getApplicationContext());
View layout = inflater.inflate(R.layout.toast_layout, (ViewGroup) findViewById(R.id.toast_layout_root));
TextView tv = (TextView)layout.findViewById(R.id.toast_text);
tv.setText(msg);
Toast toast = new Toast(Main.self.getApplicationContext());
toast.setDuration(Toast.LENGTH_SHORT);
toast.setView(layout);
return toast;
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toast_layout_root"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip"
android:background="#FFF"
>
<TextView android:id="#+id/toast_text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="#000"
/>
My code is based on the example at: http://developer.android.com/guide/topics/ui/notifiers/toasts.html
My problem is, when I try to inflate the view, I can't call findViewById without the View from the activity I am calling toastAlert in. Is there a way I can access that view?
My only thought would be to pass a View into the method. It wouldn't be so bad, the all would look like this:
class.toastAlert(this, "My Toast");
I use this to get the LayoutInflator
LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE);
I don't know if that will help or not.

Categories