Building my first app and can't find a solution by myself.
What my app does:
MainActivity prompts user to input player amount
presses Ok, input passed to next activity
now I want, that the user is prompted to input the player names, one by one with an AlertDialog. Those names, should be stored in an Array.
My code so far:
public class MainScreen extends AppCompatActivity {
private static final String TAG = MainScreen.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
try {
Intent intent = getIntent();
final int sumPlayers = getIntent().getIntExtra("sumPlayers", 0);
final List<String> playerNames = new ArrayList<>();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
final EditText input = new EditText(getBaseContext());
input.setTextColor(Color.BLACK);
//input.setSingleLine();
for (int c=0; c<sumPlayers; c++) {
builder.setTitle("Input Player Name");
builder.setView(input);
builder.setPositiveButton("ADD", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
playerNames.add(input.getText().toString());
}
});
builder.show();
}
ArrayAdapter<String> playerAdapter = new ArrayAdapter<String>(this, R.layout.player_list_item, R.id.editText, playerNames);
ListView listView = (ListView) findViewById(R.id.listView_main);
listView.setAdapter(playerAdapter);
} catch (Exception e) {
System.out.println("2te Act");
Log.e(TAG, "Error#: ", e);
}
}
}
I get this Exception # builder.show();
Java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
It's working without the for loop except one minor problem.
When I set the input field to setSingleLine(); the listView stays empty.
You are creating a single AlertDialog.Builder and repeatedly setting the title, view, and positive button with different values. You likely need to move this logic inside the for loop:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
final EditText input = new EditText(getBaseContext());
input.setTextColor(Color.BLACK);
//input.setSingleLine();
Related
In this application, I have a listview and a sqlitedatabase. There is a floating action button which on clicking displays a dialog box containing two edittext one for name and another for number. The problem is that the after clicking on the add option of the dialog box the entry is not shown on the listview. But when the activity is destroyed and onCreate is called again on the activity , the entry is shown.
I tried using adapter.notifyDataSetChanged() but it doesn't work. The code is shown below :
Code
public class DetailsActivity extends AppCompatActivity {
private DatabaseManager manager;
private ListView listView;
private SimpleCursorAdapter adapter;
final String[] from=new String[] {UserDatabase.NAME,UserDatabase.NUMBER};
final int[] to=new int[] {R.id.nameDisplay,R.id.phoneDisplay};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
manager = new DatabaseManager(getApplicationContext());
manager.open();
Cursor cursor=manager.fetch();
listView = (ListView) findViewById(R.id.listViewId);
listView.setEmptyView(findViewById(R.id.empty));
adapter = new SimpleCursorAdapter(getApplicationContext(),
R.layout.row_item, cursor, from, to, 0);
adapter.notifyDataSetChanged();
listView.setAdapter(adapter);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(DetailsActivity.this);
LayoutInflater inflater = DetailsActivity.this.getLayoutInflater();
final View dialogView = inflater.inflate(R.layout.custom_dialog, null);
dialogBuilder.setView(dialogView);
final EditText name = (EditText) dialogView.findViewById(R.id.dialogEditNmID);
final EditText phone = (EditText) dialogView.findViewById(R.id.dialogEditPhID);
dialogBuilder.setTitle("Add Details");
dialogBuilder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (!TextUtils.isEmpty(name.getText().toString()) &&
!TextUtils.isEmpty(phone.getText().toString())) {
/*adapter.notifyDataSetChanged();
manager.insert(name.getText().toString(), phone.getText().toString());
Toast.makeText(getApplicationContext(),
"Added " + name.getText().toString(), Toast.LENGTH_SHORT).show();*/
insertData(name.getText().toString(),phone.getText().toString());
} else {
Toast.makeText(getApplicationContext(),
"Empty field(s)", Toast.LENGTH_SHORT).show();
}
}
});
dialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog b = dialogBuilder.create();
b.show();
// listView.setAdapter(adapter);
//adapter.notifyDataSetChanged();
}
});
}
public void insertData(String fname,String phnumber){
manager.insert(fname,phnumber);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
Some of the statements are commented because I tried to get the desired result but couldn't get it.
There's a couple things here you have to change. Taking a look at this code:
dialogBuilder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (!TextUtils.isEmpty(name.getText().toString()) && !TextUtils.isEmpty(phone.getText().toString())) {
adapter.notifyDataSetChanged();
manager.insert(name.getText().toString(), phone.getText().toString());
Toast.makeText(getApplicationContext(), "Added " + name.getText().toString(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Empty field(s)", Toast.LENGTH_SHORT).show();
}
}
});
When you click the "Add" button, right away you call adapter.notifyDataSetChanged();. In your case, you are only supposed to call that after you have added items to listView, but you haven't added anything yet.
You insert into your database using manager.insert(name.getText().toString(), phone.getText().toString());, but you don't update listView with your newly added data. You need to insert that data to the database, and then also add that data to listView.
Now you can call adapter.notifyDataSetChanged();.
I would recommend that when you want to insert into your database, create a method which will insert the data, add the new data to the listView, and then tell the adapter to refresh.
Edit
Regarding your recent edit, there's still a few things that need to be taken care of.
You should not have listView.setAdapter(adapter) in the method. You had it right the first time (in onCreate() but before the dialog builder).
You call manager.insert(fname,phnumber);, but still do not add the newly inserted data to listView.
Here's pseudocode for what you should have in your method:
public void insertData(String fname,String phnumber){
manager.insert(fname,phnumber);
// Code to add the data you just inserted into the manager above to `listView`.
adapter.notifyDataSetChanged();
}
Remember, adapter.notifyDataSetChanged(); only updates listView if there's changes to listView, and as of right now you haven't added/deleted/modified listView.
After you insert the entries in your database, you should fetch the data again so that your list has the newest entry. So you can either modify your code to be able to add a data point to the list you are passing to the adapter or refetch the data from the database after insertions and before notifyDatasetChanged().
i have did some changes into the code please try it and let me know if it is helpful or not
public class DetailsActivity extends AppCompatActivity {
private DatabaseManager manager;
private ListView listView;
private SimpleCursorAdapter adapter;
final String[] from=new String[] {UserDatabase.NAME,UserDatabase.NUMBER};
final int[] to=new int[] {R.id.nameDisplay,R.id.phoneDisplay};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
manager = new DatabaseManager(getApplicationContext());
manager.open();
listView = (ListView) findViewById(R.id.listViewId);
listView.setEmptyView(findViewById(R.id.empty));
adapter = new SimpleCursorAdapter(getApplicationContext(),R.layout.row_item, cursor, from, to, 0);
//adapter.notifyDataSetChanged();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(DetailsActivity.this);
LayoutInflater inflater = DetailsActivity.this.getLayoutInflater();
final View dialogView = inflater.inflate(R.layout.custom_dialog, null);
dialogBuilder.setView(dialogView);
final EditText name = (EditText) dialogView.findViewById(R.id.dialogEditNmID);
final EditText phone = (EditText) dialogView.findViewById(R.id.dialogEditPhID);
dialogBuilder.setTitle("Add Details");
dialogBuilder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (!TextUtils.isEmpty(name.getText().toString()) &&
!TextUtils.isEmpty(phone.getText().toString())) {
adapter.notifyDataSetChanged();
manager.insert(name.getText().toString(), phone.getText().toString());
Toast.makeText(getApplicationContext(),
"Added " + name.getText().toString(), Toast.LENGTH_SHORT).show();
Cursor cursor = manager.fetch();
listView.setAdapter(adapter);
} else {
Toast.makeText(getApplicationContext(),
"Empty field(s)", Toast.LENGTH_SHORT).show();
}
}
});
dialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog b = dialogBuilder.create();
b.show();
// listView.setAdapter(adapter);
//adapter.notifyDataSetChanged();
}
});
}}
Try to use notifyDataSetChanged after insert operation. In all place where you call(try to call) notify manager data isn't change yet.
Context: There is a custom Listview and each list item has a button in it. When you click the button an alertDialog appears with an edit text and submit button. This only happens on the first click, on subsequent clicks a Toast will simply appear with the number of times it has been clicked thus far.
When you click the submit button a toast will appear displaying the text that was entered into the editText and the number of times they have clicked on it which will presumably always be 1 since this can only happen on the first click.
Problem: The timesClicked counter is not working properly if the user so much as clicks on the editText before clicking submit. It is restting to 0 I guess. However if the user does not click on the editText then the program works normally. 0_o I'm at a loss.
Attempts at solving: I simplified the code down quite a bit to try and pinpoint the problem and this is where I am stuck. Originally I was inflating a view that only had an edit text and then I was just using builder.setPositiveButtton. I thought implementing the buttons directly in the view would fix it but that doesn't seem to be the case. I have been stuck on this for awhile. Any help would be great
Here is a video of the bug happening
private class OnSubtractClickListener implements View.OnClickListener {
final int id; //id of list item that was clicked
int timesClicked;
Toast toast;
public OnSubtractClickListener(int id, View view) {
super();
this.id = id;
timesClicked = 0;
}
#Override
public void onClick(View view) {
if (timesClicked != 0) {
toast.setText(Integer.toString(timesClicked));
toast.show();
}
else{
toast = Toast.makeText(view.getContext(), "", Toast.LENGTH_SHORT);
final View dialogView = LayoutInflater.from(view.getContext()).inflate(R.layout.dialog_add_notes, null);
AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());
builder.setView(dialogView);
builder.setTitle("Subtract cigar?");
builder.setIcon(R.mipmap.monkey_launcher);
final AlertDialog dialog = builder.create();
Button yesButton = (Button)dialogView.findViewById(R.id.dialog_notes_yes_button);
yesButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText editText = (EditText)dialogView.findViewById(R.id.dialog_editText);
String userInput = editText.getText().toString();
String timesClickedString = Integer.toString(++timesClicked);
toast.setText(timesClickedString + ": " + userInput);
toast.show();
dialog.dismiss();
}
});
dialog.show(); //new
}
}
}
You can make class that extend Dialog.
example:
public class CustomDialog extends Dialog {
private EditText editText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowManager.LayoutParams lpWindow = new WindowManager.LayoutParams();
lpWindow.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
lpWindow.dimAmount = 0.8f;
getWindow().setAttributes(lpWindow);
setContentView(R.layout.activity_custom_dialog);
editText = (EditText) findViewById(R.id.editText);
}
}
You can use this dialog..
mCustomDialog = new CustomDialog();
mCustomDialog.show();
You can make the layout as you wish.
======================================================================
You can use AlertDialog.Builder.setPositiveButton.
site : setPositiveButton
example...
toast = Toast.makeText(view.getContext(), "", Toast.LENGTH_SHORT);
final View dialogView = LayoutInflater.from(view.getContext()).inflate(R.layout.dialog_add_notes, null);
AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());
builder.setView(dialogView);
builder.setTitle("Subtract cigar?");
builder.setIcon(R.mipmap.monkey_launcher);
builder.setPositiveButton("text", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int which) {
EditText editText = (EditText)dialogView.findViewById(R.id.dialog_editText);
String userInput = editText.getText().toString();
String timesClickedString = Integer.toString(++timesClicked);
toast.setText(timesClickedString + ": " + userInput);
toast.show();
}
});
final AlertDialog dialog = builder.create();
dialog.show(); //new
I found the solution. Basically what was happening was that when the Keyboard appeared it would cause the listview to adjust the size recreating the whole listview with recycled/old versions of the list items from before the dialog appeared -effectively undoing any changes made to the ListView items by the dialog.
In your listview XML add this:
android:descendantFocusability="beforeDescendants"
In Mainfest.xml:
<activity android:name= ".yourActivity"
android:windowSoftInputMode="adjustPan"/>
The way my dialog is set up currently, it is supposed to take the values from the EditTexts and save in into a database (a process simplified through Sugar ORM), then place the newly created SubjectInfo object into the RecyclerView. The way the notifyDataSetChanged(); is included gives me errors concerning the Thread (basically no thread is waiting upon the change in the data set). SO, I have two paths as I see it, but I'm still confused as to how each approach would work.
Option 1: Somehow revoke the onCreate() method in the SubjectManagerActivity so that the adapter responds to the new database. (How to revoke an onCreate method?)
Option 2: Create a custom Dialog Fragment Activity. Does this navigate back up to recreate the parent activity?
Please help explain how to make the notifyDataSetChanged(); respond, because once that line is removed, there are no errors, but I can't see the new Subject card until I restart the app.
Here is my code:
public class SubjectManagerActivity extends ActionBarActivity {
public static ArrayList<SubjectInfo> subjectList = new ArrayList<SubjectInfo>();
public static FloatingActionButton fabCreateSubject;
private AlertDialog.Builder build;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_subject_manager);
RecyclerView recList = (RecyclerView) findViewById(R.id.subject_card_list);
recList.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
recList.setLayoutManager(llm);
subjectList = getSubjectInfoArrayList();
SubjectAdapter sa = new SubjectAdapter(subjectList);
recList.setAdapter(sa);
fabCreateSubject = (FloatingActionButton) findViewById(R.id.fab_create_subject);
fabCreateSubject.setOnClickListener (new View.OnClickListener() {
#Override
public void onClick(View v) {
build = new AlertDialog.Builder(SubjectManagerActivity.this);
LayoutInflater inflater = getLayoutInflater();
View alertview = inflater.inflate(R.layout.create_subject_dialog, null);
// Pass null as the parent view because its going in the dialog layout
build.setView(alertview);
final EditText inputSubjectName = (EditText) alertview.findViewById(R.id.dialog_edit_subject_card_name);
final EditText inputSubjectGrade = (EditText) alertview.findViewById(R.id.dialog_edit_subject_card_grade);
build.setTitle("Add Subject")
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
String enteredSubjectName = inputSubjectName.getText().toString();
boolean enteredSubjectIsArchived = false;
if((!(inputSubjectName.getText().toString().equals("")))) {
SubjectInfo si = new SubjectInfo(enteredSubjectName, enteredSubjectIsArchived);
si.save();
}
dialog.cancel();
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = build.create();
alert.show();
}
});
}
public ArrayList<SubjectInfo> getSubjectInfoArrayList(){
ArrayList<SubjectInfo> sial= new ArrayList<SubjectInfo>();
List<SubjectInfo> sil = SubjectInfo.listAll(SubjectInfo.class);
sial.addAll(sil);
notifyDataSetChanged;
return sial;
}
It turns out often the most effective way to deal with an issue is to trust in your code and research to make it work! For anyone else with a similar issue, I included this code:
si.save();
subjectList.add(si);
sa.notifyDataSetChanged();
The method notifyDataSetChanged(); had to be directed to an adapter, which is the container of the Thread. Though the adapter isn't being populated from the getSubjectInfoArrayList() method in real-time (when the dialog is prompted), the ArrayList is still acquiring the same value and when the app is reopened, it can populate the adapter from the database (and in turn, the same get( ) method).
I am trying to create a pop-up dialog to allow the user of my android app to add a new field to a list on their main page.
I've done a bit of research and found the Dialog/alertDialog option, but i haven't been able to get it working correctly.
Here is my MainActivity class:
public class MainActivity extends Activity {
private ListView listView;
public static ArrayList<String> ArrayofName = new ArrayList<String>();
//final Dialog dialog = new Dialog(this); //!!! ERROR HERE !!! //
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DatabaseHandler db = new DatabaseHandler(this);
Button AddNewStudent = (Button) findViewById(R.id.AddNew);
/**
* CRUD Operations
* */
// Inserting Contacts
Log.d("Insert: ", "Inserting ..");
//db.addStudentProfile(new StudentProfile("Shannon", "White"));
//db.addStudentProfile(new StudentProfile(1,"Shannon", "White", "WhitehousePS", "30", "21" ));
/*AddNewStudent.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
// Using an alertDialog to get the user to enter in a new Student
dialog.setContentView(R.layout.add_new_student);
dialog.setTitle("Add a new student");
final EditText firstName=(EditText)dialog.findViewById(R.id.firstName);
final EditText surname=(EditText)dialog.findViewById(R.id.surname);
final EditText school=(EditText)dialog.findViewById(R.id.school);
final EditText age=(EditText)dialog.findViewById(R.id.age);
Button save=(Button)dialog.findViewById(R.id.save);
Button btnCancel=(Button)dialog.findViewById(R.id.cancel);
dialog.show();
}
});*/
// Reading all contacts
Log.d("Reading: ", "Reading all contacts..");
List<StudentProfile> contacts = db.getAllStudents();
for (StudentProfile studProf : contacts) {
String log = "Id: "+studProf.getID()+" , First name: " + studProf.getFirstName() + ", Surname: " + studProf.getSurname() + ", School: " + studProf.getSchool() +
", Reading Level: "+ studProf.getReadingLevel() + ", Age: " + studProf.getAge();
// Writing Contacts to log
Log.d("Name: ", log);
}
db.getAllStudents();
listView = (ListView) findViewById(R.id.listView1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, ArrayofName);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Toast.makeText(getApplicationContext(),
((TextView) v).getText(), Toast.LENGTH_SHORT).show();
}
});
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(inflater.inflate(R.layout.dialog_signin, null))
// Add action buttons
.setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
// sign in the user ...
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
LoginDialogFragment.this.getDialog().cancel();
}
});
return builder.create();
}
}
It's linked to a very simple xml page that just has editible text fields.
My application won't even open with this code - i have tracked the issue down to this line:
final Dialog dialog = new Dialog(this);
at the top of my program.
IS this the best way to go about making a pop up dialog?
Also, what is the easiest way to pass the information back to the class to be stored in a database?
Any help would be much appreciated, thanks! :)
You can create some private variables at the top of your class, and get the text from the editText and put it into those variables in the dialog's button click handler method (where you have the 'sign in the user' comment.)
Sometimes it's also easyer to crate a dialog themed activity.
why it doesn't display any auto corrections my array got strings
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Sentence");
alert.setMessage("type only words you taught him!!!");
// Set an EditText view to get user input
//final EditText input = new EditText(this);
//alert.setView(input);
// Get a reference to the AutoCompleteTextView in the layout
final AutoCompleteTextView textView = new AutoCompleteTextView(this);
// Get the string array
//String[] countries = getResources().getStringArray(R.array.countries_array);
// Create the adapter and set it to the AutoCompleteTextView
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mywords);
textView.setAdapter(adapter);
alert.setView(textView);
alert.setPositiveButton("Order", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String value =textView.getText().toString();
String[] inputarray;
value=value.trim();
inputarray=value.split(" ");
playnum=new int[inputarray.length];
for(int j=0;j<inputarray.length;j++)
{
legit=0;
for(int i=0;i<mywords.length;i++)
{
if(info.choosetext[Integer.parseInt(mywords[i])].equalsIgnoreCase(inputarray[j])){
playnum[j]=Integer.parseInt(mywords[i]);
legit++;
}
}
if(legit==0)
break;
}
if(legit!=0){
playone=MediaPlayer.create(getBaseContext(), getResources().getIdentifier("word" + Integer.toString(playnum[0]), "raw", getPackageName()));
gottext=true;
}
}
});
alert.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Canceled.
}
});
alert.show();
i want it to display array suggestions and on click input it into the text view and now i am talking just cause i got too much code and can't post
someone got to know how to do this without xml
At least one thing you should do is to declare the autocomplete text view in xml and get a reference to it by calling AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.textView); instead of final AutoCompleteTextView textView = new AutoCompleteTextView (this)
Here is a good tutorial on autocomplete text views:
http://www.tutorialspoint.com/android/android_auto_complete.htm
try this,
textview.setThreshold(1);
after textview.setAdapter()