Using a LayoutInflater, I am dynamically generating multiple TableRows, each which contains a checkbox. Everything worked great until you rotated the display. Each CheckBox gets the same text and checked state as the very last CheckBox created.
I found that if I assigned a unique ID to each row and to each checkbox it works correctly (each checkbox keeps its unique text and checked state).
If inflating the same layout multiple times, Do I need to assign a unique ID to every View inside the inflated layout? That sure could be a pain if you have an involved layout that is being inflated.
Here is my code that works:
main activity
public class PrototypeActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
TableLayout tablesLayout = (TableLayout)findViewById(R.id.TableLayout1);
tablesLayout.removeAllViews();
String[] values = new String[] { "Item 1", "Item 2", "Item 3"};
for (int i = 0; i < values.length; i++) {
View view = inflater.inflate(R.layout.row_layout, null, false);
view.setId(i);
CheckBox checkBox = (CheckBox) view.findViewById(R.id.tableCollectCheckBox);
checkBox.setId(values.length+i);
checkBox.setText(values[i]);
tablesLayout.addView(view);
}
tablesLayout.invalidate();
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TableLayout
android:id="#+id/TableLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"/>
</LinearLayout>
</ScrollView>
</FrameLayout>
row_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<TableRow
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal">
<CheckBox
android:id="#+id/tableCollectCheckBox"
android:text="DataTable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</TableRow>
You should call checkBox.setFreezesText(true).
Related
I'm trying to add some data to a ListView which one is not placed in my currently layout, so I cannot use this ListView, I'm inflating my currently layout with the layout where is the ListView placed, but I don't have any idea of how to code with ListView (I cannot set an adapter, I cannot do anything with this ListView, shows NullPointerException...).
How can I use a ListView that's not been placed on my currently Layout? Thanks in advance!
UPDATE
LAYOUT A.XML
<?xml version="1.0" encoding="utf-8"?>
<com.github.ksoichiro.android.observablescrollview.ObservableScrollView
android:layout_height="match_parent"
android:id="#+id/observable_scrollview"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"/>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cv"
card_view:cardBackgroundColor="#color/cardview_shadow_start_color"
android:layout_width="match_parent"
android:layout_height="100dp"
android:fitsSystemWindows="true"
android:isScrollContainer="true"
card_view:cardCornerRadius="#dimen/cardview_default_radius"
card_view:cardElevation="#dimen/cardview_default_elevation"
card_view:cardUseCompatPadding="true">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_marginTop="20dp"
android:layout_marginBottom="12dp"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="12dp"
android:gravity="center"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin">
<com.bluejamesbond.text.DocumentView
card_view:documentView_textColor="#color/circle_color"
android:id="#+id/dv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="#style/TextAppearance.AppCompat.Body2"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.v7.widget.CardView>
<View
android:id="#+id/view"
android:layout_width="wrap_content"
android:layout_height="600dp"
android:background="#android:color/black" />
</LinearLayout>
MAINACTIVITY.JAVA
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.LAYOUT A); //It's not the real name of layout, it's for this question...
ListView list = (ListView) findViewById(R.id.listViewId);
cv = (CardView) findViewById(R.id.cv);
//TextView dv = (TextView) findViewById(R.id.dv);
DocumentView dv = (DocumentView) findViewById(R.id.dv);
image = (ImageView) findViewById(R.id.image);
ObservableScrollView osv = (ObservableScrollView) findViewById(R.id.observable_scrollview);
osv.setScrollViewCallbacks(this);
View v = findViewById(R.id.view);
ViewGroup parent = (ViewGroup) v.getParent();
v = getLayoutInflater().inflate(R.layout.listview, parent, false);
int index = parent.indexOfChild(v);
parent.addView(v, index);
/*ViewGroup parent = (ViewGroup) findViewById(R.id.parent);
View C = getLayoutInflater().inflate(optionId, parent, false);
parent.addView(C, index);*/
b = getIntent().getExtras();
ArrayList<String> arrayList = new ArrayList<>();
for (int x = 0; x < Util.getData().size(); x++) {
if (b.get(Util.getData().get(x).getNombre()) != null) {
for (int z = 0; z < Util.GETDATA().get(x).getsomething().size(); z++) {
arrayList.add(Util.getData().get(x).getsomething().get(z).getname());
}
}
}
ArrayAdapter adapter = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_1, arrayList);
list.setAdapter(adapter); //IT CRASHES HERE!
....
//I CANNOT USE THIS LIST BECAUSE IT'S ON LAYOUT "B"
LAYOUT B.XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/llListview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".ChaptersActivity">
<ListView
android:focusableInTouchMode="false"
android:drawSelectorOnTop="true"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="#+id/listViewId"
android:fastScrollEnabled="true"/>
</LinearLayout>
JUST WHAT I WANT IS TO INFLATE THE VIEW OF LAYOUT A WITH THE LAYOUT B
You can try this:
LayoutInflater inflater = LayoutInflater.from(this);
View inflatedLayout= inflater.inflate(R.layout.LAYOUT B, null, false);
parent.addView(inflatedLayout);
EDIT:
After inflating your layout in parent, you can use findViewById to get the correct view
ListView list = (ListView) parent.findViewById(R.id.listViewId);
Finally, I've been doing this few steps to get my prefered solution:
CardView must be out, cause It's a FrameLayout and I cannot set it in the middle of between ListView and ImageView
Implementing ObservableScrollView from this place
I want to get rid of Toolbar, so I did it, because YOU CAN remove all toolbar code (from XML & Java) and It will works as ever!
Everything works perfectly, just have to look another way to implement a text on my Layout A
SOLVED!
I am trying to display 6 rows inside a linear layout. I want to do this through fragments as the content will be dynamic and the number of rows will also be dynamic later on. I have the following code but only one row appears on the screen. I have SettingsActivity.java, settings.xml ThemeRowFragment,java and theme_row_layout.xml.
SettingsActivity.java
//imports
public class SettingsActivity extends FragmentActivity {
private int NUM_THEMES = 7;
ThemeRowFragment[] view_themes;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings);
view_themes = new ThemeRowFragment[NUM_THEMES];
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
for (int i = 0; i < view_themes.length; i++) {
view_themes[i] = new ThemeRowFragment(COLOR_MAP[i]);
fragmentTransaction.add(R.id.theme_linear_layout, view_themes[i],
"Row" + i);
}
fragmentTransaction.commit();
}
}
settings.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
android:id="#+id/theme_linear_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/string_theme"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/string_theme"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#cde21c" />
</LinearLayout>
ThemeRowFragment.java
public class ThemeRowFragment extends Fragment {
private int[] colors;
public ThemeRowFragment(int colors[]) {
super();
this.colors = colors;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.theme_row_layout, container,
false);
return view;
}
}
theme_row_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="match_parent"
android:orientation="horizontal" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/pick_colors" >
</TextView>
</LinearLayout>
Fragments will inflate themselves into the View you add them to. So you really can't do it this way. So you need to have X empty containers, one for each fragment you are going to inflate. Add each fragment to the same container will actually layer them all on top of each other, sort of making them really hard to see and use when the screen renders.
Alternatives:
You could do something like the following:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
android:id="#+id/theme_linear_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/string_theme"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/string_theme"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#cde21c" />
<FrameLayout android:id="#+id/fragment_container1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout android:id="#+id/fragment_container2"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout android:id="#+id/fragment_container3"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout android:id="#+id/fragment_container4"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout android:id="#+id/fragment_container5"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<!-- etc. -->
</LinearLayout>
Or just add each FrameLayout programatically via the LinearLayout's addView() with a unique ID for each FrameLayout.
LinearLayout layout = (LinearLayout)findViewById(R.id.linear);
FragmentTxn txn = getFragmentManager.beginTransaction();
int i = 1; // This seems really fragile though
for (Fragment f : fragments) {
FrameLayout frame = new FrameLayout(this);
frame.setId(i);
layout.addView(frame);
txn.add(i, f);
i++;
}
txn.commit();
Or the other way would be to just use a listView and add each row that way. Not using Fragments at all.
<TextView
android:id="#+id/string_theme"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/string_theme"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#cde21c" />
<ListView android:id="#+id/listview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
then later on do something like this:
ListView view = (ListView)findViewById(R.id.listview);
view.setAdapter(new ArrayAdapter(items) { // items is a collection of objects you are representing
public View getView(int position, View view, ViewGroup parent) {
view = LayoutInflator.from(parent.getContext()).inflate(R.layout.theme_row_layout, parent, false);
// manipulate the view
return view;
});
You are creating a instance of ThemeRowFragment n number of times. The problem is you are creating this as an fragment and trying to add it dynamically. Since you instantiate the same Fragment i suggest you to use ListView and use a custom adapter and set CustomView and override the getView method of your adapter to adjust your views
Something gone wrong on my code. I have an XML representing layout of my fragment (fragment_layout.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
and another xml file representing a single view that shod go inside fragment layout (element.xml):
<?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" >
<TextView
android:id="#+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true" />
<EditText
android:id="#+id/et"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:inputType="number"
android:text="0" />
</RelativeLayout>
and this is how i fill Fragment layout inside onCreateView method:
View view = inflater.inflate(R.layout.fragment_layout, container,
false);
some_elements = getActivity().getResources().getStringArray(
R.array.some_array);
LinearLayout root = (LinearLayout) view.findViewById(R.id.root_layout);
for (int i = 0; i < some_elements.length; i++) {
View element = inflater.inflate(
R.layout.element, container, false);
TextView tv= (TextView) element.findViewById(R.id.tv);
prodotto.setText(prodotti[i]);
EditText et= (EditText) element.findViewById(R.id.et);
root.addView(element);
}
return view;
Now happen that only first element of "some_elements" array is showed inside fragment (element contains 10 elements). why other elements is not showed? what's wrong?
The problem is android:layout_height="match_parent", in your RelativeLayout. It should be wrap_content
I am creating a android application where i have to show contents of sqlite in Android app.
So i decide to use TableLayout here.But the main point here is that columns and rows from sqlite database is not previously decided,so i need to create that type of layout that deal with dynamic columns and rows.
So here what i am doing is that i have created a layouts sublayout.xml, cells.xml ,mainlayout.xml.
sublayout.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"
android:orientation="horizontal"
android:id="#+id/subLayout_" >
</LinearLayout>
In this layout i am dynamically adding cells using cells.xml.
cells.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"
android:orientation="horizontal" >
<TextView
android:id="#+id/cell_"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cell"
android:textSize="25dp"/>
</LinearLayout>
And when my one row gets ready i simply added it to mainlayout.xml.
mainlayout.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TableRow
android:id="#+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/tableLayout_"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"></LinearLayout>
</TableRow>
</TableLayout>
But i am getting nullpointer exception here.
Here is my class code.
LinearLayout layout,subLayout_;
layout=(LinearLayout)findViewById(R.id.tableLayout_);
subLayout_=(LinearLayout)findViewById(R.id.subLayout_);
for (int i = 0; i < columns.length; i++) {
Log.e("Column name", ""+columns[i]);
View v=inflater.inflate(R.layout.cells, null);
TextView tv=(TextView)v.findViewById(R.id.cell_);
tv.setText(columns[i]);
subLayout_.addView(v);
}
layout.addView(subLayout_);
Please help me what i am doing wrong here ?
Try this
layout = (LinearLayout) findViewById(R.id.tableLayout_);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View vi = inflater.inflate(R.layout.sublayout, null);
subLayout_ = (LinearLayout) vi.findViewById(R.id.subLayout_);
for (int i = 0; i < columns.length; i++) {
Log.e("Column name", "" + columns[i]);
ViewGroup v = (ViewGroup) inflater.inflate(R.layout.cells, null);
TextView tv = (TextView) v.findViewById(R.id.cell_);
tv.setText(columns[i]);
subLayout_.addView(v);
}
layout.addView(subLayout_);
You could try this approach here.
Design your xml like this:
<TableLayout>
<Tablerow>
<Add your views here dynamically>
</TableRow>
</TableLayout>
Create the textviews dynamically and go on adding it to the TableRow and finally add the TableRow to the TableLayout.
I have an activity in which my views (table and headertable) are overlapping
private ViewGroup createTable(ViewGroup root) {
// TODO Auto-generated method stub
TableLayout table = new TableLayout(getActivity());
table.setStretchAllColumns(true);
table.setShrinkAllColumns(true);
TableLayout headertable = new TableLayout(getActivity());
headertable.setStretchAllColumns(true);
headertable.setShrinkAllColumns(true);
/* Adding stuff to headertable which contains... */
/* ...table content I DO NOT WANT to scroll*/
root.addView(headertable);
for (int i = -2; i <= 100; i++) {
if (i > 0) {
/*Set up empty views*/
/*...3 empty views will be set*/
}
/* Adding stuff to table which contains... */
/* ...table content I WANT to scroll*/
}
ScrollView sv = new ScrollView(getActivity());
sv.addView(table);
root.addView(sv);
return root;
}
I basically broke a table into headertable and table. I want to scroll table but not headertable. However, my table(which should be below headertable), is overlapping it. Hence, as you can see above I added empty views(so it starts off below headertable(which has three rows)), but realized this would not work. As soon as I scrolled down, the empty views slide up and my headertable gets obstructed again.
All my views have been made programmatically. This activity is a fragment activity.
The XML file contains
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff" >
</FrameLayout>
Any help would be appreciated. Thanks in advance.
I don't know if it's the best way, but here's how I do it:
main.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"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/pane"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
header_list.xml
<?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" >
<TextView
android:id="#+id/header"
android:layout_width="fill_parent"
android:layout_height="30dp"
android:layout_alignParentTop="true" />
<ListView
android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_below="#id/header" />
<TextView
android:id="#android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/header"
android:gravity="center" />
</RelativeLayout>
RecipeListFragment.java
public class RecipeListFragment extends ListFragment {
private TextView header;
private TextView empty;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.common_list, container, false);
header = (TextView) v.findViewById(R.id.header);
empty = (TextView) v.findViewById(android.R.id.empty);
header.setText(R.string.header_recipe);
empty.setText(R.string.empty_recipes);
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// List code here
}
}
This code only has a single header line, but you can change that TextView to a TableLayout and then fill it the same way, giving you your header table and putting the list underneath it so that it won't scroll over the top of it.
Hope this helps!