I'm working on activity where user can add more input fields( 2 spinners and 1 edit text) on button click. This mechanism works fine until activity is recreated (rotation etc). All dynamically added views are lost.I'm looking for the the baest way to save state of views. Unfortunately I can not store list of views in onSaveInstanceState() method also I can not lock screen orientation. What can be a solution to resolve this problem?
Here is activity java code
public class ReportActivity extends AppCompatActivity {
private ImageButton addNew;
private LinearLayout mLayout;
private int categorySpinnerId =1001; //IDs of categorySpinner
private int currencySpinnerId =2001; //IDs of currencySpinner
private int editTextValueId =3001; //Ids of editText
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_report);
Toolbar toolbar = (Toolbar) findViewById(R.id.report_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
mLayout = (LinearLayout) findViewById(R.id.report_item_layout);
mLayout.addView(createNewCategorySpinner());
mLayout.addView(createNewEditText());
mLayout.addView(createNewCurrencySpinner());
addNew = (ImageButton) findViewById(R.id.btn_add_new);
addNew.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mLayout.addView(createNewCategorySpinner());
mLayout.addView(createNewEditText());
mLayout.addView(createNewCurrencySpinner());
}
});
}
//Generates operation category spinner
private Spinner createNewCurrencySpinner() {
final LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
final Spinner spinner = new Spinner(this);
spinner.setLayoutParams(lparams);
ArrayAdapter<CharSequence> currencySpinnerAdapter = ArrayAdapter.createFromResource(this,R.array.report_activity_currency_spinner,android.R.layout.simple_spinner_item);
currencySpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(currencySpinnerAdapter);
spinner.setId(currencySpinnerId);
spinner.setSaveEnabled(true);
Log.d("ID", spinner.getId() + "");
currencySpinnerId++;
return spinner;
}
//Generates currency type spinner
private Spinner createNewCategorySpinner() {
final LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
final Spinner spinner = new Spinner(this);
spinner.setLayoutParams(lparams);
ArrayAdapter<CharSequence> categorySpinnerAdapter = ArrayAdapter.createFromResource(this,R.array.report_activity_category_spinner,android.R.layout.simple_spinner_item);
categorySpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(categorySpinnerAdapter);
spinner.setId(categorySpinnerId);
spinner.setSaveEnabled(true);
Log.d("ID", spinner.getId() + "");
categorySpinnerId++;
return spinner;
}
//Generates operation input value edit text
private EditText createNewEditText() {
final LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
final EditText editText = new EditText(this);
editText.setLayoutParams(lparams);
editText.setHint("Value");
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
editText.setId(editTextValueId);
editText.setSaveEnabled(true);
Log.d("ID", editText.getId() + "");
editTextValueId++;
return editText;
}
}
Store enough information in your saved instance state Bundle to be able to recreate and repopulate the dynamically-created views in the new activity instance.
Related
I want to add spinner and edittext in my android activity on button click which looks like same as originally added in xml file. The spinner and edittext fields are adding properly upon button click on there right place.
Controls added code in MainActivity.java
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
productsIds++;
LinearLayout lv = findViewById(R.id.lnear_layout);
lv.addView(createLinearLayout());
}
public Spinner createProductSpinner() {
final LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(Math.round(getResources().getDimension(R.dimen.product_width)), Math.round(getResources().getDimension(R.dimen.control_height)));
final Spinner spinner = new Spinner(MainActivity.this);
spinner.setLayoutParams(lparams);
spinner.setAdapter(productAdapter);
return spinner;
}
public EditText createQuantityEditText() {
final LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(Math.round(getResources().getDimension(R.dimen.quantity_width)), Math.round(getResources().getDimension(R.dimen.control_height)));
final EditText editText = new EditText(MainActivity.this);
editText.setLayoutParams(lparams);
editText.setMovementMethod(new ScrollingMovementMethod());
editText.setHint("Quantity");
return editText;
}
public Spinner createUnitSpinner() {
final LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(Math.round(getResources().getDimension(R.dimen.unit_width)), Math.round(getResources().getDimension(R.dimen.control_height)));
final Spinner spinner = new Spinner(MainActivity.this);
spinner.setLayoutParams(lparams);
spinner.setAdapter(productAdapter);
return spinner;
}
public LinearLayout createLinearLayout() {
final LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
final LinearLayout subLayout = new LinearLayout(MainActivity.this);
subLayout.setOrientation(LinearLayout.HORIZONTAL);
subLayout.setLayoutParams(lparams);
subLayout.addView(createProductSpinner());
subLayout.addView(createQuantityEditText());
subLayout.addView(createUnitSpinner());
return subLayout;
}
});
I am creating dynamic textview in android. The view is created but when I am clicking on textview I want to set the background colour of that particular textview in android. I have tried but it sets the colour to only last textview not selected textview.
here is my code
public class Demo extends AppCompatActivity implements View.OnClickListener {
private LinearLayout llOptions;
private TextView textView, tvOptionFirstQue;
private ArrayList<String> arrayList = new ArrayList<>();
private static final int MY_BUTTON = 9000;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_quiz_demo);
llOptions = findViewById(R.id.llOptions);
tvOptionFirstQue = findViewById(R.id.tvOptionFirstQue);
for (int i = 0; i < 4; i++) {
textView = new TextView(Demo
.this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
float left = getResources().getDimension(R.dimen.common_twentyfive);
float top = getResources().getDimension(R.dimen.common_five);
float toppadding = getResources().getDimension(R.dimen.common_twelve);
float right = getResources().getDimension(R.dimen.common_twentyfive);
params.setMargins((int) left, (int) top, (int) right, 0);
textView.setPadding(0, (int) toppadding, 0, (int) toppadding);
textView.setTextSize(14);
textView.setBackgroundResource(R.drawable.button_background_light_gray);
textView.setGravity(Gravity.CENTER);
textView.setTextColor(Color.BLACK);
textView.setId(i);
textView.setLayoutParams(params);
textView.setText("test" + i);
textView.setOnClickListener(this);
arrayList.add(textView.getText().toString());
this.llOptions.addView(textView);
}
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case 0:
View child = llOptions.getChildAt(v.getId());
TextView textView1 = (TextView) child;
onFirstOptionClisk(textView1);
}
}
private void onFirstOptionClisk(TextView textView) {
textView.setBackgroundResource(R.drawable.rounded_lightblue_answer_backgroun);
textView.setTextColor(getResources().getColor(R.color.white));
}
Try this -
textView.setBackgroundResource(getResources.getColor(R.color.black));
And remove -
textView.setBackgroundResource(R.drawable.button_background_light_gray)
The reason of your issue is that you are creating a class variable TextView as textView and each time in your for look only this is updated with a new referance and as a result only the last textView persist. This is a type of logica issue.
Now the solution is that you create new object of your TextView in the for loop so different object reference will be added to the LinearLayout llOptions. The only thing that you need to do is that delete class variable for textView and creat object each time in for loop:
public class Demo extends AppCompatActivity implements View.OnClickListener {
private LinearLayout llOptions;
private TextView tvOptionFirstQue; //Comment by Hari: textView removed from here.
private ArrayList<String> arrayList = new ArrayList<>();
private static final int MY_BUTTON = 9000;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_quiz_demo);
llOptions = findViewById(R.id.llOptions);
tvOptionFirstQue = findViewById(R.id.tvOptionFirstQue);
for (int i = 0; i < 4; i++) {
TextView textView = new TextView(Demo
.this); //Comment by Hari: creating TextView object each time so that new reference will be created each time instead of over writing the same reference each time.
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
//Rest are unchanged......
Hope it will solve your issue. Let me know your experience.
use
textView.setBackgroundColor(Color.parseColor("#00ff00"));
instead
textView.setBackgroundResource(R.drawable.button_background_light_gray)
will work
i am making a activity that takes int position from another activity to get a class formula that have the formula, some variables and the title , so i want to create the activity by taking that formula and setting the title , making some edit text views for variables so that the user add values for them and then i return the result by a dialogue the problem is that the views that i add programitically are not displayed, plz help
public class DisplayFomula extends AppCompatActivity {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_fomula);
DB db = new DB(this);
Bundle extra = getIntent().getExtras();
int pos = extra.getInt("id");
final Formula form = db.getFormula(pos);
RelativeLayout layout=new RelativeLayout(this);
TextView tw1 =(TextView) findViewById(R.id.textView11);
tw1.setText(form.title);
final String[] var = form.var;
int i=0;
final EditText[] ed = new EditText[50];
for(;i<var.length;i++){
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
ed[i]= new EditText(this);
ed[i].setId(i);
ed[i].setHint(var[i]);
ed[i].setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
ed[i].setLayoutParams(params);
if(i!=0) params.addRule(RelativeLayout.BELOW,ed[i-1].getId());
else params.addRule(RelativeLayout.BELOW,R.id.textView11);
layout.addView(ed[i],params);}
Button btn = new Button(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
btn.setId(i);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
btn.setLayoutParams(params);
btn.setText("Go!");
layout.addView(btn,params);
params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
addContentView(layout,params);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
double[] varin=new double[var.length];
for(int i =0;i<var.length;i++){
Double dbl = Double.parseDouble(ed[i].getText().toString());
varin[i]=dbl;
}
String res = String.valueOf(form.result(varin));
}
});
}
}
You are adding all the views to RelativeLayout layout. But i think u have'nt add layout view to any activity_display_fomula view.
get a viewgroup from activity_display_fomula and add your RelativeLayout layout to it..
I have set notification listener in my code. Whenever I receive a notification I want to put a Text view in my linear layout activity which has nothing initially.
When second notification arrives I want to add one more text view below the previous text view.
public class InformationActivity extends Activity
{
public static VideoInformationClass vidInfo = new VideoInformationClass() ;
public static LinearLayout lv ;
public static LayoutParams textViewParams;
public static TextView tv ;
public static TextView tv1,tv2,tv3,tv4,tv5,tv6,tv7,tv8,tv9,tv10;
static int fieldFrequency;
static int numberOfFrameLines;
static int numberOfVisibleLines;
static int numberOfVisiblePixels;
static int interlace;
static int imageFormat;
static int videoCoding;
static int scanType;
VideoPropertiesParams GetParams;
VideoPropertiesParams VP;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.information_activity);
Context context = getBaseContext();
LinearLayout lv = new LinearLayout(this);
lv.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
// tv = new TextView(this);
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
onFieldFrequencyChanged();
onImageFormatChanged();
onInterlacedChanged();
/*vidInfo.RegisterVidPropertyListener();
vidInfo.RegisterSignalAndPresenceListener();
vidInfo.RegisterThreeDChangeListener();*/
if (ControlUnit.flag) {
GetParams = vidInfo.GetVideoProperty();
Log.i("TvPlayerFunctionalTestApp","Get Video Property called");
fieldFrequency = GetParams.fieldFrequency;
numberOfFrameLines = GetParams.numberOfFrameLines;
numberOfVisibleLines = GetParams.numberOfVisibleLines;
numberOfVisiblePixels = GetParams.numberOfVisiblePixels;
interlace = GetParams.interlace;
imageFormat = GetParams.imageFormat;
videoCoding = GetParams.videoCoding;
scanType = GetParams.scanType;
}
/* tv.setText("Something");
tv.setLayoutParams(textViewParams);
lv.addView( tv );*/
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
/*vidInfo.UnRegisterSignalAndPresenceListener();
vidInfo.UnRegisterThreeDChangeListener();
vidInfo.UnRegisterVidPropertyListener();*/
}
public void onFieldFrequencyChanged(){
String info = "On field frequency changed , value is " + vidInfo.ChangedFrequency;
tv = new TextView(this);
tv.setText(String.valueOf(info));
LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
tv.setLayoutParams(textViewParams);
lv.addView(tv);
}
public void onImageFormatChanged() {
String info = "On Image Format changed , value is " + vidInfo.ChangedFormat;
tv1 = new TextView(this);
tv1.setText(String.valueOf(info));
LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
tv1.setLayoutParams(textViewParams);
lv.addView(tv1 );
}
public void onInterlacedChanged() {
String info = "On Interlaced changed , value is " + vidInfo.InterlaceChange;
tv.setText(String.valueOf(info));
LinearLayout.LayoutParams textView
Params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
tv.setLayoutParams(textViewParams);
lv.addView(tv);
}
Just declare your Linear layout with vertical orientation
<LinearLayout
android:id="#+id/linear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
LinearLayout lv = (LinearLayout)findViewById(R.id.linear);
TextView tv = new TextView(this);
tv.setLayoutParams(InformationActivity.textViewParams);
tv.setText(String.valueOf(info));
lv.addView(tv );//not InformationActivity.tv just write tv
It will automatically add next view below the the another
Make sure your LinearLayout has orientation set to vertical. Then just add one more item:
LinearLayout layout = // your layout
TextView textView = // new text view
layout.addView(textView);
Just make a Linear Layout whose oreientation is vertacal and add TextView to it.
You need a object from the main ViewGroup(RelativeLayout, LinearLayout etc.),
TextView text = new TextView(this); RelativeLayout r = (RelativeLayout)findViewById(Id);r.add(text);
this lines of code will add a new textView object to the end of the r viewGroup.
I have an activity with some dynamic content.
For each item of an array, there is a different content (number of textViews, checkboxes, ..)
The user clicks on a "save" button and then the screen has to refresh itself to display the content of the next item.
I was wondering if it was a good practice to reload my activity like this :
Intent refresh = new Intent(this, conflictActivity.class);
startActivity(refresh)
finish()
instead of removing all the views in my layouts, etc ...
I think it's easier to reload it.
Is there another way to do it ?
EDIT : added Code.
public class ConflicFieldTest extends Activity {
private int nbField;
private int nbChecked;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.conflict);
final Button saveButton = (Button) findViewById(R.id.save);
final LinearLayout leftLayout = (LinearLayout) findViewById(R.id.leftLayout);
final LinearLayout rightLayout = (LinearLayout) findViewById(R.id.rightLayout);
final TextView fieldName = new TextView(this);
final LinearLayout editLayoutRight = new LinearLayout(this);
final LinearLayout editLayoutLeft = new LinearLayout(this);
final LinearLayout fieldRight = new LinearLayout(this);
final LinearLayout fieldLeft = new LinearLayout(this);
final ArrayList<String> allIdInConflict = getAllIdInConflict();
for (int i = 0; i < allIdInConflict.size(); i++) {
new AccountSyncTask() {
#Override
public void onPostExecute(
final ArrayList<ArrayList<String>> result) {
nbField = 0;
nbChecked = 0;
final Map<String, Object> fieldsInConflict = conflict
.conflictWithFields(memoAccountMap,
serverAccountMap, modifiedAccountMap);
for (Iterator<Map.Entry<String, Object>> field = fieldsInConflict
.entrySet().iterator(); field.hasNext();) {
final Map.Entry<String, Object> entry = field.next();
fieldName.setText(entry.getKey() + " : ");
final EditText[] editTextArrayRight = new EditText[fieldsInConflict
.size()];
final EditText[] editTextArrayLeft = new EditText[fieldsInConflict
.size()];
final CheckBox[] checkboxRight = new CheckBox[fieldsInConflict
.size()];
final CheckBox[] checkboxLeft = new CheckBox[fieldsInConflict
.size()];
checkboxRight[nbField] = new CheckBox(
ConflicFieldTest.this);
checkboxLeft[nbField] = new CheckBox(
ConflicFieldTest.this);
editLayoutLeft.setGravity(Gravity.CENTER_HORIZONTAL);
editLayoutRight.setGravity(Gravity.CENTER_HORIZONTAL);
fieldRight.setGravity(Gravity.CENTER_HORIZONTAL);
fieldLeft.setGravity(Gravity.CENTER_HORIZONTAL);
editLayoutRight.setOrientation(LinearLayout.HORIZONTAL);
fieldRight.setOrientation(LinearLayout.VERTICAL);
fieldLeft.setOrientation(LinearLayout.VERTICAL);
rightLayout
.addView(
editLayoutRight,
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
leftLayout
.addView(
editLayoutLeft,
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
editTextArrayRight[nbField] = new EditText(
ConflicFieldTest.this);
editTextArrayRight[nbField].setText((String) entry
.getValue());
editTextArrayRight[nbField].setTextColor(Color.BLACK);
editTextArrayRight[nbField].setFocusable(false);
editTextArrayRight[nbField].setClickable(false);
editTextArrayRight[nbField].setWidth(180);
editTextArrayRight[nbField].setPadding(0, 10, 0, 0);
editTextArrayLeft[nbField] = new EditText(
ConflicFieldTest.this);
editTextArrayLeft[nbField]
.setText((String) serverAccountMap.get(entry
.getKey()));
editTextArrayLeft[nbField].setTextColor(Color.BLACK);
editTextArrayLeft[nbField].setFocusable(false);
editTextArrayLeft[nbField].setClickable(false);
editTextArrayLeft[nbField].setWidth(180);
editTextArrayLeft[nbField].setPadding(0, 10, 0, 0);
final int i1 = nbField;
checkboxLeft[i1]
.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
checkboxRight[i1]
.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
editLayoutLeft.addView(fieldName);
editLayoutRight
.addView(
editTextArrayRight[nbField],
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
editLayoutLeft
.addView(
editTextArrayLeft[nbField],
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
editLayoutRight.addView(checkboxRight[nbField]);
editLayoutLeft.addView(checkboxLeft[nbField]);
nbField++;
}
saveButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
//save data & update UI
}
}
.execute(appState.getSessionName(), id, "getObjectOnServer");
}
}
Sorry for the code, it is a litle bit dirty (i have deleted some parts), i am reworking it.
int flag = 0;
public void updateUI() {
if(flag == 0) {
//your normal codes...
} else {
//display view with user given data
}
}
Call this function in oncreate. At first flag will be set to zero. When u enter the data in textview and tick checkboxes, update the flag with some value. Then on save Button click call this function again. Now flag is set. So it will display the updated UI.
I think this will give u an idea..