I had this working in the past, but I made some changes to my code and now, whenever I delete a row from the ListView and click on one of the remaining rows, I am getting IndexOutOfBoundsException: Index: 1, Size: 1.
This only seems to be happening when there is a single row remaining. If there are more than one row remain, this error does not appear.
The image above shows that the when there are more than one row remaining the error does not occur.
I am not sure why this would be happening since none of the code for selecting and deleting a row has changed.
I have checked other posts on this site but none of them seem to be similar to what I am experiencing.
Android IndexOutOfBoundsException: Index: 1, Size: 1
OutOfBoundException index:1, size:1
java jtable removeRow : java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
I have posted my code below.
Logcat:
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.get(ArrayList.java:411)
at ca.rvogl.tpbcui.views.LeagueAdapter$2.onClick(LeagueAdapter.java:116)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Code for selecting a row in the listview:
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
League league = leaguesList.get(position);
int id = league.getId();
String leagueId = String.valueOf(id);
holder.id.setText(leagueId);
holder.name.setText(league.getName());
holder.basescore.setText(league.getBaseScore());
holder.basescorepercentage.setText(league.getBaseScorePercentage());
if (league.getAverage() != "") {
holder.leagueAverage.setText(String.format("League Avg: %s", league.getAverage()));
} else {
holder.leagueAverage.setText(String.format("League Avg: %s", "0"));
}
//Formatting And Displaying Timestamp
holder.timestamp.setText(formatDate(league.getTimestamp()));
holder.buttonViewOption.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//creating a popup menu
PopupMenu popup = new PopupMenu(context, holder.buttonViewOption);
//inflating menu from xml resource
popup.inflate(R.menu.league_options_menu);
//adding click listener
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.profile:
((MainActivity) context).showLeagueDialog(true, leaguesList.get(position), position);
break;
case R.id.delete:
((MainActivity) context).deleteLeague(position);
break;
}
return false;
}
});
//displaying the popup
popup.show();
}
});
holder.name.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int leagueId = leaguesList.get(position).getId();
Intent myIntent = new Intent(context, BowlerActivity.class);
myIntent.putExtra("leagueId", leagueId);
context.startActivity(myIntent);
}
});
}
Code for deleting a row:
//Deleting League From SQLite Database And Removing The League Item From The List By Its Position
public void deleteLeague(int position) {
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "Series will be deleted.", Snackbar.LENGTH_LONG)
.setActionTextColor(Color.YELLOW)
.setAction("OK", new View.OnClickListener() {
#Override
public void onClick(View v) {
//Deleting The League From The Database
db.deleteLeague(leaguesList.get(position));
//Removing League From The List
leaguesList.remove(position);
mAdapter.notifyItemRemoved(position);
toggleEmptyLeagues();
}
});
snackbar.show();
}
The error seems to be happening with this line int leagueId = leaguesList.get(position).getId();
Any help getting this error fixed would be greatly appreciated.
BowlerActivity.java
public class BowlerActivity extends AppCompatActivity {
private BowlerAdapter mAdapter;
private final List<Bowler> bowlersList = new ArrayList<>();
private TextView noBowlersView;
private DatabaseHelper db;
private TextView leagueId;
private String savedLeagueId;
private TextView seriesleagueId;
private String seriesLeagueId;
private TextView bowlerAverage;
private TextView bowlerHandicap;
private String savedBowlerAverage;
private static final String PREFS_NAME = "prefs";
private static final String PREF_BLUE_THEME = "blue_theme";
private static final String PREF_GREEN_THEME = "green_theme";
private static final String PREF_ORANGE_THEME = "purple_theme";
private static final String PREF_RED_THEME = "red_theme";
private static final String PREF_YELLOW_THEME = "yellow_theme";
#Override protected void onResume() {
super.onResume();
db = new DatabaseHelper( this );
mAdapter.notifyDatasetChanged( db.getAllBowlers( savedLeagueId ) );
}
#Override
protected void onCreate(Bundle savedInstanceState) {
//Use Chosen Theme
SharedPreferences preferences = getSharedPreferences( PREFS_NAME, MODE_PRIVATE );
boolean useBlueTheme = preferences.getBoolean( PREF_BLUE_THEME, false );
if (useBlueTheme) {
setTheme( R.style.AppTheme_Blue_NoActionBar );
}
boolean useGreenTheme = preferences.getBoolean( PREF_GREEN_THEME, false );
if (useGreenTheme) {
setTheme( R.style.AppTheme_Green_NoActionBar );
}
boolean useOrangeTheme = preferences.getBoolean( PREF_ORANGE_THEME, false );
if (useOrangeTheme) {
setTheme( R.style.AppTheme_Orange_NoActionBar );
}
boolean useRedTheme = preferences.getBoolean( PREF_RED_THEME, false );
if (useRedTheme) {
setTheme( R.style.AppTheme_Red_NoActionBar );
}
boolean useYellowTheme = preferences.getBoolean( PREF_YELLOW_THEME, false );
if (useYellowTheme) {
setTheme( R.style.AppTheme_Yellow_NoActionBar );
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bowler);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Objects.requireNonNull( getSupportActionBar() ).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(),MainActivity.class));
finish();
overridePendingTransition(0, 0);
}
});
savedLeagueId = String.valueOf(getIntent().getIntExtra("leagueId",2));
leagueId = findViewById(R.id.tvLeagueId);
bowlerAverage = (TextView) findViewById(R.id.tvBowlerAverage);
bowlerHandicap = (TextView) findViewById(R.id.tvBowlerHandicap);
CoordinatorLayout coordinatorLayout = findViewById( R.id.coordinator_layout );
RecyclerView recyclerView = findViewById( R.id.recycler_view );
noBowlersView = findViewById(R.id.empty_bowlers_view);
db = new DatabaseHelper(this);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.add_bowler_fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showBowlerDialog(false, null, -1);
}
});
mAdapter = new BowlerAdapter(this, bowlersList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
//recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16));
recyclerView.setAdapter(mAdapter);
toggleEmptyBowlers();
}
//Inserting New Bowler In The Database And Refreshing The List
private void createBowler(String leagueId, String bowlerName) {
String bowlerAverage = "0";
//Inserting Bowler In The Database And Getting Newly Inserted Bowler Id
long id = db.insertBowler(leagueId, bowlerName, bowlerAverage);
//Get The Newly Inserted Bowler From The Database
Bowler n = db.getBowler(leagueId);
if (n != null) {
//Adding New Bowler To The Array List At Position 0
bowlersList.add( 0, n );
//Refreshing The List
mAdapter.notifyDatasetChanged(db.getAllBowlers(savedLeagueId));
//mAdapter.notifyDataSetChanged();
toggleEmptyBowlers();
}
}
//Updating Bowler In The Database And Updating The Item In The List By Its Position
private void updateBowler(String bowlerName, int position) {
Bowler n = bowlersList.get(position);
//Updating Bowler Text
n.setLeagueId(savedLeagueId);
n.setName(bowlerName);
//Updating The Bowler In The Database
db.updateBowler(n);
//Refreshing The List
bowlersList.set(position, n);
mAdapter.notifyItemChanged(position);
toggleEmptyBowlers();
}
//Deleting Bowler From SQLite Database And Removing The Bowler Item From The List By Its Position
public void deleteBowler(int position) {
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "Series will be deleted.", Snackbar.LENGTH_LONG)
.setActionTextColor(Color.YELLOW)
.setAction("OK", new View.OnClickListener() {
#Override
public void onClick(View v) {
//Deleting The Bowler From The Database
db.deleteBowler(bowlersList.get(position));
//Removing The Bowler From The List
bowlersList.remove(position);
mAdapter.notifyItemRemoved(position);
db.leagueAverageScore(savedLeagueId);
toggleEmptyBowlers();
}
});
snackbar.show();
}
//Opens Dialog With Edit/Delete Options
private void showActionsDialog(final int position) {
LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext());
View view = View.inflate(this, R.layout.dialog_options_1, null);
final AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(new ContextThemeWrapper(BowlerActivity.this, R.style.AppTheme));
alertDialogBuilderUserInput.setView(view);
alertDialogBuilderUserInput.setCancelable(true);
final AlertDialog alertDialog = alertDialogBuilderUserInput.create();
//Cancel
final ImageButton cancel_btn = (ImageButton) view.findViewById(R.id.cancel);
cancel_btn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
alertDialog.cancel();
}
});
//Edit
ImageButton edit_btn = (ImageButton) view.findViewById(R.id.edit);
edit_btn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
showBowlerDialog(true, bowlersList.get(position), position);
alertDialog.dismiss();
}
});
ImageButton delete_btn = (ImageButton) view.findViewById(R.id.delete);
delete_btn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "Bowler will be deleted.", Snackbar.LENGTH_LONG)
.setAction("OK", new View.OnClickListener() {
#Override
public void onClick(View v) {
deleteBowler(position);
}
});
snackbar.show();
alertDialog.dismiss();
}
});
Window window = alertDialog.getWindow();
window.setGravity(Gravity.TOP);
alertDialog.show();
}
//Show Alert Dialog With EditText Options to Enter/Edit A League
//When shouldUpdate = true, It Will Automatically Display Old Bowler Name And Change The Button Text To UPDATE
public void showBowlerDialog(final boolean shouldUpdate, final Bowler bowler, final int position) {
LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext());
final View view = View.inflate(this, R.layout.dialog_bowler, null);
AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(new ContextThemeWrapper(BowlerActivity.this, R.style.AppTheme));
alertDialogBuilderUserInput.setView(view);
alertDialogBuilderUserInput.setCancelable(true);
leagueId.setText(savedLeagueId);
final EditText inputBowlerName = view.findViewById(R.id.etBowlerNameInput);
TextView dialogTitle = view.findViewById(R.id.dialog_title);
dialogTitle.setText(!shouldUpdate ? getString(R.string.lbl_new_bowler_title) : getString(R.string.lbl_edit_bowler_title));
if (shouldUpdate && bowler != null) {
leagueId.setText(bowler.getLeagueId());
inputBowlerName.setText(bowler.getName());
}
alertDialogBuilderUserInput
.setCancelable(false)
.setPositiveButton(shouldUpdate ? "update" : "save", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogBox, int id) {
}
})
.setNegativeButton("cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogBox, int id) {
dialogBox.cancel();
}
});
ImageView bowlerName = (ImageView) view.findViewById (R.id.ivBowlerName);
bowlerName.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
AlertDialog.Builder bowlerName = new AlertDialog.Builder(BowlerActivity.this);
bowlerName.setMessage("Enter the name of the bowler to hold your new scores.");
bowlerName.setCancelable(true);
bowlerName.create();
bowlerName.show();
}
});
final AlertDialog alertDialog = alertDialogBuilderUserInput.create();
alertDialog.show();
alertDialog.getButton( AlertDialog.BUTTON_POSITIVE).setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
//Show Toast Message When No Text Is Entered
if (TextUtils.isEmpty(inputBowlerName.getText().toString())) {
Snackbar.make( view, "Enter Bowler Name", Snackbar.LENGTH_LONG )
.setAction( "Action", null ).show();
return;
} else {
alertDialog.dismiss();
}
//Check If User Is Updating Bowler
if (shouldUpdate && bowler != null) {
//Updating Bowler By Its Id
updateBowler(inputBowlerName.getText().toString(), position);
} else {
//Creating New Bowler
createBowler(leagueId.getText().toString(), inputBowlerName.getText().toString());
}
}
});
}
//Toggling List And Empty Bowler View
private void toggleEmptyBowlers() {
//You Can Check bowlerList.size() > 0
if (db.getBowlersCount() > 0) {
noBowlersView.setVisibility( View.GONE);
} else {
noBowlersView.setVisibility( View.VISIBLE);
}
}
#Override
public void onRestart() {
super.onRestart();
//When BACK BUTTON is pressed, the activity on the stack is restarted
//Do what you want on the refresh procedure here
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate( R.menu.menu_main, menu );
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
overridePendingTransition(0, 0);
return true;
}
return super.onOptionsItemSelected( item );
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
//Check If Request Code Is The Same As What Is Passed - Here It Is 1
if(requestCode==1)
{
String savedLeagueId=data.getStringExtra("seriesLeagueId");
String seriesBowlerId=data.getStringExtra("seriesBowlerId");
bowlersList.addAll(db.getAllBowlers(savedLeagueId));
}
}
#Override
public void onBackPressed() {
startActivity(new Intent(getApplicationContext(),MainActivity.class));
finish();
overridePendingTransition(0, 0);
}
}
This is the line that it is complaining about. This worked perfectly before I move the onClick() to the adapter.
savedLeagueId = String.valueOf(getIntent().getIntExtra("leagueId",2));
I am really hoping that someone can help me get this issue resolved. I have tried several different approaches from other stackoverflow posts and I am still not able to resolve it.
mAdapter.notifyItemRemoved(position);
Means that the adapter will shift and animate items up. However, the items will not be redrawn.
You can observe that by clicking on the last item of your list after deleting any item: you should see the same crash.
And by clicking on any item after the one you deleted (except the last one), the details view should show the next item instead of the one you clicked.
The issue is that position is no longer relevant, because the indices have changed. Instead use the value for leagueId that you already have in your binder. Simply remove the int leagueId that is shadowing the String leagueId and that should work as expected.
The problem is that the view was already bind and the position at this method:
holder.name.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
int leagueId = leaguesList.get(position).getId(); // here position will still be 1 after deletion
//...
}
});
belongs to the old index. To fix it, use the same object you fot previously.
holder.name.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int leagueId = league.getId(); //league object will be the same
//...
}
});
****Try This****
#Override
protected void onBindViewHolder(#NonNull final BoardsViewHolder holder, final int position, #NonNull final Board model) {
holder.setTitle(model.getBoardTitle());
holder.setDesc(model.getBoardDesc());
holder.setDate(model.getCreatedOn());
holder.mDeleteBoardButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder alert = new AlertDialog.Builder(mContext);
alert.setTitle("Delete Board");
alert.setMessage("This Board will be deleted forever");
alert.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
final ProgressDialog loading = new ProgressDialog(mContext);
loading.setMessage("Deleting...");
loading.show();
getSnapshots().getSnapshot(position).getReference().delete().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()){
notifyDataSetChanged();
loading.dismiss();
}else {
loading.dismiss();
Toast.makeText(mContext,"Something went wrong please try again later",Toast.LENGTH_LONG).show();
}
}
});
}
});
alert.setNegativeButton("Keep", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alert.show();
}
});
This is the problem of zero based elements. Your code is trying to access an non existing element index. Launch your app in debug mode and line by line see what is happening. Android studio has an excellent debugger built-in, so it is very easy to go step by step and see what is happening with your variables.
Related
When I run my app and go to the "EditProfile" activity. And then, I will immediately receive the toast message "Something is wrong" which means, the variables "selectedCountry", "selectedAge", and "selectedGender" are null.
public class EditProfile extends AppCompatActivity {
UserInfo userInfo;
UserInfo profileDetails;
Spinner spinnerFrom;
Spinner spinnerAge;
Spinner spinnerGender;
EditText hobbyEdit;
Button btnDone;
TextView textView;
String selectedCountry;
String selectedAge;
String selectedGender;
DatabaseHelper mydb = new DatabaseHelper(this, "MyUsers", null, 5);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_profile);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), Profile.class);
intent.putExtra("id", userInfo.getId());
intent.putExtra("username", userInfo.getUsername());
startActivity(intent);
}
});
Bundle extras = getIntent().getExtras();
int id = extras.getInt("id");
final String username = extras.getString("username");
// Username
userInfo = new UserInfo(id, username);
textView = (TextView) findViewById(R.id.usernameUnedit);
textView.setText(username);
// Country
spinnerFrom = (Spinner) findViewById(R.id.spinnerFrom);
Locale[] locales = Locale.getAvailableLocales();
final ArrayList<String> countries = new ArrayList<String>();
countries.add("-");
for (Locale locale : locales) {
String country = locale.getDisplayCountry();
if (country.trim().length() > 0 && !countries.contains(country)) {
countries.add(country);
}
}
Collections.sort(countries);
ArrayAdapter<String> countryAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, countries);
countryAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerFrom.setAdapter(countryAdapter);
spinnerFrom.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedCountry = parent.getItemAtPosition(position).toString();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
// Age
spinnerAge = (Spinner) findViewById(R.id.spinnerAge);
final ArrayList<String> ages = new ArrayList<String>();
ages.add("-");
for (int i = 18; i < 100; i++) {
ages.add(String.valueOf(i));
}
ArrayAdapter<String> ageAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, ages);
ageAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerAge.setAdapter(ageAdapter);
spinnerAge.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedAge = parent.getItemAtPosition(position).toString();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
// Gender
spinnerGender = (Spinner) findViewById(R.id.spinnerGender);
final ArrayList<String> genders = new ArrayList<String>();
genders.add("-");
genders.add("Male ♂");
genders.add("Female ♀");
genders.add("Other");
ArrayAdapter<String> genderAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, genders);
genderAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerGender.setAdapter(genderAdapter);
spinnerGender.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedGender = parent.getItemAtPosition(position).toString();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
// Hobby
hobbyEdit = (EditText) findViewById(R.id.hobbyEdit);
// Button done
btnDone = (Button) findViewById(R.id.btnDone);
btnDone.setEnabled(false);
/* Stuck at this if statement below */
if (selectedCountry != null && selectedAge != null && selectedGender != null) {
if (!mydb.isStoredProfileDetails(username, selectedCountry, selectedAge, selectedGender, hobbyEdit.getText().toString())) {
btnDone.setEnabled(true);
btnDone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
profileDetails = new UserInfo(selectedCountry, selectedAge, selectedGender, hobbyEdit.getText().toString());
mydb.updateTable(username, profileDetails);
}
});
} else {
Toast.makeText(this, "Something is wrong 2.", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(this, "Something is wrong.", Toast.LENGTH_LONG).show();
}
}
}
I expect that after choosing an item from those 3 dropdown lists (spinners) and the values of the chosen items do not exist in database, then the "Done" button would be clickable. Once the button is clicked, it would store the selected values from the dropdown lists (spinners) into database by updating it.
Unfortunately, I am stuck at the if statement as stated in the given code as it keeps returning the "else" statement.
Set your variable as...
String selectedCountry = "";
String selectedAge = "";
String selectedGender = "";
And check condition as...
if (!selectedCountry.equals("") && !selectedAge.equals("") && !selectedGender.equals("")) {
//your code goes here
}
You have to check your both conditions in Spinner's OnItemSelectedListener, If both conditions will return true then enable your button. and call setonClickListener on button in onCreateView, like this.
spinnerGender.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedGender = parent.getItemAtPosition(position).toString();
//Conditions to enable button
if (selectedCountry != null && selectedAge != null && selectedGender != null) {
if (!mydb.isStoredProfileDetails(username, selectedCountry, selectedAge, selectedGender, hobbyEdit.getText().toString())) {
btnDone.setEnabled(true);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
add these lines in all spinners.
In your onCreate method, you have instantiated the views and attached listeners to them. That is perfectly fine. However, this does not mean that the logic in those listeners will be execute at the same time and order. You have just defined the behaviour of the listeners. After all that initialisation, your code directly checks the values of the three Strings mentioned in your question. It does not wait for a user to interact with the spinners.
What you want is to trigger the change in the "done" button when a user selects something from the spinner. So the logic of setting the strings and thereby checking if you could enable the "done" button must go in the listeners of the spinners.
I am not giving you a direct code solution to the problem, but an approach which you could employ.
I have kind of to-do app. In profile activity, there are 2 tabs.
To-do and Done. In Tab 1, user can check as "done" of their "to-do". In this case, I want to update TAB 2's recyclerview.
I tried several things, but didn't work. Here is TAB 1 codes, it's almost same as TAB 2.
TAB 1 Class
public class Tab_Profile_1 extends Fragment {
private RecyclerView recyclerView_tab_todo;
private List<Model_ListItem> itemList;
private Adapter_Profile_ToDo adapter_profile_toDo;
SharedPreferences mSharedPref;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_profile_tab_1, container, false);
//TO-DO
//
recyclerView_tab_todo = view.findViewById(R.id.recyclerView_tab_todo);
//
fetchUserToDo();
return view;
}
public void fetchUserToDo() {
itemList = new ArrayList<>();
//First Settings
mSharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
String session_user_id = mSharedPref.getString("session_user_id", "");
API_Service api_service = Client.getRetrofitInstance().create(API_Service.class);
Call<List<Model_ListItem>> call = api_service.fetchUserToDo(session_user_id);
call.enqueue(new Callback<List<Model_ListItem>>() {
#Override
public void onResponse(Call<List<Model_ListItem>> call, Response<List<Model_ListItem>> response) {
itemList = response.body();
adapter_profile_toDo = new Adapter_Profile_ToDo(getContext(), itemList);
recyclerView_tab_todo.setHasFixedSize(true);
LinearLayoutManager layoutManager
= new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
recyclerView_tab_todo.setLayoutManager(layoutManager);
recyclerView_tab_todo.setAdapter(adapter_profile_toDo);
}
#Override
public void onFailure(Call<List<Model_ListItem>> call, Throwable t) {
}
});
}}
TAB 1 RecyclerView Adapter
public class Adapter_Profile_ToDo extends RecyclerView.Adapter {
private Context context;
private List<Model_ListItem> itemList;
private String url_extension_images = URL_Extension.url_extension_images;
SharedPreferences mSharedPref;
ProgressDialog progressDialog;
View view;
public Adapter_Profile_ToDo(Context context, List<Model_ListItem> itemList) {
this.context = context;
this.itemList = itemList;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_profile_todo, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, final int position) {
Glide.with(context).load(url_extension_images + itemList.get(position).getItem_image()).into(holder.imageView_profile_todo);
holder.textView_profile_todo_name.setText(itemList.get(position).getItem_name());
holder.textView_profile_todo_desc.setText(itemList.get(position).getItem_description());
holder.layout_profile_todo_detail.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//detail
}
});
holder.layout_profile_todo_add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final AlertDialog.Builder builder = new AlertDialog.Builder(view.getRootView().getContext(), R.style.AlertStyle);
builder.setTitle("\"" + itemList.get(position).getItem_name() + "\"" + "\n");
builder.setIcon(R.drawable.ic_bookmark);
builder.setPositiveButton("YAPTIM", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
showProgressDialog();
addDone("" + itemList.get(position).getItem_id(), position);
}
});
builder.setNegativeButton("SİL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
showProgressDialog();
deleteUserToDo("" + itemList.get(position).getItem_id(), position);
}
});
builder.setNeutralButton("İptal", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.show();
}
});
}
#Override
public int getItemCount() {
return itemList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView_profile_todo;
TextView textView_profile_todo_name, textView_profile_todo_desc;
LinearLayout layout_profile_todo_detail, layout_profile_todo_add;
public ViewHolder(View itemView) {
super(itemView);
imageView_profile_todo = itemView.findViewById(R.id.imageView_profile_todo);
textView_profile_todo_name = itemView.findViewById(R.id.textView_profile_todo_name);
textView_profile_todo_desc = itemView.findViewById(R.id.textView_profile_todo_desc);
layout_profile_todo_detail = itemView.findViewById(R.id.layout_profile_todo_detail);
layout_profile_todo_add = itemView.findViewById(R.id.layout_profile_todo_add);
}
}
public void deleteUserToDo(final String listId, final int clicked) {
mSharedPref = PreferenceManager.getDefaultSharedPreferences(context);
String session_user_id = mSharedPref.getString("session_user_id", "");
API_Service api_service = Client.getRetrofitInstance().create(API_Service.class);
Call<Response_Success> call = api_service.deleteUserToDo(session_user_id, listId);
call.enqueue(new Callback<Response_Success>() {
#Override
public void onResponse(Call<Response_Success> call, Response<Response_Success> response) {
if (response.code() == 200) {
if (progressDialog.isShowing()) {
progressDialog.dismiss();
progressDialog = null;
}
if (response.body().getSuccess().matches("true")) {
Toast.makeText(context, "Silindi!", Toast.LENGTH_SHORT).show();
itemList.remove(itemList.get(clicked));
notifyItemRemoved(clicked);
notifyItemRangeChanged(clicked, itemList.size());
} else {
Toast.makeText(context, "Bilinmeyen bir hata oluştu!", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onFailure(Call<Response_Success> call, Throwable t) {
Toast.makeText(context, "Bilinmeyen bir hata oluştu!", Toast.LENGTH_SHORT).show();
}
});
}
public void addDone(String listId, final int clicked) {
mSharedPref = PreferenceManager.getDefaultSharedPreferences(context);
String session_user_id = mSharedPref.getString("session_user_id", "");
API_Service apiService = Client.getRetrofitInstance().create(API_Service.class);
Call<Response_Success> call = apiService.addDone(session_user_id, listId);
call.enqueue(new Callback<Response_Success>() {
#Override
public void onResponse(Call<Response_Success> call, Response<Response_Success> response) {
if (response.code() == 200) {
if (progressDialog.isShowing()) {
progressDialog.dismiss();
progressDialog = null;
}
if (response.body().getSuccess().matches("true")) {
Toast.makeText(context, "Eklendi", Toast.LENGTH_SHORT).show();
itemList.remove(itemList.get(clicked));
notifyItemRemoved(clicked);
notifyItemRangeChanged(clicked, itemList.size());
} else {
Toast.makeText(context, "Bilinmeyen bir hata oluştu!", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onFailure(Call<Response_Success> call, Throwable t) {
}
});
}
public void showProgressDialog() {
progressDialog = new ProgressDialog(view.getRootView().getContext());
progressDialog.setMessage("Yükleniyor");
progressDialog.setCancelable(false);
progressDialog.show();
}
}
If i'm reading this correctly, you have two tabs and a backend database that stores the to do items and their state? To get the second list to update, you just need to do the same thing that you're doing in your first list, and update the adapter's data set and notify that the data set changed. How you trigger this action in your second tab is really the question.
You can either use an interface and have your adapter notify your activity that recycler view 1 had an action on it, and you can then tell adapter 2 to update its data. You can either pass back the data and only notify one row, or you could notify the entire data set. If you're doing this all service based, you could just reload the recycler view from the service and it will have the new data.
I think all you need to figure out is how you want to notify tab 2 that it needs to update its data. My recommendation is:
public interface AdapterInterface
{
void itemCompleted(Item hereIsTheItemThatNeedsToBeAddedTo2);
}
Then inside your adapter have a property with getters/setters such as:
private AdapterInterface adapterInterfaceListener;
Inside your Fragment/Activity implement AdapterInterface and implement the itemCompleted function.
And then set your adapter.setAdapterInterfaceLisetener to that function that you implemented. Then inside your adapter when the user clicks the checkbook to mark it as done, you can call the adapterInterfaceListener.itemCompleted() function, and it will send that information to your Fragment/Activity. From there you can give that new data to adapter2, or recall the API, however you want to get the new data.
Does this help?
I have a list of items that are displayed in a recylcerview in my adapter class i implmented a onlongclick method, when used it opens up a new alertdialog, when i press on the selected item in the alterdialog im calling updateList() function that is supposed to update the selected item the problem is this only works for the first item displayed in my list, so in exmaple if i pressed the 10th item on the list said item wont update.
Update function
public boolean updateList(long rowId, String stanje) {
ContentValues newValues = new ContentValues();
newValues.put(TABELA_STOLPEC_STANJE,stanje);
return db.update(TABELA_IME,newValues,TABELA_STOLPEC_ID+"="+rowId,null)>0;
}
OnlongClickListener this method is in my fragment class.
mmAdapter.setOnLongClick(new ToDoRecyclerViewAdapter.OnLongClickListener_() {
#Override
public void onLongClick(long i,String item) {
if(item.equals("doing")) {
boolean update_1 = db.updateList(i, item);
if(update_1) {
android.support.v4.app.FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(TodoFragment.this).attach(TodoFragment.this).commit();
Toast.makeText(getContext(), "Dodano v bazo.!", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(getContext(), "Prislo je do napake!", Toast.LENGTH_SHORT).show();
}
}
}
});
onlongclicklistener implementation in my adapter class
holder.mView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(final View v) {
AlertDialog.Builder adb = new AlertDialog.Builder(v.getContext());
CharSequence meni[] = new CharSequence[] {"DOING"};
adb.setItems(meni, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
if(i == 0) {
mValues.get(i).setStanje("doing");
clickLinster_.onLongClick(mValues.get(position).getId_(),mValues.get(position).getStanje());
}
}
});
AlertDialog alertDialog = adb.create();
alertDialog.setCancelable(true);
alertDialog.show();
return true;
}
});
public interface OnLongClickListener_ {
void onLongClick(long i, String item);
}
The reason is simple, you are updating wrong row with index, correct solution:
#Override
public void onBindViewHolder(#NonNull final CustomViewHolder holder, int position) {
//Rest of onBindViewHolder code
holder.mView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(final View v) {
final int pos = holder.getAdapterPosition();
AlertDialog.Builder adb = new AlertDialog.Builder(v.getContext());
CharSequence meni[] = new CharSequence[] {"DOING"};
adb.setItems(meni, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
if(i == 0) {
mValues.get(pos).setStanje("doing");
clickLinster_.onLongClick(mValues.get(pos).getId_(),mValues.get(pos).getStanje());
}
}
});
AlertDialog alertDialog = adb.create();
alertDialog.setCancelable(true);
alertDialog.show();
return true;
}
});
}
I have a list that I saved in sharedpreferences I want to delete an item from the listview when the user longclicks so on the long click the app prompts you with a question to delete or not when you confirm it deletes it. This works but when i come back to the activity the list still contains that item that has been deleted
This is the code for the onCreateView. tinyDB is sharedprefrences.Thank you
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_tab_secondsemester, container, false);
btnAddNew = (Button)rootView.findViewById(R.id.btnAddNewYearOneSecondSemester);
listView = (ListView)rootView.findViewById(R.id.listViewSubjectsMyCoursesSecondSemester);
tinyDB = new TinyDB(getContext());
storedList = new ArrayList<>(tinyDB.getListString("storedList"));
generalList = new ArrayList<>();
spinnerValues = new ArrayList<>();
getActivity().setTitle("Year One");
setHasOptionsMenu(true);
btnAddNew.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getContext(),R.style.DialogeTheme);
// Setting Dialog Title
alertDialog.setTitle("Add new");
// Setting Dialog Message
String getUsername = tinyDB.getString("Username");
alertDialog.setMessage("Hello "+ getUsername + ", please write the new subject");
final EditText input = new EditText(getContext());
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
input.setLayoutParams(lp);
input.setTextColor(Color.parseColor("#f06292"));
alertDialog.setView(input);
alertDialog.setPositiveButton("Add", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
String getSubjectInput = input.getText().toString();
storedList.add(getSubjectInput);
tinyDB.putListString("storedList", storedList);
arrayAdapter.notifyDataSetChanged();
}
});
alertDialog.setNegativeButton("CANCEL",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Write your code here to execute after dialog
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.create();
alertDialog.show();
}
});
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(final AdapterView<?> adapterView, View view, final int i, long l) {
new SweetAlertDialog(getContext(), SweetAlertDialog.WARNING_TYPE)
.setTitleText("Delete")
.setContentText("Are you sure you want to delete this course")
.setConfirmText("YES")
.setCancelText("NO")
.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
#Override
public void onClick(SweetAlertDialog sweetAlertDialog) {
storedList.remove(i);
arrayAdapter.notifyDataSetChanged();
tinyDB.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
arrayAdapter.notifyDataSetChanged();
}
});
sweetAlertDialog.dismiss();
}
})
.setCancelClickListener(new SweetAlertDialog.OnSweetClickListener() {
#Override
public void onClick(SweetAlertDialog sweetAlertDialog) {
sweetAlertDialog.dismiss();
}
})
.show();
return true;
}
});
arrayAdapter = new CustomListAdapter(getContext(),storedList);
listView.setAdapter(arrayAdapter);
arrayAdapter.notifyDataSetChanged();
return rootView;
}
Use this when the user deletes it
public void removeAt(int position) {
mDataset.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mDataSet.size());
}
mDataset is the array/list in which you save all the data for the adapter
I have a arraylist in which users can input their text. And it is displayed in the screen as a listview. That works, but when i try to get the values of the arraylist it says that: Invalid index 0, size is 0. So im guessing for some reason the listview isnt populating?
This is how I add values to the list:
public class ZaidejaiActivity extends ActionBarActivity implements View.OnClickListener{
public Button mBtnIstrinti;
public Button mBtnPrideti;
public Button mBtnPradeti;
public EditText mYrasytiVarda;
public ListView mZaidejai;
ArrayList<String> list = new ArrayList<String>();
ArrayAdapter<String> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zaidejai);
mBtnPrideti = (Button) findViewById(R.id.pridėtiBtn);
mBtnPrideti.setOnClickListener(this);
mYrasytiVarda = (EditText) findViewById(R.id.VardoYrasymoBtn);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, list);
// set the mZaidejai variable to your list in the xml
mZaidejai = (ListView) findViewById(R.id.sarašas);
mZaidejai.setAdapter(adapter);
mZaidejai.setOnItemClickListener(new AdapterView.OnItemClickListener() {
// remove item from List.
#Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
list.remove(position);
AlertDialog.Builder builder = new AlertDialog.Builder(ZaidejaiActivity.this);
builder.setMessage("Delete?");
builder.setTitle("Confirm Action");
builder.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
adapter.notifyDataSetChanged();
}
//checked.clear();
});
builder.setNegativeButton("Cancel", null);
builder.create();
builder.show();
}
});
mBtnPradeti = (Button) findViewById(R.id.žaistiBtn);
mBtnPradeti.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// count items
int i;
for (i = adapter.getCount() - 1; i >= 0; i--) {
String obj = adapter.getItem(i);
// send items to other activity
Intent pradetiZaidima = new Intent(v.getContext(), ZaidimasActivity.class);
pradetiZaidima.putExtra("playerList", obj);
startActivity(pradetiZaidima);
}
}
});
}
#Override
public void onClick(View v) {
String input = mYrasytiVarda.getText().toString();
if(input.length() > 0)
{
// add string to the adapter, not the listview
adapter.add(input);
// no need to call adapter.notifyDataSetChanged(); as it is done by the adapter.add() method
}else{
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Klaida:");
alertDialog.setMessage("Blogai yrašytas vardas");
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// here you can add functions
}
});
alertDialog.show();
}
}
EDIT
In this activity I want to get the values of the list:
public class ZaidimasActivity extends ZaidejaiActivity {
public TextView mZaidejas;
public TextView mKlausimas;
public Button mKitasKlausimas;
public Button mGryzti;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zaidimas);
/** //get the player list from ZaidejaiActivity
Bundle recdData = getIntent().getExtras();
String myVal = recdData.getString("playerList"); */
//show the first players name
mZaidejas = (TextView)findViewById(R.id.ZaidejoVardas);
mZaidejas.setText(list.get(0));
/** mGryzti = (Button)findViewById(R.id.GryztiMeniuBtn);
mKitasKlausimas = (Button)findViewById(R.id.KitasBtn);
mKitasKlausimas.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
*/
Unfortunately your list==empty. So add some values on it.
list.add("ABC");
list.add("XYZ");
and then setAdapter
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, list);
mZaidejai = (ListView) findViewById(R.id.sarašas);
mZaidejai.setAdapter(adapter);
Your not adding any values to it. And your list is empty and add some values to it like list.add("hyd");
list.add("city");
and pass those values to adapter
Rather doing
adapter.add(input);
Do
list.add(input);
adapter.notifyDataSetChanged();
So, as others have said you should change the adapter.add(input); on the onClick method to
list.add(input);
adapter.notifyDataSetChanged();
Also, on an unrelated matter, you should really move the list.remove(position); call to the following onClick method of the positive button, before the adapter.notifyDataSetChanged(); call, so it wont be removed if the user cancels the action :)
at the first time your list adapter is empty (getCount() = 0) and you do -1 in the for
mBtnPradeti.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// count items
int i;
if (adapter.getCount() > 0)
{
for (i = adapter.getCount() - 1; i >= 0; i--) {
String obj = adapter.getItem(i);
// send items to other activity
Intent pradetiZaidima = new Intent(v.getContext(), ZaidimasActivity.class);
pradetiZaidima.putExtra("playerList", obj);
startActivity(pradetiZaidima);
}
}
}
});
and for this code :
mZaidejas.setText(list.get(0));
but on Create your list is empty !!!