I was struggling to create a spinner dynamically. I had it on the page but every time I tried to select an option it would blow up. My original code is at the bottom. I fixed it by moving the addSpinner() function outside of the inner class and changing
Spinner newSpinner = new Spinner(getApplicationContext());
to
Spinner newSpinner = new Spinner(this);
It's fixed but I have no idea what it didn't work initially. Can anyone explain? (apologies if it's a noob question - I am new to both Java and android)
public class SpotManageActivity extends Activity
{
private SimpleCursorAdapter mSpots;
#Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.reminder_manage_activity);
Button add_new_button = (Button) findViewById(R.id.add_new_spot_button);
add_new_button.setOnClickListener(new ButtonOnClickListener());
}
public class ButtonOnClickListener implements View.OnClickListener
{
#Override
public void onClick(View v)
{
addSpinner();
}
private void addSpinner()
{
LinearLayout layoutHolder =
(LinearLayout) findViewById(R.id.layout_holder);
LinearLayout spinnerHolder = new LinearLayout(getApplicationContext());
spinnerHolder.setOrientation(LinearLayout.HORIZONTAL);
spinnerHolder.setLayoutParams(
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT, 1f));
Spinner newSpinner = new Spinner(getApplicationContext());
newSpinner.setLayoutParams(
new Spinner.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
newSpinner.setAdapter(mSpots);
layoutHolder.addView(spinnerHolder);
spinnerHolder.addView(newSpinner);
// A non-internal spot was selected
}
}
}
I am not sure at all, but if in the stack trace you're getting something about a wrong context, it's probably because a Spinner, when clicked, opens a Dialog, and a Dialog needs an Activity context.
For more info:
Android - what's the difference between the various methods to get a Context?
Dialog throwing "Unable to add window — token null is not for an application” with getApplication() as context
Related
I'm doing a grocery list app and i want all the list to be sort by department (Meat, fruit, bakery etc.). I try to do the first list which is the fruit list everything is working i can add item the checkbox is there i can use it no problem. the problem is that when i check items and i press the previous button on the phone and then i click back on the button to access the fruit list the items are not checked anymore.
I use the android.R.layout.simple_list_item_multiple_choice for the checkbox.
I try to use onSaveinstance but i cant get it to work ...i would like to save it without using SQl now my array are save in a file for my list.
I eard about shared preference but i'm not sure its what i'm looking for and i would need some help to understand how to use it.
This is the class that call the activity where the fruit list is displayed with the checkbox:
public class SelectDoActivity extends AppCompatActivity {
/*Set the instance variable*/
private ImageButton btn_FruitList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_select_do);
btn_FruitList = (ImageButton) findViewById (R.id.btn_FruitList);
/*Create the method that call the activity*/
btn_FruitList.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openFruitList_Activity();
}
});
}
public void openFruitList_Activity() {
Intent intent = new Intent (this, FruitList_Activity.class);
startActivity(intent);
}
}
This is the class that display the fruit list with the check mark.
public class FruitList_Activity extends AppCompatActivity {
private ListView fruitsList;
private ArrayAdapter<String> adapterFruit;
private Button btn_Delete;
private Button btn_SelectAll;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_fruit_list_);
fruitsList = findViewById(R.id.list_Fruits);
fruitsList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
btn_Delete = findViewById (R.id.btn_delete);
CreateActivity.itemsFruit = FileHelper.readData(this);
adapterFruit = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, CreateActivity.itemsFruit);
fruitsList.setAdapter(adapterFruit);
/*button to Remove items*/
btn_Delete.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
SparseBooleanArray checkedItemPositions = fruitsList.getCheckedItemPositions();
int itemCount = fruitsList.getCount();
for(int i=itemCount-1; i >= 0; i--){
if(checkedItemPositions.get(i)){
fruitsList.setItemChecked(i,true);
adapterFruit.remove(CreateActivity.itemsFruit.get(i));
FileHelper.writeData(CreateActivity.itemsFruit, FruitList_Activity.this );
}
}
adapterFruit.notifyDataSetChanged();
}
});
}
}
I've been stuck with this since 2 weeks i would we really like some precious help i'm ne to java and android so thanks for taking the time to explain how to fix this.
I call a view class from my activity. Then the view class calls the same activity. Here is the problem, once the activity comes back up, it won't register any more button pushes.(I'm trying to call another view class. Here is some code:
View Class
public class AnimationView extends View {
Activity myActivity;
//...
public AnimationView(Context context, Activity activity) {
super(context);
//...
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//...
myActivity.setContentView(R.layout.activity_home);
}
}
Home Activity
public class HomeActivity extends AppCompatActivity {
private AnimationView mDrawViewA;
///...
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mDrawViewA = new AnimationView(this,this);
start = (Button) findViewById(R.id.startButton);
//...
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//...
setContentView(mDrawViewA);
//calls more views
//......
});
}
I realize now maybe I should have been calling the view classes in different activities, but I would very much like a get all the view classes working within the same activity.
The problem is you're calling setContentView every time you press the "start" button. This method will overwrite the current layout (if any) with the new value you're setting.
What you can do to get the result you're expecting, which, from what I understand, is to add a new AnimationView to your current layout on every button click, you can try something like this:
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AnimationView animationView = new AnimationView(getApplicationContext());
// I'm using ConstraintLayout as an example, since I don't know exactly what layout you're using
ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
// Set the layout params the way you want
addContentView(animationView, params); // This is where the magic happens
}
});
In short, addContentView is the method you should use when you want to add new views into your activity's root layout.
PS.: It's a terribly bad practice to let the views "know" the activity controlling it. It's always the opposite way around: the activity/fragment knows the view(s) it's controlling.
I have the following OnCreateMethod()
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_siege_main);
mContext = getApplicationContext();
gridview = (GridView) findViewById(R.id.gridview_board);
initialBoard = new Board();
initialBoard.generate(Globals.rand_width,
Globals.rand_height,
Globals.rand_low,
Globals.rand_high);
gridview.setAdapter(new BoardAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//updateGameState(initialBoard);
}
});
updateGameState(initialBoard);
//typography
TextView boardName = (TextView) findViewById(R.id.textview_board_name);
boardName.setText("Uncharted Territory");
Toast.makeText(SiegeMainActivity.this, "Uncharted Territory loaded", Toast.LENGTH_SHORT).show();
Typeface face = Typeface.createFromAsset(getAssets(),
"fonts/calibri-1.ttf");
boardName.setTypeface(face);
TextView pl1Name = (TextView) findViewById(R.id.textViewPlayer1Name);
face = Typeface.createFromAsset(getAssets(),
"fonts/calibri-1.ttf");
pl1Name.setTypeface(face);
TextView pl2Name = (TextView) findViewById(R.id.textViewPlayer2Name);
face = Typeface.createFromAsset(getAssets(),
"fonts/calibri-1.ttf");
pl2Name.setTypeface(face);
}
and my updateGameState() method is like this:
private void updateGameState(Board b) {
int [] vals = b.getLinearVals();
int [] plays = b.getLinearPlays();
int [] score = b.getScore();
int turns = b.getTurns();
Button tile;
//updating board
for(int i=0;i<gridview.getChildCount();i++){
tile = (Button)gridview.getChildAt(i);
tile.setText(""+vals[i]);
if(plays[i]==1)
tile.setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.btn_default_normal_green));
else if (plays[i]==2)
tile.setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.btn_default_normal_blue));
}
//Setting the score
Button pl1Score, pl2Score;
pl1Score = (Button) findViewById(R.id.buttonPlayer1Score);
pl2Score = (Button) findViewById(R.id.buttonPlayer2Score);
pl1Score.setText(""+score[0]);
pl2Score.setText(""+score[1]);
}
When I call updateGameState() in OnCreate after creating the adapter, it should fill the buttons with some values. But it doesn't seem to work. But when I do the same thing on a click (commented out in the click listener), it seems to work fine. I want to populate the values on loading the page. Can somebody help me?
You need to let the GridView know that the data has changed. If you are dynamically changing the data in the ArrayAdapter, you need to call BoardAdapter.notifyDataSetChanged() so the GridView can "refresh" itself with the new data.
In your case, you need to create a reference to you new BoardAdapter and then use that to call the notifyDataSetChange() method.
private BoardAdapter boardAdapter = null;
protected void onCreate(Bundle savedInstanceState) {
// your things
boardAdapter = new BoardAdapter(this);
gridview.setAdapter(boardAdapter);
// more things
}
private void updateGameState(Board b) {
// update your data
boardAdapter.notifyDataSetChanged();
}
Edit: You mentioned in the comment that you tried using an ArrayAdapter and it didn't work for you... maybe try this, which says to use the GridViews invalidateViews() method. gridView.invalidateViews()
Have a look at this SO question & answer here:
How to refresh a GridView?
I had a similar problem, but couldn't get it to even refresh on a button click, even tho items were being changed and added. In my case, the trick, as it turns out, was to recreate the (in your case) BoardAdapter with the new/updated list of items, and then reassign it to the gridview.
gridViewAdapter = new MyGridViewAdapter(this, blah, yourUpdatedItems);
discoverGridView.InvalidateViews();
discoverGridView.Adapter = gridViewAdapter;
I am sure there has to be a better, more reactive, way of doing it, but this at least got my proof of concept up and running.
In my Main.class I am creating a dynamic ScrollView and starting it using setContentView(sv) it displays a Spinner and a Button.
The user selects an option from the Spinner and then clicks the Button. I have set a setOnClickListener to the Button.
In the onClick method I am trying to start up a new ContentView. Calling a new class file with the same type of layout as Main.class. Not sure how to go about doing this. I added finish() to the onClick method and it closes the original window but not sure how to open the new one.
Here is the Main.class code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.messages = new Messages(this);
this.datasource = new FacilitiesDataSource(this);
this.datasource.open();
ScrollView sv = new ScrollView(this);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
sv.addView(ll);
Spinner s = new Spinner(this);
s.setId(SPINNER_FACILITIES);
s.setLayoutParams(new Spinner.LayoutParams(-2,-1));
final List<SpinnerObject> list = this.datasource.getFacilitiesList();
final ArrayAdapter<SpinnerObject> adapter = new ArrayAdapter<SpinnerObject>(this, android.R.layout.simple_spinner_dropdown_item, list);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s.setAdapter(adapter);
ll.addView(s);
Button b = new Button(this);
b.setText("Submit");
b.setLayoutParams(new LayoutParams(-2,-1));
b.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
Spinner spin = (Spinner)findViewById(SPINNER_FACILITIES);
Log.v("option picked", Integer.toString(( (SpinnerObject) spin.getSelectedItem () ).getId () ));
/*
* NEED HELP HERE
* NEED HELP HERE
* NEED HELP HERE
*/
//finish();
}
});
ll.addView(b);
setContentView(sv);
}
Here is my Vehicles.class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v("Started onCreate", "Vehicle");
ScrollView sv = new ScrollView(this);
setContentView(sv);
}
I assume you mean you want to start a new Activity (from Main to Vehicles). In that case you can use the following code:
Intent intent = new Intent(Main.this, Vehicle.class);
startActivity(intent);
Make sure all Activity classes are declared in your Android Manifest file, inside the <application> tag, like this:
<activity android:name=".Vehicles" />
I'm trying to create a view where the user can click a "plus" button, and have additional EditTexts be created. The goal is to have a base of 2 EditTexts, and each time the user clicks the button, add another 2 EditTexts.
How can I do this? I can add EditTexts from Java, but I can't figure out how to add and handle a list of them dynamically.
I was hoping to take however many pairs of EditTexts, and push it into a key/value HashMap or something.
Any ideas of how to do this? Thanks!
public class MyActivity extends Activity {
private LinearLayout main;
private int id = 0;
private List<EditText> editTexts = new ArrayList<EditText>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
main = new LinearLayout(this);
main.setOrientation(LinearLayout.VERTICAL);
Button addButton = new Button(this);
addButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
addEditText();
}
});
Button submit = new Button(this);
submit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
for (EditText editText : editTexts) {
editText.getText().toString();
// whatever u want to do with the strings
}
}
});
main.addView(addButton);
main.addView(submit);
setContentView(main);
}
private void addEditText() {
LinearLayout editTextLayout = new LinearLayout(this);
editTextLayout.setOrientation(LinearLayout.VERTICAL);
main.addView(editTextLayout);
EditText editText1 = new EditText(this);
editText1.setId(id++);
editTextLayout.addView(editText1);
editTexts.add(editText1);
EditText editText2 = new EditText(this);
editText2.setId(id++);
editTextLayout.addView(editText2);
editTexts.add(editText2);
}
Do it in a ListView.
Then you can just add them to a ListAdapter.
And then use adapter.notifyDatasetChanged()
May be I am not clear but Instead of adding Individual edit text you can add as Group View like Linear layout here you can use any flag values to add dynamic name conversions also.
That view you can update into List View like inflating rows in the List View....