Android Layout - list within a list - android

I am new to Android and need help in creating the following layout:
I've gone through the example of using ListFragment and ArrayAdapter but in this scenario, I want to display a list within a list. How would I create a layout like this?

You can use the ExpandableListView for this. The ExpandableListView is a List within a List:
http://developer.android.com/reference/android/widget/ExpandableListView.html
Here is a nice tutorial which explains how to use it:
http://www.androidhive.info/2013/07/android-expandable-list-view-tutorial/

You don't necessarily need a list within a list for this. You can as well use a TableLayout and modify the TableRow elements according to your requirement. Infact, I would highly recommend it. Check out this link for an example :
http://code.tutsplus.com/tutorials/android-user-interface-design-table-layouts--mobile-4788
Cheers !

For your design, you don't need to use ListView in ListView. Just use two different custom layout for ListView. One for title and other for subject data.
example:
for title layout
<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/title1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
for data layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="#+id/tv2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:id="#+id/tv3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:id="#+id/tv4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:id="#+id/tv5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
in your getView() from Adapter,
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Context context;
if(object.isTitle() == true){
convertView = mInflater.inflate(R.layout.title_layout, null);
//implement title layout
}
else{
convertView = mInflater.inflate(R.layout.data_layout, null);
//implement data layout
}
return convertView;
}
Hope this can help you.

Related

Display many views efficiently in a FlexboxLayout

My goal is to efficiently display a lot of TextViews (with background) in a FlexboxLayout (or something similar).
I want to display information about actors and crew members from a movie in a kind of 'tag'-layout style
How the layout looks like (one of the FlexboxLayouts is marked)
I inflate the TextViews dynamically via LayoutInflater into a FlexboxLayout. The problem is of course that with a lot of data (which means a lot of views, sometimes 30 or more in over 20 Flexbox-Layouts) the creation time of my fragment/activity increases and the activtiy takes longer to open.
The TextView I inflate:
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tag_name"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_margin="5dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:gravity="center_vertical"
android:background="#drawable/bg_tag"
android:textColor="?android:textColorSecondary"
android:text="#string/placeholder" />
My container layout (TextViews get inflated into the FlexboxLayout #+id/fxl_names):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/txt_names"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/colorOnBackground"
android:padding="5dp"
android:textSize="16sp"
android:textStyle="bold"
android:text="test" />
//TextViews get inflated into this FlexboxLayout
<com.google.android.flexbox.FlexboxLayout
android:id="#+id/fxl_names"
app:flexWrap="wrap"
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/view_more"
android:visibility="gone"
android:layout_margin="0dp"
android:text="Show all"
style="#style/Widget.MaterialComponents.Button.TextButton.Dialog" />
</LinearLayout>
Thank you for any help/advice on optimizing this layout!
When you had to inflate a lot of views dynamically, you should use something called ViewHolder to ensure the optimization of the inflate view action.
For your problem may you had to use a RecyclerView instead a FlexBoxLayout, the best solution in my opinion. And a FlexBoxLayoutManager to organize your views.
There is a example in the Android FlexBoxLayout repository

How to add dynamic row Item in activity and able to access its ids?

My requirement is: After click on + icon , a new row should add dynamically and able to access its ids. Please give suggestions to implement it.
The easiest way to do this would be to display the items in a ListView/RecyclerView and simply add the new item into adapter and let the adapter handle adding the new row Item. You don't have to care about the items id and can simply use the adapters position as an id.
When you create a view programmatically, you can assign the View id by calling View.setID(), which can be any int (it must be unique). I wouldn't recommend this approach because it'll get very tedious to track the id's and the data the items contains. Using RecyclerView/ListView elevates this problem by separating the data from the presentation layers.
This is the code to add new row dynamically, but not able to create new ids
public void onAddField(View v) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View rowView = inflater.inflate(R.layout.field, null);
// Add the new row before the add field button.
parentLinearLayout.addView(rowView, parentLinearLayout.getChildCount() - 6);
}
in field.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="50dp"
android:orientation="horizontal" >
<EditText
android:id="#+id/grid_Itemcode"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:inputType="textPhonetic"
android:hint="Code" />
<EditText
android:id="#+id/grid_itemdesc"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="5"
android:inputType="textPersonName"
android:hint="Description" />
<EditText
android:id="#+id/grid_itemQty"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:inputType="phone"
android:hint="Qty" />
<EditText
android:id="#+id/grid_itemRate"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:inputType="phone"
android:hint="Rate" />
<Button
android:id="#+id/delete_button"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="1"
android:background="#android:drawable/ic_delete"
android:onClick="onDelete"/>
</LinearLayout>

ScrollView makes content disappear

I am trying to put a custom listView into a scrollView and when I scroll down and up I lose the top items in the listView which are a TextView and a CheckBox for some reason.
Here's my code:
activity_program.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/tv_program_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.10"
android:text="Program name"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/tv_program_info"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_weight="0.20"
android:text="program info, talk abt sets, reps, weight etc..." />
<ListView
android:id="#+id/android:list"
android:layout_width="match_parent"
android:layout_height="395dp" >
</ListView>
<Button
android:id="#+id/bt_savework"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.10"
android:text="Save Workout" />
</LinearLayout>
My custom listView contains these:
<?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"
android:padding="5dp" >
<TextView
android:id="#+id/tv_exercice_title"
android:layout_width="270dp"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/cb_exercicedone"
android:layout_alignParentTop="true"
android:gravity="center_vertical"
android:text="Exercice title"
android:textAppearance="?android:attr/textAppearanceMedium" />
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_below="#+id/tv_exercice_title"
android:orientation="horizontal" >
<CheckBox
android:id="#+id/cb_setdone"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="7dp"
android:text="Set" />
<TextView
android:id="#+id/tv_set_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="3dp"
android:text="1" />
<TextView
android:id="#+id/tv_reps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:text="Reps x" />
<EditText
android:id="#+id/et_reps_number"
android:layout_width="47dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number" />
<TextView
android:id="#+id/tv_weight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:text="Weight" />
<EditText
android:id="#+id/et_weight_number"
android:layout_width="65dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number" />
<TextView
android:id="#+id/tv_kgorlbs"
android:layout_width="59dp"
android:layout_height="wrap_content"
android:text="kg/lbs"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<CheckBox
android:id="#+id/cb_exercicedone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignRight="#+id/linearLayout1" />
</RelativeLayout>
In my ListActivity I use a custom adapter to fill the ListView with the above template and only edit the tv_set_number (for now) then set the tv_exercice_title's visibility to "gone" to add more sets.
If you think the problem could be in my java code let me know in the comment and I will post it.
Please tell me what's the problem.
Here's some screenshots:
Before I scroll:
image 1
After I scroll:
image 2
Seems to me you are using the ListView to generate different kinds of rows and you're missing some steps. You could also consider to rethink the structure, as maybe this would better fit into a ExpandableListView: from the screenshots you post seems like you'd have a set of rows that hierarchically belong to a group view.
The ExpandableListView would fit this purpose, and also allow to collapse/expand the groups. I'd take a look at it, it's really easy, you'd only have to make the adapter descend from ExpandableListViewAdapter and provide methods to obtain the Group views (Your title & checkbox) and the item views (the sets with reps, weight, etc...)
If, on the contrary, you want to make it with a ListView, there are some issues to care about (I'll call TITLE ROWS to those with the title & checkbox, and regular rows to the regular ones)
What is happening now is, when you create a view and this view is not a TITLE ROW, you are setting the visibility of the title to GONE. But if you scroll, ie., DOWN and a TITLE row has to appear from the upper edge, the View you are given to recycle is the one that just left the screen by the lower edge, that was probably a REGULAR ROW. So in getView() you not only have to set Visibility to GONE for regular rows, but also back to VISIBLE for Title Rows. Google an explanation on how View recycling works for ListView and you'll understand it right away.
ListView provides a mechanism to help in these cases: The View Types:
You declare 2 "row types" overriding getViewTypeCount() and getItemViewType(int position) in your adapter. Type 0 will be TITLE ROWS, and Type 1 would be REGULAR ROWS.
In getView / convertView you'll generate / reuse the 2 different views separately based on the type.
.
#Override
public int getViewTypeCount() {
return 2; // you have 2 different types
}
#Override
public int getItemViewType(int position) {
if (position IS A TITLE ROW) return 0; else return 1;
}
... and then in getView() {
if (getItemViewType(position) == 0) {
// it's a TITLE ROW, create / reuse it accordingly
} else {
// it's a REGULAR ROW, create / reuse it accordingly
}
This has the advantage that ListView does some of the dirty work for you, so you'll be given the correct view type to recycle.

EditText steals focus from other EditTexts inside ListView

I have a stand-alone EditText and a ListView. Each item in the ListView also has two EditText fields. When I touch inside the ListView EditText, the stand-alone EditText steals the focus. This makes it impossible to edit any of the ListView EditText fields.
Name steals the focus from the other TextView elements inside the ListView
Here is the activity's XML, containing the stand-alone EditText and the ListView
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dip"
android:orientation = "vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dip" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dip"
android:layout_weight="1"
android:text="#string/name"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="#+id/editblindschedule_name"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="5"
android:ems="10"
android:inputType="text" />
</LinearLayout>
<ListView
android:id="#+id/listview_editblindschedule"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
And here is the ListView row 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="match_parent" >
<TextView
android:id="#+id/editblindschedule_round"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"/>
<EditText
android:id="#+id/editblindschedule_small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="#string/small"
android:ems="4"
android:inputType="number"
android:layout_weight="4"
android:layout_marginRight="10dip"
android:text="#string/integer_zero"
android:gravity="center" />
<EditText
android:id="#+id/editblindschedule_big"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="#string/big"
android:ems="4"
android:inputType="number"
android:layout_weight="4"
android:layout_marginRight="10dip"
android:paddingRight="6dip"
android:text="#string/integer_zero"
android:gravity="center" />
<CheckBox
android:id="#+id/editblindschedule_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true" />
</LinearLayout>
Here is the Java code
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_blind_schedule);
...
adapter = new BlindAdapter(this, blindSchedule.getBlindLevels());
listView = (ListView) findViewById(R.id.listview_editblindschedule);
listView.setAdapter(adapter);
And finally, the adapter:
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.listview_editblindschedule, parent, false);
if (!creating) { // Set default values.
TextView round = (TextView) row.findViewById(R.id.editblindschedule_round);
EditText small = (EditText) row.findViewById(R.id.editblindschedule_small);
EditText big = (EditText) row.findViewById(R.id.editblindschedule_big);
round.setText("" + (position + 1));
small.setText("" + blindLevels.get(position).getSmallBlind());
big.setText("" + blindLevels.get(position).getBigBlind());
}
return row;
}
The solution that worked for me was to put android:windowSoftInputMode="adjustPan" in the activity in the manifest. This was the only change necessary for me.
I don't like it but after digging ListView code I ended up by overriding the getFocusedChild() method and returning null as all other trials of flag combinations didn't get to a satisfactory solution.
Even if android:windowSoftInputMode="adjustPan" works adjusting pan leads to too much artifacts in my layout.
Beware overriding that method may lead to other unwanted behaviours so use it and test it comprehensively in all android versions you support and may be call super instead of returning null for android versions that does not/will have this problem.

Listview Custom Layout Multiple Choice

I would like to create a listview that allows multiple choice. The typical solutions is to get a cursor and use the SimpleCursorAdapter.
SimpleCursorAdapter adapter2 = new SimpleCursorAdapter(this,
R.layout.simple_list_item_multiple_choice, cur2, cols2, views2);
I am able to get this working when using the R.layout.simple_list_item_multiple_choice. I get the checkmarks to work when multiple items are selected.
So I decided to try it with a custom made layout. Here is the XML code for my layout.
<?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="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/lookup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="#+id/hasphone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall" />
<CheckedTextView
android:id="#+id/checkedTextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"/>
</LinearLayout>
So here is my issue. The layout is inflated fine using the same code and setting the ChoiceMode to multiple on my listview. The data from the cursor is populated fine.
However, the issue I have is that the checkmarks do not show up as selected (a check in the box) when I click on the item. Is there something I am missing that would not involve creating a custom adapter?
l2.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
l2 is my listview.
I'm not up on CheckedTextView... from my understanding, it should toggle the check when you click the line.
I suppose you could try and force it like this:
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
CheckedTextView chkTxt = (CheckedTextView) v.findViewById(R.id.CheckedTextView1);
chkTxt.toggle();
}
Note this would be a hack and you should really find the root problem, but it might get you going in the meantime.
EDIT
After much googling, I found the issue... the root of the row layout needs to be checkable to use CheckedTextView, and a LinearLayout is not.
More googling found a solution... override the LinearLayout class.
Instructions/code here
The problem with "the issue I have is that the checkmarks do not show up as selected" is because of your wrong layout. It should be without LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/lookup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="#+id/hasphone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall" />
<CheckedTextView
android:id="#+id/checkedTextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple" />
Then the SimpleCursorAdapter can set properly your "checkedTextView1" (with visible effect).
In my case I used the ArrayAdapter and it worked.
list.setAdapter(new ArrayAdapter<String>(this, R.layout.category_layout,
R.id.category_checkedText, this.categories));

Categories

Resources