I'm trying to create an activity entirely by java code. The goal here is to create an Activity that fills up itself by previous activity. It's a shop list activity.
The user add itens in the previous activity and when he ask to show the complete list the activity above will be generated.
The problem here is, I want to set red as the initial color of the textviews with the itens names, and when the user clicks on then, they change their color to green.
But when I click it the aplication force close with the message indexoutofbounds exception.
Could someone helps me?
public class Listdinamiccor extends Activity {
Bundle recebendoparametros;
int i = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listdinamiccor);
Intent parametro = getIntent();
recebendoparametros = parametro.getExtras();
int j = recebendoparametros.getInt("i");
ScrollView sv = new ScrollView(this);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
sv.addView(ll);
final TextView[] tvarray = new TextView[j];
for (i = 0; i < tvarray.length; i++) {
String chave = "chave"+i;
final TextView tv = new TextView(this);
tvarray[i] = new TextView(this);
tvarray[i].setText(""+recebendoparametros.getString(chave));
tvarray[i].setTextColor(Color.RED);
tvarray[i].setOnClickListener(new View.OnClickListener() {
int click = 0;
#Override
public void onClick(View v) {
/*if (click == 0) {
tvarray[i].setTextColor(Color.GREEN);
}
else {
tvarray[i].setTextColor(Color.RED);
}*/
AlertDialog.Builder alert = new AlertDialog.Builder(Listdinamiccor.this);
alert.setTitle("dinamico");
alert.setMessage("eu sou muito dinamico");
}
});
ll.addView(tvarray[i]);
}
this.setContentView(sv);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.listdinamiccor, menu);
return true;
}
}
When your loop has completed executing, i is now set to tvarray.length -- your onClick handler doesn't "remember" the value of i, it simply does what you tell it to, which is to setTextColor on tvarray[i], and i is now out of bounds.
One way to solve it is to do this above your setOnClickListener line:
final TextView me = tvarray[i];
And then change your onClick method to call me.setTextColor instead of tvarray[i].setTextColor.
Also, I wouldn't recommend hanging onto the int i outside of your loop - I'm assuming you moved the member to the parent class so that your current code compiled, but in general you don't want to use for loop indexes outside of the for loop (this exception is one such reason).
Try casting your View v to a TextView inside your onclick listener instead of using the instance your creating in your array like this:
tvarray[i].setOnClickListener(new View.OnClickListener() {
int click = 0;
#Override
public void onClick(View v) {
if (click == 0) {
((TextView)v).setTextColor(Color.GREEN);
}
else {
((TextView)v).setTextColor(Color.RED);
}
AlertDialog.Builder alert = new AlertDialog.Builder(Listdinamiccor.this);
alert.setTitle("dinamico");
alert.setMessage("eu sou muito dinamico");
}
});
Related
I have a dynamic Android form with dynamic fields behaviour.
Example: If user fills field A, show field B and hides field C.
I'm using methods view.setVisibility(View.VISIBLE) and view.setEnabled(boolean) for this purpose. This approach works for RadioGroup and EditText, but don't work for Spinner component.
The spinner is set to visible, but is always disabled. The method .setEnable(true) don't cause any effect.
I need to show the spinner enabled.
If the spinner was visible, the setEnabled() works. But if the spinner was invisible, this 2 commands together don't work.
spinner.setVisibility(View.VISIBLE)
spinner.setEnabled(Boolean.TRUE)
[]'s
Please provide more details. The following code shows you how you can show/hide or enable/disable the spinner.
boolean visibility = true;
boolean enabled = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout linearLayout = new LinearLayout(this);
final Spinner spinner = new Spinner(this);
String[] animals = {"cats","dogs","lines","rats"};
spinner.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,animals));
linearLayout.addView(spinner);
Button visiblity = new Button(this);
visiblity.setText("VisibilityButton");
linearLayout.addView(visiblity);
setContentView(linearLayout);
visiblity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(visibility){
spinner.setVisibility(View.INVISIBLE);
visibility = false;
}
else{
spinner.setVisibility(View.VISIBLE);
visibility = true;
}
}
});
Button enabledButton = new Button(this);
enabledButton.setText("EnabledButton");
linearLayout.addView(enabledButton);
enabledButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(enabled){
spinner.setEnabled(false);
enabled = false;
}
else{
spinner.setEnabled(true);
enabled = true;
}
}
});
}
In my Activity, I have a field that is a button. It's value is always the currently selected button in a LinearLayout that is created dynamically in the activity. I want this field to always point to the button that is currently selected, however, if I select a button and then change the configuration, the field no longer points to the selected button. What can I do so that I can save this value across a configuration change?
Here's my code:
Activity.java
public class Activity extends AppCompatActivity {
Button myButton;
LinearLayout myLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
for (int i = 0; i < 2; i++) {
LinearLayout row = new LinearLayout(this);
LayoutParams rowParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1f);
row.setLayoutParams(rowParams);
for (int j = 0; j < 2; j++) {
final Button button = new Button(this);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setMyButton(button);
}
});
}
row.addView(button);
}
myLayout.addView(row);
}
public void setMyButton(Button button) {
myButton = button;
}
}
I have looked into using some savedInstanceState methods but none of them have one for a Button, only integers and booleans.
What can I do so that I can retain the value of myButton when the configuration changes?
You can use onSaveInstanceState() as long as you have some way to identify the button you want to save; you don't have to save the button itself.
Normally, you'd use the button's id for this purpose, but since you're dynamically creating the buttons at runtime (instead of putting them in your XML layout) I recommend using the button's tag instead.
Save the button's tag in onSaveInstanceState(), and then when you're creating the buttons, if you create a button with that same tag, save it as myButton.
onSaveInstanceState():
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("myButtonTag", myButton != null ? (String) myButton.getTag() : null);
}
At the top of onCreate():
String myButtonTag = null;
if (savedInstanceState != null) {
myButtonTag = savedInstanceState.getString("myButtonTag");
}
Inside your inner for loop:
final Button button = new Button(this);
String tag = i + "," + j;
button.setTag(tag);
if (tag.equals(myButtonTag)) {
myButton = button;
}
I have created a set of TextViews programmatically using a for loop. This what i have tried.
for(int i=1; i<5; i++){
valueTV = new TextView(AddMyVehicle.this);
linearLayout.addView(valueTV);
vehicleModelReturned = myVehicleData.getString("VehicleModel"+x, "");
valueTV.setText(vehicleModelReturned);
valueTV.setGravity(Gravity.CENTER_HORIZONTAL);
valueTV.setTextSize(TypedValue.COMPLEX_UNIT_SP,22);
valueTV.setTextColor(Color.parseColor("#333333"));
i++;
}
this.valueTV.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
valueTV.setText("Hello");
}
});
I need to change the text of clicked TextView to "Hello". How can i achieve this?
You have to add a listener to all your TextView created.
And be careful, you incremented i twice : one in the first line of the for and another one in the end of the for.
for (int i = 1; i < 5; i++)
{
final TextView valueTV = new TextView(AddMyVehicle.this);
linearLayout.addView(valueTV);
vehicleModelReturned = myVehicleData.getString("VehicleModel" + x, "");
valueTV.setText(vehicleModelReturned);
valueTV.setGravity(Gravity.CENTER_HORIZONTAL);
valueTV.setTextSize(TypedValue.COMPLEX_UNIT_SP, 22);
valueTV.setTextColor(Color.parseColor("#333333"));
valueTV.setId("test");
valueTV.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
TextView tv = (TextView) v;
tv.setText("Hello");
}
});
}
First, set the OnClickListener to all the TextViews you create, not just the last one. That is, move the setOnClickListener() inside the for loop.
Second, in onClick(), change the text of the clicked view and not again the last one you created. The View v param is the view that was clicked. You can cast it to TextView.
Need some advice again.
I am 99% done with this module I'm working on, although I'm stuck at the last hurdle. I'm dynamically publishing a button on the screen at runtime. This button will take it to a new activity view when pressed. I got that working perfectly.
However, I have another button which randomly changes the view so it effectively needs to reset itself, if that makes sense. What's happening is each time the button is clicked (the dynamic one) it then adds another button to the stack. Effectively I have buttons each time I click running down the screen. Is my logic wrong or is there a way to check and prevent the button to show each time? i.e. Just once...Below is the code.
public void ButtonOnClick(View v) {
Random rnd = new Random();
int randomListIndex = rnd.nextInt(2);
Animation myFadeInAnimation = AnimationUtils.loadAnimation(Page1.this, R.anim.fadein);
int firstRun = 0;
switch (randomListIndex) {
case 0:
//get the image your going to muck with
image = (ImageView) findViewById(R.id.cardImageView);
//set the image with what it should be
image.setImageResource(R.drawable.storm);
//apply the transition effect so it looks correct
image.startAnimation(myFadeInAnimation);
button = (Button)findViewById(R.id.dynamicButton);
button.setText("Need another question?");
Button myButton = new Button(this);
myButton.setText("Press Me");
LinearLayout layout = (LinearLayout) findViewById(R.id.nextPageContainer);
layout.addView(myButton);
final Button myButton1 = myButton;
myButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0) {
String activityName = "Storm";
Intent intent = new Intent(Page1.this, Page2.class);
intent.putExtra(ACTIVITYNAME,activityName);
startActivity(intent);
}
});
break;
}
}
EDIT: How about this? Add a new class field member (a class variable, not a method's local variable) that indicates whether the button was actually added in the layout.
private boolean buttonShown = false; /* Here changed */
public void ButtonOnClick(View v) {
Random rnd = new Random();
int randomListIndex = rnd.nextInt(2);
Animation myFadeInAnimation = AnimationUtils.loadAnimation(Page1.this, R.anim.fadein);
int firstRun = 0;
switch (randomListIndex) {
case 0:
//get the image your going to muck with
image = (ImageView) findViewById(R.id.cardImageView);
//set the image with what it should be
image.setImageResource(R.drawable.storm);
//apply the transition effect so it looks correct
image.startAnimation(myFadeInAnimation);
button = (Button)findViewById(R.id.dynamicButton);
button.setText("Need another question?");
if (buttonShown == false) { /* Here changed */
Button myButton = new Button(this);
myButton.setText("Press Me");
LinearLayout layout = (LinearLayout) findViewById(R.id.nextPageContainer);
layout.addView(myButton);
final Button myButton1 = myButton;
myButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0) {
String activityName = "Storm";
Intent intent = new Intent(Page1.this, Page2.class);
intent.putExtra(ACTIVITYNAME,activityName);
startActivity(intent);
}
});
buttonShown = true; /* Here changed */
} /* Here changed */
break;
}
}
Edited again: Instead of local variable myButton, I used class field member pressMeButton.
private Button pressMeButton;
public void ButtonOnClick(View v) {
Random rnd = new Random();
int randomListIndex = rnd.nextInt(2);
Animation myFadeInAnimation = AnimationUtils.loadAnimation(Page1.this, R.anim.fadein);
int firstRun = 0;
switch (randomListIndex) {
case 0:
//get the image your going to muck with
image = (ImageView) findViewById(R.id.cardImageView);
//set the image with what it should be
image.setImageResource(R.drawable.storm);
//apply the transition effect so it looks correct
image.startAnimation(myFadeInAnimation);
button = (Button)findViewById(R.id.dynamicButton);
button.setText("Need another question?");
if (pressMeButton == null) {
pressMeButton = new Button(this);
pressMeButton.setText("Press Me");
LinearLayout layout = (LinearLayout) findViewById(R.id.nextPageContainer);
layout.addView(pressMeButton);
}
/* If the pressMeButton is already in the layout, all you need to do is just changing the onClickListener. */
pressMeButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0) {
String activityName = "Storm";
Intent intent = new Intent(Page1.this, Page2.class);
intent.putExtra(ACTIVITYNAME,activityName);
startActivity(intent);
}
});
break;
}
}
Your code is fine but the way it is it will always add a button to the screen. Whats the desired behavior your looking for? If its a conditional thing than you need to account for that in the onclick call.
EDIT:
So what you need to do then is to create some kind of flag or id for the button and set it as the button's view.tag like this:
Button b = new Button(context);
b.setTag(flagTag);
Then when you want to check if the button exists you check it like:
if((LinearLayout) findViewById(R.id.nextPageContainer))
.findViewById(tagFlag)==null){
Button b = new Button(context);
b.setTag(flagTag);
}else{
//do nothing or something :p
}
I have a problem with parts of layout. I am adding buttons programmatically, because I want do something like breadcrump. I my solution work good. If I am in first activity I show one button. If I go to second I show two buttons.
This is code:
public class TabsGenerator extends LinearLayout{
public TabsGenerator(Context context) {
super(context);
}
public View addNewLinearLayout(Context context, ArrayList<String> descriptions) {
final HorizontalScrollView horizontalView = new HorizontalScrollView(context);
LinearLayout linearLayout = new LinearLayout(context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
params.height = 60;
linearLayout.setLayoutParams(params);
horizontalView.setLayoutParams(params);
postDelayed(new Runnable() {
public void run() {
horizontalView.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
}
}, 100L);
linearLayout.setGravity(Gravity.TOP);
List<View> components = getButtons(context, descriptions);
for(View component : components) {
linearLayout.addView(component);
}
horizontalView.addView(linearLayout);
return horizontalView;
}
public List<View> getButtons(Context context, ArrayList<String> descriptions) {
List<View> buttons = new ArrayList<View>();
for(int i = 0; i < descriptions.size(); i++) {
buttons.add(createButton(context,i, descriptions));
}
return buttons;
}
public View createButton(final Context context, final int i, final ArrayList<String> descriptions){
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
params.leftMargin = -20;
final Button button = new Button(context);
button.setText(SecondActivity.descriptions.get(i));
button.setBackgroundDrawable(getResources().getDrawable(R.drawable.paseknawigacji));
button.setHorizontallyScrolling(true);
button.setEllipsize(TruncateAt.END);
button.setSingleLine();
button.setWidth(20);
if(i==1)
button.bringToFront();
button.setLayoutParams(params);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ActivityManager am = (ActivityManager) context.
getSystemService(Activity.ACTIVITY_SERVICE);
String packageName = am.getRunningTasks(1).get(0).topActivity.getPackageName();
String className = am.getRunningTasks(1).get(0).topActivity.getClassName();
final String StringClassname = packageName+"."+descriptions.get(i);
Class<?> c = null;
if(StringClassname != null) {
try {
c = Class.forName(StringClassname );
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Intent intent = new Intent();
intent.setClassName(context,StringClassname);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if(!(StringClassname.contains(className))){
for(int j = 0; j<descriptions.size()-1;j++)
if(i<descriptions.size()-1)
descriptions.remove(i+1);
context.startActivity(intent);
}
}
});
return button;
}
}
I have a problem because buttons was added to layout but every buttons has ending by triangular shape. When I add second button he cover this shape.
This is how it is looks:
I want to bring to front ending every button. How I can do that?
Edit: Maybe is other way to create breadcrup in android?
Try to add buttons in the reverse order
Your code
List<View> components = getButtons(context, descriptions);
for(View component : components) {
linearLayout.addView(component);
}
now in reverse order
List<View> components = getButtons(context, descriptions);
for(int i = components.size() - 1; i >= 0; i --) {
View component = components.get (i);
linearLayout.addView(component);
}
(code not compiled, may have errors)
try this
thirdButton.bringtoFront();
SecondButton.bringToFront();
Your will see the triangular shape of third and second button.
Hope so this will work
I dont think yours will work with a linear layout as I have noticed that when using bring to front in a linear layout you automatically set it at the total end (eg its not longer button 1 button 2 button 3 but button 1 button 3 button 2). You would need to use a Relative layout or something similar. This might add a little logic to your code but it should be ok otherwise.
Maybe you can try setting elevation in your buttons
But I think the leftMargin= -20 is the reason why you cant see the ending triangle shape