So I am creating a custom AlertDialog using the Builder. I have a custom view I am inflating in the dialog with the following layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<EditText android:id="#+id/edit_username"
style="#style/EditPassword"
android:hint="#string/login_username_hint" />
<EditText android:id="#+id/edit_password"
style="#style/EditPassword"
android:hint="#string/login_password_hint" />
</LinearLayout>
The android:layout_height style for the EditText controls is set to "wrap_content". When I show the dialog with this custom view the dialog is stretched to fill the height of the entire screen. No matter what I set the layout_height on the LinearLayout to (including hardcoded pixel values), it still fills the entire screen on my emulator.
I'm hoping there's something simple that I'm missing here?
EDIT: I looked in the Hierarchy Viewer and the layout I included in this question is correctly defined, but it is wrapped within a FrameLayout within a FrameLayout, and the outermost FrameLayout is set to "wrap_content" but is rendering in the Viewer with a bunch of empty space below it.
EDIT 2: As requested, the code that inflates the layout.
protected Dialog onCreateDialog(int id) {
switch(id) {
case AUTHENTICATION_DIALOG:
LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
final View loginView = inflater.inflate(R.layout.login_dialog, null);
return new AlertDialog.Builder(HomeActivity.this)
.setTitle("Upload profile data")
.setView(loginView)
.setPositiveButton("Upload", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
EditText userName = (EditText)loginView.findViewById(R.id.edit_username);
EditText password = (EditText)loginView.findViewById(R.id.edit_password);
String userNameStr = StringUtils.convertToTrimmedString(userName.getText());
String passwordStr = StringUtils.convertToTrimmedString(password.getText());
if (userNameStr.equals("") || passwordStr.equals("")) {
new AlertDialog.Builder(HomeActivity.this)
.setTitle("Required fields missing")
.setMessage("You must enter a username and password")
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
HomeActivity.this.showDialog(AUTHENTICATION_DIALOG);
dialog.dismiss();
}
}).show();
} else {
dialog.dismiss();
} // end if user entered username and password
} // end "Upload" onClick
}) // end setPositiveButton DialogInterface.OnClickListener()
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
} // end "Cancel" onClick
}).create();
default:
return null;
}
}
So I switched to using a RelativeLayout like so:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<EditText android:id="#+id/edit_username"
style="#style/EditPassword"
android:hint="#string/login_username_hint" />
<EditText android:id="#+id/edit_password"
style="#style/EditPassword"
android:layout_below="#+id/edit_username"
android:hint="#string/login_password_hint" />
</RelativeLayout>
and it works fine. I switched back to Linear to test and it exhibited the old broken behavior when I switched back to the LinearLayout. I'm going to leave this answer unmarked in the hopes that someone can tell me why it's freaking out over LinearLayout vs Relative.
Related
I would like to enable or disable the OK (POSITIVE) button of the AlertDialog with a custom layout such that I can:
Disable the OK button initially
Enable the OK button when all required fields have been entered
Disable the OK button again if a required field has been cleared
Perform validation after the OK button is selected and prevent dismissal upon validation errors
Assume the AlertDialog layout is as follows with one required field description and one optional field age:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<EditText
android:id="#+id/description"
android:hint="Field is required"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="#id/age" />
<EditText
android:id="#+id/age"
android:hint="Optional"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#id/description"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Assume I have a button to kick off the dialog
Button b = findViewById(R.id.main_button);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e(TAG,"button");
View viewcustom = getLayoutInflater().inflate(R.layout.customdialog,null);
EditText edt1 = viewcustom.findViewById(R.id.description);
EditText edt2 = viewcustom.findViewById(R.id.age);
// render alertdialog
}
});
Here is the code. I created a custom layout with 2 EditText fields and require only 1 to be entered. The first is treated as just text that must be present and the second is treated as an optional Age. The final example shows how to add validation and to "not dismiss" after OK is pressed and validation fails.
The OK button is initially disabled and when data is entered in the first text field the OK button is enabled.
By controlling the enable/disable of the positive (OK) button it requires the user to the enter fields necessary (rather than giving them an error when omitted).
Note that when the user clears the same field the OK button is disabled.
You can also add a hint to the EditText field(s) to indicate required (shown in second example).
Note that this was used as reference for the EditText listening (as I linked to in comment).
Finally, the last demo shows if you really wanted to show an error on field validation after the OK button is enabled and pressed. (From here.)
This should be obvious how to expand it to all your EditText fields. And bear in mind you can an condition to enabling the OK button - here it is just at least one character.
Button b = findViewById(R.id.main_button);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e(TAG,"button");
View viewcustom = getLayoutInflater().inflate(R.layout.customdialog,null);
EditText edt1 = viewcustom.findViewById(R.id.description);
EditText edt2 = viewcustom.findViewById(R.id.age);
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(MainActivity.this)
.setView(viewcustom)
.setPositiveButton("Ok", (dialogInterface, i) -> {
String d = edt1.getText().toString();
String a = edt2.getText().toString();
Toast.makeText(MainActivity.this,d, Toast.LENGTH_LONG).show();
});
alertDialog.setNegativeButton("Cancel", null);
AlertDialog ad = alertDialog.create();
edt1.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence sequence, int i, int i1, int i2) {}
#Override
public void onTextChanged(CharSequence sequence, int i, int i1, int i2) {}
#Override
public void afterTextChanged(Editable editable) {
if (edt1.getText().length() > 0) {
// if user enters anything then enable - modify criteria as desired
ad.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
} else {
// if user deletes entry then back to disabled
ad.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false);
}
}
});
// Initially OK button is disabled.
ad.show();
ad.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false);
}
});
And demo:
You can also add a hint to each field to indicate it is required if nothing is entered as in :
<EditText
android:id="#+id/description"
android:hint="Field is required"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="#id/age" />
Finally, if you really, really want to allow the OK but then do further validation to display errors then add the following. Note that the second field is treated as an Age field and the data entered must be an integer. A bit contrived but used to show an example.
// add this after the AlertDialog create()
ad.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface anInterface) {
Button b = ad.getButton(DialogInterface.BUTTON_POSITIVE);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// do some validation on edit text
String s = edt2.getText().toString();
try {
Integer age = Integer.valueOf(s);
Toast.makeText(MainActivity.this,d+":"+age, Toast.LENGTH_LONG).show();
ad.dismiss();
} catch (Exception e) {
// complain
Toast.makeText(MainActivity.this, "Age must be an integer", Toast.LENGTH_LONG).show();
}
}
});
}
});
And demo of requiring the optional Age to be an integer:
Ok so I am trying change my background of my dialog box from white to a dark blue. However when I long press on one of the grid elements the dialog box looks like this:
I am trying to make it look something like this (this is a photoshop):
Here is snipet of my XML code for the edit dialog
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:background="#color/customBG">
Java code for custom dialog
#Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.edit_game_dialog,null);
editTitle = view.findViewById(R.id.editTitle);
editTitle.setText(currentTitle);
imageView = view.findViewById(R.id.item_image_dialog);
imageView.setImageResource(currentImage);
changeImageBt = view.findViewById(R.id.change_image);
changeImageBt.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
}
});
builder.setView(view).setTitle("Edit game")
.setPositiveButton("Apply Changes", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialogInterface, int i)
{
String title = editTitle.getText().toString();
int image = R.drawable.blank; //PLACE HOLDER CODE
editGameDialogListener.applyChanges(pos,title,image);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialogInterface, int i)
{
}
});
return builder.create();
}
I think you should use Dialog instead of AlertDialog.
Alert Dialog has its own Title and Button.
With Dialog you will have the benefit of defining your Title and Buttons.
Create a Layout as your design needs and set it in Dialog.
class ABC(context: Context) : Dialog(context) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.your_custom_layout)
}
}
When you create your dialog, you can pass theme as a second param
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.MyDialogTheme);
and set the custom theme to override anything you need. For background color something like this should work:
<style name="MyDialogTheme" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="android:background">#color/customBG</item>
</style>
I am working on android application in my application there are registration page in that page i am using #slackid, when user fill the registration form and enter slack id without # its show validation message like # is necessary. Than he move to the next. Kindly please tell me how i use this # validation message. Here is the code
activity_registration.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:context=".RegisterActivity">
<EditText
android:id="#+id/name_reg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Your Name"/>
<EditText
android:id="#+id/email_reg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Your email id"
android:inputType="textEmailAddress"/>
<EditText
android:id="#+id/slackid_reg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint=" #slackId"/>
<EditText
android:id="#+id/password_reg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:hint="Password"/>
<EditText
android:id="#+id/confirm_password_reg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:hint="Retype Password"/>
<EditText
android:id="#+id/info_reg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Information/Phone no/Optional"/>
<Button
android:id="#+id/register_reg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/colorAccent"
android:text="Register"/>
</LinearLayout>
RegistrationActivity.java
public class RegisterActivity extends AppCompatActivity implements View.OnClickListener {
private EditText name,emailId,slackId,password,conPasword,info;
private Button registerB;
// Alert dialog
AlertDialog.Builder alertBuilder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
name = findViewById(R.id.name_reg);
emailId = findViewById(R.id.email_reg);
slackId = findViewById(R.id.slackid_reg);
password = findViewById(R.id.password_reg);
conPasword = findViewById(R.id.confirm_password_reg);
info = findViewById(R.id.info_reg);
registerB = findViewById(R.id.register_reg);
//set register to onClick event
registerB.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.register_reg:
// Check all requir field empty or not
//Apply the validation in each field including slack Id
if(name.getText().toString().length()==0) {
name.setError("Name cannot be blank");
}
if(emailId.getText().toString().equals("")) {
emailId.setError("Email cannot be blank");
}
if(String.valueOf(slackId.getText().toString().charAt(0)).equals("#")) {
slackId.setError("Slack id cannot be blank");
}
if (password.getText().toString().equals("")) {
password.setError("password cannot be blank");
}
if(conPasword.getText().toString().equals("")) {
conPasword.setError("confirm password cannot be blank");
// if any of the required field empty "Show Dialog to fill the required field
alertBuilder = new AlertDialog.Builder(RegisterActivity.this);
alertBuilder.setTitle("Something Wrong");
alertBuilder.setMessage("Please Fill all required field");
alertBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
AlertDialog alertDialog = alertBuilder.create();
alertDialog.show();
}else if(!(password.getText().toString().equals(conPasword.getText().toString()))){
//check pasword and confirm pasword mismatch
alertBuilder = new AlertDialog.Builder(RegisterActivity.this);
alertBuilder.setTitle("Something Wrong");
alertBuilder.setMessage("Pasword Mismatch");
alertBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
password.setText("");
conPasword.setText("");
}
});
AlertDialog alertDialog = alertBuilder.create();
alertDialog.show();
}else{
// Background task to insert user information into database
BackgroundLoginTask backgroundLoginTask = new BackgroundLoginTask(RegisterActivity.this);
backgroundLoginTask.execute("register",name.getText().toString(),
emailId.getText().toString(),
slackId.getText().toString(),
password.getText().toString(),
info.getText().toString());
}
break;
}
}
}
Try :
edittext.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if(!edittext.getText().toString().contains("#")) {
edittext.setError("# not detected");
}
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void afterTextChanged(Editable s) {
}
});
If you want something that the id should start with # then can use this pattern : ^#.*
You can blank validation by using TextUtils.isEmpty(slackId.getText().toString())
This will check if text is null or empty
In your code you did validation like
if(String.valueOf(slackId.getText().toString().charAt(0)).equals("#")) {
slackId.setError("Slack id cannot be blank");
}
this will not validate weather is contains # or not.
do this:
if(!slackId.getText().toString().contains("#")){
//show your error message here
}
Hope it will help you!!
You can make a validation like
if(!slackId.getText().toString().contains("#")){}
You can use this as its better than using textChange listener for your case to check the text edit after losing focus , which will give you the needed validation without submitting .
EditText ed= (EditText) findViewById(R.id.edittxt);
ed.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus && !ed.getText().toString().contains("#")) {
ed.setError("# not detected")
}
}
});
I have the following method where I must confirm the user's password before he is allowed to access the Setup menu. To do so, I make him login again because Parse (my cloud storage) doesn't allow me to confirm passwords. So far so good. The problem is when I inflate the view to my AlertDialog to use a custom button and EditText. You can see in my code below that I have commented the Button section, because when I try to get the onClickListener it doesn't work. It just does nothing. So I'm currently using the alertDialogPositiveButton and it's ok. The second problem and the real one is that I cannot retrieve the data insert into the editText. The SUpassword3is always equals to blank, not null. Can someone please help?
method:
public void confirmPassword(){
final LayoutInflater inflateSetup = getLayoutInflater();
AlertDialog.Builder alertSetup = new AlertDialog.Builder(this);
alertSetup.setView(inflateSetup.inflate(R.layout.inflate_setup, null));
alertSetup.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
System.out.println("User has clicked the [confirm] button");
View viewInflate_setup = inflateSetup.inflate(R.layout.inflate_setup, null);
edtPassword3 = (EditText)viewInflate_setup.findViewById(R.id.edtPassword3);
SUpassword3 = edtPassword3.getText().toString();
final ParseUser beforeConfirmPassword = ParseUser.getCurrentUser();
ParseUser.logInInBackground(beforeConfirmPassword.getUsername(), SUpassword3, new LogInCallback() {
#Override
public void done(ParseUser parseUser, ParseException e) {
if(e==null){
//password confirmed, logout last user and go to next setup
System.out.println("Password [" +SUpassword3+ "] and user [" +beforeConfirmPassword.getUsername()+ "] confirmed, logout last user and go to setup");
beforeConfirmPassword.logOut();
}else{
//passwords don't match
System.out.println("Password don't match: [" +SUpassword3 + "] USER [" +beforeConfirmPassword.getUsername()+ "]");
}
}
});
}
});
final AlertDialog dialogSetup = alertSetup.create();
dialogSetup.show();
/**
btnConfirmPassowod = (Button)viewInflate_setup.findViewById(R.id.btnConfirm);
btnConfirmPassowod.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
System.out.println("User has clicked the [confirm] button");
final ParseUser beforeConfirmPassword = ParseUser.getCurrentUser();
ParseUser.logInInBackground(beforeConfirmPassword.getUsername(), SUpassword3, new LogInCallback() {
#Override
public void done(ParseUser parseUser, ParseException e) {
if(e==null){
//password confirmed, logout last user and go to next setup
System.out.println("Password confirmed, logout last user and go to setup");
beforeConfirmPassword.logOut();
}else{
//passwords don't match
dialogSetup.dismiss();
Snackbar.make(v, "Wrong password, try again.", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
}
});
}
}); */
}
inflate_setup.xml(the xml file I inflate on the alertDialog)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:ems="10"
android:id="#+id/edtPassword3"
android:layout_gravity="center_horizontal"
android:hint="#string/EN_txt.confirmPassword"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="New Button"
android:id="#+id/btnConfirm"
android:layout_gravity="center_horizontal" />
</LinearLayout>
Final version(working):
public void confirmPassword(){
final LayoutInflater inflateSetup = getLayoutInflater();
final View viewInflate_setup = inflateSetup.inflate(R.layout.inflate_setup, null);
AlertDialog.Builder alertSetup = new AlertDialog.Builder(this);
alertSetup.setView(viewInflate_setup);
alertSetup.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
System.out.println("User has clicked the [confirm] button");
edtPassword3 = (EditText)viewInflate_setup.findViewById(R.id.edtPassword3);
SUpassword3 = edtPassword3.getText().toString();
...
You inflate another view inside your onClickListener. That's why you actually check text of another edtPassword3, not that one which visible for user. It should be something like that:
View view = inflateSetup.inflate(R.layout.inflate_setup;
final EditText edtPassword3 = (EditText)viewInflate_setup.findViewById(R.id.edtPassword3);
alertSetup.setView(view, null));
alertSetup.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
System.out.println("User has clicked the [confirm] button");
SUpassword3 = edtPassword3.getText().toString();
....
Try to use: Dialog class
// custom dialog
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.custom);
dialog.setTitle("Title...");
Get a reference of the inflated view:
View dialogView = inflateSetup.inflate(R.layout.inflate_setup, null);
In dialog use:
alertSetup.setView(dialogView);
Then, access button using:
Button myButton = (Button) dialogView.findViewById(R.id.btnConfirm);
Making a to-do list. Having 2 issues, The not so important issue is that for some reason I can't see the TextView's that I set up as "labels". The more important thing is that when I click the create new task button, my alert pops up, I can put values in my EditText boxes, but when I hit create, it crashes and I get a NullPointer exception saying I'm trying to call getText() on a null object reference. I can't figure out if I'm inflating incorrectly or if I'm not linking the EditTexts to the alert properly. The annoying thing is that my edittext alert box works just fine editing existing list items(that I hardcoded for testing). Here's my layout and activity, I commented the line in which it breaks. Sorry about all the Log.d's I'm really trying to visualize how all this works.
The Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<EditText
android:layout_width="55dp"
android:layout_height="wrap_content"
android:inputType="number"
android:ems="10"
android:id="#+id/txtCreatePriority"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="25dp"
android:hint="1"
android:textAlignment="center" />
<EditText
android:layout_width="235dp"
android:layout_height="wrap_content"
android:id="#+id/txtCreateItemContent"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/txtCreatePriority"
android:layout_toEndOf="#+id/txtCreatePriority"
android:layout_marginLeft="15dp"
android:hint="Do Laundry"
android:textAlignment="center" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Priority"
android:id="#+id/lblPriority"
android:layout_above="#+id/txtCreatePriority"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="17dp"
android:textStyle="bold"
android:textSize="23dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Task to-do"
android:id="#+id/lblItemContent"
android:layout_above="#+id/txtCreateItemContent"
android:layout_toRightOf="#+id/lblPriority"
android:layout_toEndOf="#+id/lblPriority"
android:layout_marginLeft="65dp"
android:textStyle="bold"
android:textSize="23dp" />
</RelativeLayout>
The Activity
public class MainActivity extends AppCompatActivity {
private ListDataSource ds;
private ListView listViewToDo;
private Button btnAddNew;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Context context = this;
Log.d("MainActivity","Attempting to create data source");
try {
ds = new ListDataSource();
}
catch(Exception e)
{
e.printStackTrace();
Log.d("MainActivity","Failed to create data source");
}
btnAddNew = (Button)findViewById(R.id.btnAddNew);
Log.d("Main Activity","Attempting to link empty list view to on screen view");
listViewToDo = (ListView)findViewById(R.id.listOfLists);
Log.d("Main Activity", "Views linked, Attempting to set adapter to listView");
listViewToDo.setAdapter(new ListDataSourceAdapter(this, ds));
Log.d("Main Activity", "Successfully set Adapter");
btnAddNew.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("addItem", "Entered onclick, Attempting to create AlertDialog");
AlertDialog.Builder addItem = new AlertDialog.Builder(context);
Log.d("addItem", "AlertDialog Built, attempting to create inflater");
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
addItem.setView(inflater.inflate(R.layout.create_item_layout, null));
Log.d("addItem", "inflater built linking text boxes");
final TextView txtCreatePriority = (TextView)findViewById(R.id.txtCreatePriority);
final TextView txtCreateCellContent = (TextView)findViewById(R.id.txtCreateItemContent);
final TextView lblPriority = (TextView)findViewById(R.id.lblPriority);
final TextView lblItemContent = (TextView)findViewById(R.id.lblItemContent);
addItem.setTitle("Create new item");
addItem
.setCancelable(false)
.setPositiveButton("Create", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.d("editText onClick", "in onClick method, preparing to add entry");
// This is where the code breaks
ds.getList().add(Integer.valueOf(txtCreatePriority.getText().toString()), new CellContent(Integer.valueOf(txtCreatePriority.getText().toString()) + 1, txtCreateCellContent.getText().toString().trim()));
Log.d("editText onClick", "added new entry");
ListDataSourceAdapter adapter = new ListDataSourceAdapter(context, ds);
Log.d("editText onClick", "reestablished link to adapter");
listViewToDo.setAdapter(adapter);
Log.d("editText onClick", "adapter set");
adapter.notifyDataSetChanged();
Log.d("editText onClick", "DataSetChanged");
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alertDialog = addItem.create();
alertDialog.show();
}
});
// add button listener
listViewToDo.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id)
{
AlertDialog.Builder editItem = new AlertDialog.Builder(context);
final EditText edittext = new EditText(context);
editItem.setTitle("Change item");
editItem
.setMessage("Set new todo item")
.setView(edittext)
.setCancelable(false)
.setPositiveButton("Submit", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
Log.d("editText onClick","in onClick method, preparing to remove previous entry");
ds.getList().remove(position);
Log.d("editText onClick", "removed previous entry");
ds.getList().add(position, new CellContent(position + 1, edittext.getText().toString().trim()));
Log.d("editText onClick", "added new entry");
ListDataSourceAdapter adapter = new ListDataSourceAdapter(context,ds);
Log.d("editText onClick","reestablished link to adapter");
listViewToDo.setAdapter(adapter);
Log.d("editText onClick", "adapter set");
adapter.notifyDataSetChanged();
Log.d("editText onClick", "DataSetChanged");
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alertDialog = editItem.create();
alertDialog.show();
}
});
}
}
The Error
java.lang.NullPointerException: Attempt to invoke virtual method 'android.text.Editable android.widget.EditText.getText()' on a null object reference
You're calling "(EditText)v.findViewById" on the view v.
The view v is the view passed back in the onClickListener, which is the button itself.
Since that button does not contain the EditTexts within it, those views are null. And crash when you try to access them.
I'm a little uncertain where the layout with the edit texts is in this code. Is it in the same layout as the listview, or in create_item_layout?
If its create_item_layout, that needs to be inflated before getting the EditTexts. Use the view you inflate to findViewById.