Edittext in TableView not displaying pre-lollipop devices - android

I am having trouble getting EditText to dynamically populate in TableView, this is only happening on non Lollipop Devices in a fragment (In particular an appcompat fragment, i have not tested in a regular framgent). When the same code is run in an activity it works fine.
Here is my fragment code on creating the row of edit texts.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_daily_field_report, container, false);
tableLayout = (TableLayout) view.findViewById(R.id.equipmentLayout);
context = getActivity().getBaseContext();
this.inflater = inflater;
activityContext = getActivity();
return view;
}
private void createRow(Equipment equipment, final int editId) {
TableRow row = new TableRow(context);
EditText equipmentName = (EditText) getActivity().getLayoutInflater().inflate(R.layout.table_text_edittext, row, false);
EditText headerQty = (EditText) getActivity().getLayoutInflater().inflate(R.layout.table_number_edittext, row, false);
EditText headerHrs = (EditText) getActivity().getLayoutInflater().inflate(R.layout.table_number_edittext, row, false);
equipmentName.setText(equipment.title);
if (equipment.Qty != 0) {
headerQty.setText(Integer.toString(equipment.Qty));
}
if (equipment.Hrs != 0) {
headerHrs.setText(Integer.toString(equipment.Hrs));
}
equipmentName.setId(editId);
this.fields.add(equipmentName);
this.fields.add(headerQty);
this.fields.add(headerHrs);
row.addView(equipmentName);
row.addView(headerQty);
row.addView(headerHrs);
tableLayout.addView(row);
rows.add(new myTableRow(equipment, equipmentName, headerHrs, headerQty));
}
And Here are the edit text Xml layouts.
<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_weight="1"
android:padding="5dp"
android:gravity="center"
android:layout_height="wrap_content"
android:inputType="text"
android:ems="10"
android:id="#+id/pumptruckQty"
android:layout_column="1"/>

I figured out what was causing the issue. When creating the TableRow to add to the TableLayout i was using the wrong context. The context used to create the Row should be the context of the LayoutInflater that is given in the onCreateView of the fragment.

Related

Dynamically populate a dialogue inside a fragment

I have created a fragment and want to start a dialogue on a button click on which i would display n numbers of texts distributed vertically using Linear layout vertical orientation. To begin with i have created a textview which i am populating dynamically. But i get a null pointer exception saying the any of the layout i referenced here points to NULL.
View view,tempView;
TextView myName, myPhNo, myEmail, myDob;
ImageButton selectRingTone;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_profile, container, false);
tempView = inflater.inflate(R.layout.fragment_selectsong, container, false);
myName = (TextView)view.findViewById(R.id.username);
myPhNo = (TextView)view.findViewById(R.id.userPhNo);
myEmail = (TextView)view.findViewById(R.id.useremailId);
myDob = (TextView)view.findViewById(R.id.userdob);
selectRingTone = (ImageButton)view.findViewById(R.id.selectRingTone);
setUserProfileData();
//setUserTextStatus();
//setUserAudioStatus();
selectRingTone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
chooseAndSetRingTone();
}
});
return view;
}
private void chooseAndSetRingTone(){
final Dialog fbDialogue = new Dialog(view.getContext(), android.R.style.Theme_Black);
fbDialogue.getWindow().setTitle("Select your audio status song");
fbDialogue.getWindow().setBackgroundDrawable(new ColorDrawable(Color.argb(100, 0, 0, 0)));
fbDialogue.setContentView(R.layout.fragment_selectsong);
getSongsAndFillDialogue();
fbDialogue.setCancelable(true);
fbDialogue.show();
}
private void getSongsAndFillDialogue(){
LayoutInflater inflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout container = (LinearLayout) tempView.findViewById(R.id.eachRingToneSong);
TextView tv = new TextView(tempView.getContext());
tv.setText("Hi hello");
Button b = new Button(tempView.getContext());
b.setText("abcde");
container.addView(tv);
container.addView(b);
}
XML Code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainLyt"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ScrollView
android:id="#+id/scrollCotainerForRingToneSongs"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/eachRingToneSong"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--<TextView
android:id="#+id/song1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="abcde"
/>-->
</LinearLayout>
</ScrollView>
</RelativeLayout>
you are creating View for your Dialog in onCreateView method:
tempView = inflater.inflate(R.layout.fragment_selectsong, container, false);
and fulfilling it using getSongsAndFillDialogue method, but you are setting for your Dialog another new instance passing only resource id:
fbDialogue.setContentView(R.layout.fragment_selectsong);
when you are passing just id then Dialog is inflating this layout by itself (just like you). So there are two layouts created, one in Activity - fulfilled, and one created "automatically" by setContentView method, but not touched at all by your methods (so it stays empty)
instead of passing resource id pass already prepared tempView, like below:
fbDialogue.setContentView(tempView);

Append TextView to RelativeLayout

I have a RelativeLayout containing a TextView.
I want to append a new TextView under the existing TextView programmatically in the onCreateView method, but what happens when I try to do so, is that the TextView I add programmatically gets overlapped with the existing one.
More details below:
public static class ContentTours extends Fragment{
public static String TOUR_NAME= "tour_info";
View view = getView();
TextView contentTour;RelativeLayout toursView;
public ContentTours(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.tours_view, container, false);
toursView = (RelativeLayout) view.findViewById(R.id.rel_layout);
contentTour = (TextView) view.findViewById(R.id.tours);
contentTour.setText(getArguments().getString("2"));
ViewGroup.LayoutParams stt = contentTour.getLayoutParams();
TextView nt = new TextView(getActivity().getBaseContext());
nt.setText(getArguments().getString("1"));
toursView.addView(nt, new ViewGroup.MarginLayoutParams(stt));
return view;
}
}
I have a RelativeLayout containing the TextView. tours_view.xml:
<RelativeLayout android:id="#+id/rel_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:layout_marginBottom="16dp">
<TextView android:id="#+id/tours" android:clickable="true"
android:background="?android:selectableItemBackground"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
android:text="Lorem ipsum"/>
</RelativeLayout>
the reason why I have a Fragment class is that tours_view.xml is a layout that I am applying to another FrameLayout.
By default in a RelativeLayout, the views overlap if there is no relation defined.
What you should do for your requirement is create a relation(rule) between the TextView to be added and the already present TextView.
RelativeLayout.LayoutParams stt = (RelativeLayout.LayoutParams) contentTour.getLayoutParams();
Now, add a rule
stt.addRule(RelativeLayout.BELOW, R.id.tours);
RelativeLayout.BELOW, so that the new TextView is below your old one. Hope this helps.

Unexpected EditText reuse

Implementing a table-like UI I met a really strange behaviour. After rotating the screen all rows contain the same edit text field
Here is my code:
Main activity:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ViewGroup layout = (ViewGroup) findViewById(R.id.table_layout);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
addRow(inflater, layout, "A", 0);
addRow(inflater, layout, "B", 1);
addRow(inflater, layout, "C", 2);
}
private void addRow(LayoutInflater inflater, ViewGroup layout, String title, int value) {
View view = inflater.inflate(R.layout.row, null, false);
Row row = (Row) view;
row.setTitle(title);
row.setValue(value);
layout.addView(row);
}
}
Main activity layout:
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:layout_gravity="center"
a:orientation="vertical">
<LinearLayout
a:id="#+id/table_layout"
a:orientation="vertical"
a:layout_width="match_parent"
a:layout_height="wrap_content" />
</LinearLayout>
Table row:
public class Row extends LinearLayout {
public Row(Context context) {
super(context);
}
public Row(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setTitle(String title) {
final TextView titleView = (TextView) findViewById(R.id.title);
titleView.setText(title);
}
public void setValue(int i) {
final TextView valueEdit = (TextView) findViewById(R.id.value);
valueEdit.setText("" + i);
}
}
Table row layout:
<?xml version="1.0" encoding="utf-8"?>
<com.anagaf.freqhelper.Row
xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="match_parent"
a:layout_height="match_parent"
a:orientation="horizontal">
<TextView
a:id="#+id/title"
style="#style/RangeTitle"
a:layout_marginBottom="#dimen/gap"
a:layout_height="wrap_content"/>
<EditText
a:id="#+id/value"
style="#style/ChannelEdit"/>
</com.anagaf.freqhelper.Row>
After the app starts the table looks ok:
A 0
B 1
C 2
If I change the screen orientation to landscape the table changes to:
A 2
B 2
C 2
It looks like the EditText from the last row is re-used for all rows.
If I replace value EditText with TextView - everything is ok
Any idea what's happening?
You are inflating the ViewGroup inflater.inflate(R.layout.row, null, false); as a View. Instead, inflate it as a ViewGroup then use yourviewgroup.findById(R.id.someview) to get each element you want to fill.
Even better would be to create a new layout in code, then inflate your 'template' layout and instantiate each element from there. Then you use the created layout to display the elements you just instantiated.
This way you can inflate the layout only once and pass it as a variable to each row, return a new layout and put it in the activity's layout.

Android - List of labels in a fragment, wrong display when scrolling

So here's my problem.
I'm working on API 14, I made a "MasterDetailFlow" with the help of Eclipse.
On the left part of the "twopane", I have some textviews, and a fragment.
(I made it simple)
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="horizontal"
tools:context=".ListActivity" >
<RelativeLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="27"
android:orientation="vertical" >
<TextView
android:text="toto"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="textView"/>
<fragment
android:id="#+id/fragment1"
android:name=""
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="button"
/>
</RelativeLayout>
//the right part of the screen, doesn't matter
<FrameLayout
/>
</LinearLayout>
The Fragment class is like that
public class MyFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = null;
if (mItem != null) {
if(mItem.isTrue){
rootView = inflater.inflate(layout1, container, false);
}else{
rootView = inflater.inflate(layout2, container, false);
}
}
}
}
I dynamically add items in the list with a ArrayAdapter.
The thing is : When the list doesn't need to be scrolled (the height of the list is smaller than the height of the fragment), everything is displayed the good way.
But when the list is bigger (the visible part is OK) and I scroll the list, some items which should have the layout1 have the layout2, and the other way.
Those items are weirdly always at the junction, like the first element hidden.
And when you click on the item, it act normally. For exemple, a item that should be layout1 (but is displayed layout2) act as an item layout1 on click.
I don't know if it's clear, because it's not to me :)
And when I print in logcat the list of Strings which is in the fragment, it's in the good order. So it looks like a "display error" only, but where does it come from?
Does anyone have some similar problem? Know the issue?
Thanks.
EDIT :
Here is my Custom ArrayAdapter. I don't have the methods getItemViewType and getViewTypeCount, I should work on that.
Till now I was using a boolean stored in the DummyItem to know if it's a type 1 item or a type 2.
public class CustomArrayAdapter extends ArrayAdapter<DummyItem>
#Override
public View getView(int p_position, View p_convertView, ViewGroup p_parent) {
DummyItem item = data.get(p_position);
View row = p_convertView;
if(row==null){
if(item.isTrue){
LayoutInflater inflater = ((Activity)m_context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, p_parent, false);
row.setTag(item);
TextView label1 = (TextView) row.findViewById(textViewId);
label1.setText(item.content);
}else{
LayoutInflater inflater = ((Activity)m_context).getLayoutInflater();
row = inflater.inflate(R.layout.simple_list_item_activated_1_custom, p_parent, false);
TextView label2 = (TextView) row.findViewById(R.id.text1);
labelPiece.setText(item.content);
}
}else{
}
return row;
}
}

addfooterview cause exception

i inflate by this
linear = (LinearLayout) findViewById(R.id.layout_content);
linear.setVisibility(View.VISIBLE);
LayoutInflater liInflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
linear.addView(liInflater.inflate(R.layout.main_particularcategoryallnewslist, null));
linear.addView(liInflater.inflate(R.layout.main_particularcategoryallnewslistfv, null));
This is my listview
btnmore = (Button)findViewById(R.id.btn_more);
getListView().addFooterView(btnmore);
lv.setAdapter(adapter);
I want to inflate second time but failed.
However i can inflate firsttime which was
linear.addView(liInflater.inflate(R.layout.main_particularcategoryallnewslist, null));
What is the problem why i get this error?
java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
Try changing this:
linear.addView(liInflater.inflate(R.layout.main_particularcategoryallnewslist,
null));
To this:
linear.addView(liInflater.inflate(R.layout.main_particularcategoryallnewslist,
linear));
i think It's not because of the line you pointed out..
Did you call getLayoutParams() anywhere in your code?
Whenver you call getLayoutParams(), you show typecase to parent layoutparams.
Like, if your ListView's parent is LinearLayout then,
LinearLayout.LayoutParams params=(LinearLayout.LayoutParams) listView.getLayoutParams();
If your ListView's parent is RelativeLayout then,
RelativeLayout.LayoutParams params=(RelativeLayout.LayoutParams) listView.getLayoutParams();
I had similar situation - there was exception "java.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams" on list_view.setAdapter();
I have managed to workaround this problem by using same layout for both footer and list items. The code below demonstrates how to use layout "listview_row" in footer and in items.
This is content of "listview_row.xml":
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/hs_line"
android:layout_alignParentLeft ="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<!-- TextView for list items -->
<TextView android:id="#+id/hs_line_textview"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_alignParentLeft="true"
/>
<!-- Button for footer -->
<Button android:id="#+id/hs_line_footer_action"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:visibility="gone"
android:layout_alignParentLeft="true"
/>
</RelativeLayout>
Footer is initialized in such way:
View v = View.inflate(pager.Activity, R.layout.listview_row, null);
View footer = (View) v.findViewById(R.id.listview_line);
//footer doesn't use TextView, it uses Button only. So, we hide TextView.
footer.findViewById(R.id.hs_line_textview).setVisibility(View.GONE);
footer.findViewById(R.id.hs_line_footer_action).setVisibility(View.VISIBLE)
...
list_view.addFooterView(footer);
MyAdapter<Item> adapter = new MyAdapter(context, getListItems());
list_view.setAdapter(adapter);
Adapter:
public class MyAdapter<T> extends ArrayAdapter<T> {
private final ArrayList<T> _List;
private final LayoutInflater _Inflater;
public MyAdapter(Context context, ArrayList<T> srcList) {
super(context, 0, srcList);
_Inflater = LayoutInflater.from(context);
_List = srcList;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = _Inflater.inflate(R.layout.listview_row, null);
holder = new ViewHolder();
//item doesn't use Button, it uses TextView only
//Button is hidden by default (see xml)
holder.TextView = (TextView) convertView.findViewById(R.id.hs_line_textview);
} else {
holder = (ViewHolder) convertView.getTag();
}
//item initialization
.....
}
It's not ideal solution - only workaround, of course.

Categories

Resources