Add new LinearLayout on each iteration of Activity - android

In one of my activities, I create a Linear Layout and some other Widgets when a bundle is received from an Intent. Currently, that Layout is overwrited each time I come back to that Activity. How can I create a new Layout each time without rewriting the code?
CODE:
public class FrontPageActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frontpage);
Bundle bundle = this.getIntent().getExtras();
try{
String size = bundle.getString("size");
int toppcount = bundle.getStringArrayList("toppings").toArray().length;
LinearLayout container = (LinearLayout)findViewById(R.id.container);
TextView t = new TextView(this);
TextView tprice = new TextView(this);
tprice.setGravity(Gravity.RIGHT);
LinearLayout inner = new LinearLayout(this);
LinearLayout.LayoutParams innerparams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
inner.setLayoutParams(innerparams);
inner.setBackgroundDrawable(getResources().getDrawable(R.drawable.background));
inner.setPadding(10,10,10,10);
if(toppcount == 0){
t.setText(size+" Cheese Pizza");
}
else{
t.setText(size+" "+toppcount+" Topping Pizza");
}
tprice.setText(getPrice(size, toppcount)+"");
tprice.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
container.addView(inner);
inner.addView(t);
inner.addView(tprice);
}
catch(NullPointerException e){
}
final Intent sender = new Intent(this.getApplicationContext(), OrderPizzaActivity.class);
Button badd = (Button)findViewById(R.id.buttonaddpizza);
badd.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
startActivityForResult(sender, 0);
}
});
}

It sounds like you would need to create a data structure to hold the LinearLayouts, or provide a ViewGroup container for them to be added to each time.
Currently you are creating, modifying, and then overwriting the same LinearLayout in the try{} catch(){} block. Which I would guess to be the reason why it keeps overwriting.

As I understood you add new "options" to the "final order". Every time additional topping added you create a layout and fill it with specific data. And you want it to be aka OrderList. If what this app is about, you can have an application level variable myOrder:List. Add there toppings (topping = new Order()) and read list in FrontPageActivity.
Recommend you to have a separate layout for an order. Looping through orders fill layout with data and inflate in a container of Activity.
Idea in pseudo:
MyApplication extends Application {
private static List<Order> mOrderList = null;
public MyApplication(){
mOrderList = new ArrayList<Order>();
}
public static List<Order> getOrderList(){
return mOrderList();
}
public static void addOrder(Order order) {
mOrderList.add(order);
}
}
options activity:
MyApplication.add(order);
MyApplication.add(order);
FrontPageActivity
foreach(Order order : MyApplication.getOrderList()) {
// fill layout with order data
// inflate orderLayout into container
}

Related

Weird Behavior about notifyDatasetChanged refreshment

Background
Hi, I am new to Android and trying to get familiar with ListView. So I decide to write a simple program for user to enter quotes and display them in order. I implement a StringAdapter and call the notifyDataSetChanged every time when the user confirms.
Question
The weird thing is that the ListView would sometimes update the oldest quotes and sometimes the newer one. and I don't know the problem.
Please ignore the view data button. In this state, I have entered four quotes:
Quotes: hi - Signature:William Shakespeare
Quotes: hello - Signature:William Shakespeare
Quotes: Virtue is bold and goodness never fearful. - Signature:William Shakespeare
Quotes: Love all, trust a few, do wrong to none. - Signature:William Shakespeare
(in reverse order, meaning in time sequence, it goes 4,3,2,1)
Code
main activity
public class storage extends AppCompatActivity {
// the adapter
private StringAdapter sa;
// the edit text view
public EditText etString,etSignature;
// the list view
public ListView lv;
// the array list to capture the quotes and signature
private ArrayList<String[]> dataString = new ArrayList<String[]>();
// add the string and notify
public void addString(String[] s){
this.dataString.add(0,s);
((BaseAdapter)this.lv.getAdapter()).notifyDataSetChanged();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_storage);
// Link the view elements
this.etString = (EditText) findViewById(R.id.etInput);
this.etSignature = (EditText) findViewById(R.id.etSignature);
this.lv = (ListView) findViewById(R.id.stringList);
Button btn_confirm = (Button) findViewById(R.id.btnConfirm),
btn_viewData = (Button) findViewById(R.id.btnViewData);
// load the adapter
this.sa = new StringAdapter(this,this.dataString);
lv.setAdapter(sa);
btn_confirm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
storage s = (storage) v.getContext();
// get the String
String sString = s.etString.getText().toString(),
sSignature = s.etSignature.getText().toString();
System.out.println("Quotes: " + sString + "\nSignature:" + sSignature);
// verify it is not empty
if (!sString.isEmpty()&&!sSignature.isEmpty()) {
// add new string and notify
s.addString(new String[]{s.etString.getText().toString(),
s.etSignature.getText().toString()});
((StringAdapter) s.lv.getAdapter()).print_stringData();
// prompt the result
Toast.makeText(s.getBaseContext(),
"Enter Quotes from"+etSignature.getText().toString(),Toast.LENGTH_SHORT).show();
} else {
// prompt the result
Toast.makeText(s.getBaseContext(),
"Please Enter Quotes and Signatures!",Toast.LENGTH_SHORT).show();
}
}
});
}
}
StringAdapter
public class StringAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String[]> dataStrings = new ArrayList<String[]>();
public StringAdapter(Context c,ArrayList<String[]> dataStrings){this.mContext=c;this.dataStrings=dataStrings;}
public int getCount(){return this.dataStrings.size();}
public Object getItem(int position){ return this.dataStrings.get(position);}
public long getItemId(int postion){ return (long) postion;}
public void print_stringData(){
System.out.println("String Adapter Output:");
for(String [] s: this.dataStrings){
System.out.println("Quotes: "+s[0]+"\nSignature:"+s[1]);
}
}
public View getView(int position, View convertView, ViewGroup parent){
LinearLayout ll;
if(convertView == null){
// set the linear layout
ll = new LinearLayout(this.mContext);
ll.setOrientation(LinearLayout.VERTICAL);
ll.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
// get the data and set the text inside
String[] data = this.dataStrings.get(position);
TextView //tvNo = new TextView(this.mContext),
tvString = new TextView(this.mContext),
tvSignature = new TextView(this.mContext);
ll.addView(tvString);
ll.addView(tvSignature);
tvString.setText(data[0]);
tvString.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
tvSignature.setText(data[1]);
tvSignature.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
tvSignature.setGravity(Gravity.RIGHT);
}
else{
ll = (LinearLayout) convertView;
}
return ll;
}
}
Comments
Some might notice that I add the String[] always to the first element. Actually I have tried to add to the last. The weird behavior still exists.
Environment
Android SDK Version: API 23 lollipop
Emulator Version: Nexus S API 23
Yes, of course, you get that error. Why? Because ListView always re-use convertView in your getView function of Adapter.
Look at your if,else:
else{
ll = (LinearLayout) convertView;
}
return ll;
At this block, you tell the adapter reuse the convertView, but you dont re-set the data. As a result, it will show the data of the previous row.
How to resolve it? just set the data in else block as you do in if one.
P/s: you should learn how to use ViewHolder in ListView to avoid laggy in when scrolling.

How to clear and add new texts to a dynamically created TextView?

I have added a TextView dynamically in a loop. On a button click, I want to clear the existing text in the text view and set some other text to it. How can I do this?
This is my current code:
ArrayList<String> Cheif_ComplaintNew = new ArrayList<String>();
int cc_Arraylist_length = Cheif_ComplaintNew.size();
android.widget.TextView cc_new = new android.widget.TextView(getApplicationContext());
for(int i=0; i<cc_Arraylist_length; i++)
{
cc_new.setId(i);
cc_new.setText(Cheif_ComplaintNew.get(i));
cc_new.setTextColor(getResources().getColor(R.color.black));
cc_new.setTypeface(null,android.graphics.Typeface.ITALIC);
cc_new.setTextSize(14);
cc_linearNew.addView(cc_new);
System.out.println("id"+i);
}
On a button click, the list is cleared and new data is stored in it. I want to display the new data in the same text view by clearing the old one.
You can either add the text to the textbox when you are creating it or assign it a class variable when you create it and later on you can add text to it.
TextView dynamicTextView;
...
private void CreateNewTextView()
{
dynamicTextView = Your New Text View;
}
...
private void ChangeTheText()
{
dynamicTextView.SetText("new value");
}
if you have more than one TextView you can create a class level generic list of TextViews and add them to the list and call them later.
you can also create a map of all TextView so you can call them with their key as well.
I think you can set a tag to cc_new before add it to cc_linearNew, like this: cc_new.setTag(i). when button got click, you can find those TextView by cc_linearNew.findViewByTag(i) in loop, and set new data to them.
Depends on how many TextViews you need to add to the layout dynamically.
As per the code mentioned, no TextViews are added to the layout as: Cheif_ComplaintNew.size() would return "0" so your loop will not be executed.
If you have to add only one TextView, then I agree with Daniel's answer of having a class level TextView variable.
If its multiple TextViews and you know which ID to use then in your Activity you can always get that TextView by calling findViewById("ID_OF_THE_TEXTVIEW_NEEDED")
You can do this in many ways, some of them :
Store your just created ids in array. Then just get your views calling parentView.findViewById(arreyOfIds(0));
Bad for performance do not do this :) - remove all of just added views from your parentView and create them one more time.
To handle back click in Activity use :
#Override
public void onBackPressed()
{
clearTextView();
}
All of this will simple look like this :
private List<Integer> ids = new ArrayList<Integer>();
#Override
public void onBackPressed()
{
clearTextView();
}
private void clearTextView()
{
for(Integer id : ids)
{
TextView view = (TextView)findViewById(id);
view.setText("")
}
}
private void createTextViews()
{
ArrayList<String>Cheif_ComplaintNew = new ArrayList<String> ();
int cc_Arraylist_length=Cheif_ComplaintNew.size();
android.widget.TextView cc_new = new android.widget.TextView(getApplicationContext() );
for(int i=0; i<cc_Arraylist_length; i++)
{
ids.add(i)
cc_new.setId(i);
cc_new.setText(Cheif_ComplaintNew.get(i));
cc_new.setTextColor(getResources().getColor(R.color.black));
cc_new.setTypeface(null,android.graphics.Typeface.ITALIC);
cc_new.setTextSize(14);
cc_linearNew.addView(cc_new);
System.out.println("id"+i);
}
}

Find List item that populated clicked Table-layout row:

I have an activity that contains a TableLayout. I'm populating this table programmaticly by data i have in a list:
what i need to do is to make every row clickable and when it's click I need to find the corresponding item in the list so i can get extra data out of it, this is my onCreate code:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.reports_list_activity_layout);
application = (SGRaportManagerAppObj)getApplication();
reportsRepository = application.reportsRepository.getReportsRepository();
TableLayout table = (TableLayout) findViewById(R.id.tableReportsList);
table.setStretchAllColumns(true);
table.setShrinkAllColumns(true);
for (Report tempReport : reportsRepository)
{
TableRow row = new TableRow(this);
row.setClickable(true);
TextView tvName = new TextView(this);
tvName.setText(tempReport.getName());
tvName.setGravity(Gravity.CENTER_HORIZONTAL);
tvName.setTextColor(getResources().getColor(R.color.my_black));
row.addView(tvName);
TextView tvPath = new TextView(this);
tvPath.setText(tempReport.getPath());
tvPath.setGravity(Gravity.CENTER_HORIZONTAL);
tvPath.setTextColor(getResources().getColor(R.color.my_black));
row.addView(tvPath);
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
Map<String, String> map = new HashMap<String, String>();
map.put(Report.JSON_KEY_ID, );
}
});
table.addView(row);
}
}
so what I need here is when the row is clicked i need to find it in the list and get the ID of the report that was clicked in the table and put into the Map object to pass foreword.
does anyone know how is this can be done?
thanks.
Use a hashtable that maps the content you show in the table row (say Report ID) againsg the Report Object
So something like
Hashtable map = new Hashtable();
...
map.put(report.getId(), report);
onClick on table row, manage to get the report id and in turn look it up this hashtable you are maintaining at a class level or somewhere accessible ..
Edit(code block)
class MyTableRow extends TableRow{
Object report = null;
public MyTableRow(Context context) {
super(context);
}
public Object getReport() {
return report;
}
public void setReport(Object report) {
this.report = report;
}
}
in the onCreate() of your activity, jus use MyTableRow class instead of TableRow like
tableRow = new MyTableRow(this) and use tableRow.setMethod(reportObject) to set the Report. should work..

Passing the view in onClick to a private class causes the wrong object to be sent

What im trying to do is display a checkbox, a button and a spinner in a TableLayout. The values are obtained from a web service and tableRows are added dynamically to the TableLayout.
The first button creates a dialog with a listview. The listview contains the numbers 1-30. When the user clicks selects a value in the ListView, i need the text of the button to change to the value clicked.
The code works for the first button that is clicked(The first time the listview is opened and a value is selected the text of the button is changed). But the second time i open the list view and select a button, the text of the first button changes and not the one which was clicked. What am i doing wrong?
protected void fillTableView() {
for (MedicineInfo temp : orderedMedList) {
LayoutInflater inflater = getLayoutInflater();
TableRow tr = (TableRow) inflater.inflate(
R.layout.neworderrestockmedicinelist2, tlOrderInfo, false);
CheckBox cbMedicine = (CheckBox) tr
.findViewById(R.id.cbNewOrderRestockMedName);
cbMedicine.setText(temp.vcProduct);
Button btnQty = (Button) tr
.findViewById(R.id.btnNewOrderRestockQty);
Spinner spnIntakeUnit = (Spinner) tr
.findViewById(R.id.spnNewOrderRestockIntakeUnit);
IntakeUnitAdapter intakeUnitAda = new IntakeUnitAdapter(this);
spnIntakeUnit.setAdapter(intakeUnitAda);
ArrayAdapter<String> arrayAda = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, numberArray);
arrayAda.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
tlOrderInfo.addView(tr);
btnQty.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
dlgQty = new Dialog(mContext);
TableRow tr = (TableRow) v.getParent();
ListView lvQty = new ListView(mContext);
QuantityAdapter qtyAda = new QuantityAdapter(mContext);
lvQty.setAdapter(qtyAda);
dlgQty.addContentView(lvQty,
new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
ItemSelectTest test = new ItemSelectTest(tr);
lvQty.setOnItemClickListener(test);
showDialog(DLG_QTY);
test = null;
}
});
}
}
private class ItemSelectTest implements OnItemClickListener {
Button btn = null;
public ItemSelectTest(TableRow tr) {
Button bt = (Button) tr.findViewById(R.id.btnNewOrderRestockQty);
btn = bt;
}
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
btn.setText(String.valueOf(arg3));
}
}
In the same shown above, i'm passing the TableRow that contains the button. I've also tried passing v from onClick. The problem is the same either way..
Thanks
I think that the problem is the way that you're showing the dialog. If you look at the docs for showDialog (here):
Show a dialog managed by this activity. A call to onCreateDialog(int,
Bundle) will be made with the same id the first time this is called
for a given id. From thereafter, the dialog will be automatically
saved and restored.
Presumably you're returning dlgQty in onCreateDialog. The thing is, that dialog will be cached after the first time. A quick fix for this is to always call removeDialog when you are done with it.

Multiple Listviews in single Activity in Android?

I want to have multiple listviews in single activity. But only one
listview should be displayed at one time. The listviews will be loaded
dynamically. So, how can I fill all the four listviews at the same
time and display only one?
Instead of using all that code to flip between listviews why not put all your listviews inside a ViewFlipper? It the easiest way an required almost 1 line of code! :)
-Moto
You can do one thing for your problem. The reason you will only see the one list view, may be because one list will have the fill parent paramter value for its height. What you have to do is, use absolute layout or just fix the height for each layout. Also use the scrollview to place the controls. Moreover, if you post your XML layout here, then it will be easier to answer your query as to where you need to make changes.
You should use a FrameLayout; it allows z ordering of its child views which means that you can have your ListView stacked one above the other. You can then toggle visibility of each of these ListViews from your code using View#setVisibility() method.
You would create appropriate adapters for each of these ListViews and whenever a ListView is to be drawn the framwork will call getView() method of the required adapter.
I have used mostly the same way of showing multiple listviews as you
suggested i.e. using setvisibility.
But now what I want is to have the Bitmap image of all the four
listviews. Suppose, my activity starts and the data are loaded into
all four listviews by binding them to their respective adapters.
Now, when I am trying to fetch the Bitmap using getDrawingCache() it
always returns null to me.
So, can you let me know how can I fetch the Bitmap of all the four
listviews?
public class HomeScreenActivity extends Activity
{
private ImageView imgBabble = null;
private ListView listBabble = null;
private ListView listVille = null;
private ListView listPrivateMsgs = null;
private ListView listBookmarks = null;
private List<String> tempBabble = null;
private List<String> tempVille = null;
private List<String> tempPrivateMsgs = null;
private List<String> tempBookmarks = null;
//RelativeLayouts
private RelativeLayout babbleLayout = null;
private RelativeLayout villeLayout = null;
private RelativeLayout privateMsgsLayout = null;
private RelativeLayout bookmarksLayout = null;
//Bitmap
private Bitmap babbleShrunkView = null;
private Bitmap villeShrunkView = null;
private Bitmap privateMsgsShrunkView = null;
private Bitmap bookmarksShrunkView = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.homescreen);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.customtitle);
imgBabble = (ImageView) findViewById(R.id.imgBtnBabble);
Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),R.drawable.babble_top_logo);
BitmapDrawable bmpDrawable = new BitmapDrawable(bitmapOrg);
imgBabble.setBackgroundDrawable(bmpDrawable);
//Initialize the layouts for Babble, Ville, Private Messages and Bookmarks
babbleLayout = (RelativeLayout) findViewById(R.id.babbleLayout);
babbleLayout.setDrawingCacheEnabled(true);
villeLayout = (RelativeLayout) findViewById(R.id.villeLayout);
villeLayout.setDrawingCacheEnabled(true);
privateMsgsLayout = (RelativeLayout) findViewById(R.id.privatemsgsLayout);
privateMsgsLayout.setDrawingCacheEnabled(true);
bookmarksLayout = (RelativeLayout) findViewById(R.id.bookmarksLayout);
bookmarksLayout.setDrawingCacheEnabled(true);
//Babble
tempBabble = new ArrayList<String>();
tempBabble.add("First Babble");
tempBabble.add("Second Babble");
tempBabble.add("Third Babble");
listBabble = (ListView) findViewById(R.id.listBabble);
listBabble.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, tempBabble));
//babbleShrunkView = babbleLayout.getDrawingCache();
//babbleLayout = (RelativeLayout) findViewById(R.id.listLayout);
if(babbleShrunkView == null)
{
System.out.println("Babble View is null");
}
//Ville
tempVille = new ArrayList<String>();
tempVille.add("First Ville");
tempVille.add("Second Ville");
tempVille.add("Third Ville");
listVille = (ListView) findViewById(R.id.listVille);
//listVille.setDrawingCacheEnabled(true);
listVille.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, tempVille));
//villeShrunkView = villeLayout.getDrawingCache();
if(villeShrunkView == null)
{
System.out.println("Ville View is null");
}
//listVille.setVisibility(View.GONE);
//Private Messages
tempPrivateMsgs = new ArrayList<String>();
tempPrivateMsgs.add("First PM");
tempPrivateMsgs.add("Second PM");
tempPrivateMsgs.add("Third PM");
listPrivateMsgs = (ListView) findViewById(R.id.listPrivateMessages);
//listPrivateMsgs.setDrawingCacheEnabled(true);
listPrivateMsgs.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, tempPrivateMsgs));
//privateMsgsShrunkView = privateMsgsLayout.getDrawingCache();
if(privateMsgsShrunkView == null)
{
System.out.println("Private Messages View is null");
}
//listPrivateMsgs.setVisibility(View.GONE);
//Bookmarks
tempBookmarks = new ArrayList<String>();
tempBookmarks.add("First Bookmarks");
tempBookmarks.add("Second Bookmarks");
tempBookmarks.add("Third Bookmarks");
listBookmarks = (ListView) findViewById(R.id.listBookmarks);
//listBookmarks.setDrawingCacheEnabled(true);
listBookmarks.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, tempBookmarks));
//bookmarksShrunkView = bookmarksLayout.getDrawingCache();
if(bookmarksShrunkView == null)
{
System.out.println("Bookmarks Messages View is null");
}
//listBookmarks.setVisibility(View.GONE);
imgBabble.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
System.out.println("Babble Clicked");
babbleShrunkView = babbleLayout.getDrawingCache();
villeShrunkView = villeLayout.getDrawingCache();
privateMsgsShrunkView = privateMsgsLayout.getDrawingCache();
bookmarksShrunkView = bookmarksLayout.getDrawingCache();
BabbleVilleShrinkView.addBitmap(0, resizeBitmap(200, 200, babbleShrunkView));
BabbleVilleShrinkView.addBitmap(1, resizeBitmap(200, 200, villeShrunkView));
BabbleVilleShrinkView.addBitmap(2, resizeBitmap(200, 200, privateMsgsShrunkView));
BabbleVilleShrinkView.addBitmap(3, resizeBitmap(200, 200, bookmarksShrunkView));
Gallery gallery = new Gallery(getApplicationContext());
gallery.setAdapter(new ImageAdapter(getApplicationContext()));
}
});
} // End of class

Categories

Resources