从中删除项目后,ListView 不是 "refreshing"
ListView not "refreshing" after item is deleted from it
我想弄清楚当我的列表视图中的项目被删除时,我如何 "Refresh" 用户所在的列表视图。我已经尝试过 notifyDataSetChanged() 但无济于事,这让我感到困惑,因为这在我添加项目时有效。
P.S。我知道该项目正在被删除,因为如果我按下后退按钮并再次进入我的 activity,该项目将从列表视图中直观地删除。
public void deleteButtonClicked(View view){
dbHandler.deleteExerciseFromDatabase(exerciseClickedbyUser, workoutClicked);
exerciseListView.setAdapter(edsAdapter);
edsAdapter.notifyDataSetChanged();
Toast.makeText(getBaseContext(),"Exercise Deleted", Toast.LENGTH_SHORT).show();
}
当我在模拟器中 运行 时,Toast 确实出现了。
public class CustomExerciseAdapter 扩展 ArrayAdapter{
public CustomExerciseAdapter(Context context, ArrayList<String> workouts) {
super(context, R.layout.exercise_custom_row, workouts);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View customView = inflater.inflate(R.layout.exercise_custom_row, parent, false);
String singleExerciseItem = getItem(position);
TextView exerciseTV = (TextView) customView.findViewById(R.id.exerciseTV);
exerciseTV.setText(singleExerciseItem);
return customView;
}
这是我的 class,其中包含 deleteButtonClicked
public class ExercisesSection extends ActionBarActivity {
private EditText userWorkoutInput;
private Button addNewWorkoutButton;
private CustomExerciseAdapter edsAdapter;
private ArrayList<String> itemHold;
private MyDBHandler dbHandler;
private String workoutClicked;
private String exerciseClickedbyUser;
private ListView exerciseListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_exercises_section);
initViews();
handleIntentData();
inputTextHandler();
loadDataFromDatabase();
}
//This method initializes all the views
public void initViews(){
userWorkoutInput = (EditText) findViewById(R.id.userWorkoutInput);
addNewWorkoutButton = (Button) findViewById(R.id.addNewWorkoutButton);
exerciseListView = (ListView) findViewById(R.id.exerciseListView);
itemHold = new ArrayList<String>();
dbHandler = new MyDBHandler(this,null,null,1);
}
//This method makes the "Add new workout Button" clickable or not depending on user input
public void inputTextHandler(){
userWorkoutInput.addTextChangedListener(
new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
boolean isEmpty = false;
if ((userWorkoutInput.getText().toString().trim()).equals("")) {
isEmpty = true;
}
addNewWorkoutButton.setEnabled(!isEmpty);
}
@Override
public void afterTextChanged(Editable s) {
}
}
);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
THIS IS THE BUTTON LISTENER FOR @id+/addNewWorkoutButton
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
public void addWorkoutButtonClicked(View view){
String input = (userWorkoutInput.getText().toString().trim());
if (!input.equals("")){
addItemToList(input);
userWorkoutInput.setText(""); //Empties the edit text section
saveDataToDatabase(input);
}
}
public void saveDataToDatabase(String input){
//GIVE THE EXERCISES OBJ VALUES!
Exercises exercises = new Exercises(input, workoutClicked);
dbHandler.addExerciseToDatabase(exercises);
}
public void loadDataFromDatabase(){
String exerName = dbHandler.getExercisesForBodyParts(workoutClicked);
//IF STATEMENT WEEDS OUT EMPTY DATA
if(!(exerName.trim().equals(""))) {
String delim = ",";
String[] tokens = exerName.split(delim);
for (int i = 0; i < tokens.length; i++) {
addItemToList(tokens[i]);
}
}
}
public void addItemToList(String input){
itemHold.add(input);
edsAdapter = new CustomExerciseAdapter(this, itemHold);
exerciseListView.setAdapter(edsAdapter);
edsAdapter.notifyDataSetChanged();
exerciseListView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
exerciseClickedbyUser = String.valueOf(parent.getItemAtPosition(position));
textClicked(view, exerciseClickedbyUser); //starts intent and sends to Exercise Clicked Activity
}
}
);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method is an onClick Method from exercise_custom_row.xml
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
public void deleteButtonClicked(View view){
dbHandler.deleteExerciseFromDatabase(exerciseClickedbyUser, workoutClicked);
itemHold.remove(exerciseClickedbyUser);
edsAdapter.notifyDataSetChanged();
Toast.makeText(getBaseContext(),"Exercise Deleted", Toast.LENGTH_SHORT).show();
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method gets the data (name of section clicked) from MainActivity
and changes the textView in exercise_section accordingly
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
public void handleIntentData(){
Bundle workoutData = getIntent().getExtras();
if (workoutData == null){
return;
}
workoutClicked = workoutData.getString("exerciseChosen");
TextView exerciseChosenText = (TextView) findViewById(R.id.exerciseChosenText);
exerciseChosenText.setText(workoutClicked);
exerciseChosenText.setTypeface(null, Typeface.BOLD);
}
public void textClicked(View view, String exercise){
Intent i = new Intent(this, ExerciseClicked.class);
i.putExtra("exerciseClicked", exercise);
startActivity(i);
}
在我的应用程序中,我根本不使用 notifyDataSetChanged
。要刷新 ListView,我只需 运行 再次查询数据库 并使用 CursorAdapter.changeCursor
。它会根据需要自动调用notifyDataSetChanged
。
您的项目正在从数据库中删除,但列表视图未更新visually.Setting适配器是一个解决方案,但它会从头开始重置列表,这对于用户一直滚动的体验来说不是很好again.You 当您从数据库中删除项目时可以做一件事,同时您可以从列表中删除选定的项目。我认为您的列表视图侦听器在 activity:
中应该如下所示
listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
deleteButtonClicked(postion);
}
});
public void deleteButtonClicked(int position){
int count=dbHandler.deleteExerciseFromDatabase(exerciseClickedbyUser, workoutClicked);
if(count>0){
list.remove(position);
edsAdapter.notifyDataSetChanged();
Toast.makeText(getBaseContext(),"Exercise Deleted", Toast.LENGTH_SHORT).show();
}
}
您在列表视图中似乎没有变化,因为您分配给适配器的 ArrayList 或 Array 没有变化。请也从 ArrayList 或数组中删除该项目。你只需要调用 notifyDataSetChanged() 。即,不需要再次调用 listview.setAdapter(adapter)。
编辑:
请用下面显示的代码替换您的 customArrayAdapter
private ArrayList<String> workouts;
public CustomExerciseAdapter(Context context, ArrayList<String> workouts) {
super(context, R.layout.exercise_custom_row, workouts);
this.workouts = workouts;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View customView = inflater.inflate(R.layout.exercise_custom_row, parent, false);
/////here change to
String singleExerciseItem = (String)workouts.get(position);
TextView exerciseTV = (TextView) customView.findViewById(R.id.exerciseTV);
exerciseTV.setText(singleExerciseItem);
return customView;
}
public void setList(ArrayList<String> workouts){
this.workouts = workouts;
notifyDatasetChanged();
}
}
在您的删除方法中,更新数据库和列表后,调用 adapter.setList(workouts)。它可能会帮到你。
感谢大家的帮助,但最后我得出的答案与你们的大相径庭。我最终使用了他的方法 [1]: http://jmsliu.com/2444/click-button-in-listview-and-get-item-position.html/ "here" 这对我来说绝对完美。无论如何,这就是那些可能 运行 遇到同样问题的人所做的。
将此代码粘贴到位于 .JAVA 文件中的 GetView() 方法中使 XML 文件膨胀。
Button deleteButton = (Button) customView.findViewById(R.id.deleteButton);
deleteButton.setTag(position);
然后将其添加到您的按钮点击侦听器/ onClick 方法中
int position = (Integer) view.getTag();
list.remove(position);
adapter.notifyDataSetChanged();
删除项目后始终添加以下两行
notifyDataSetChanged();
notifyDataSetInvalidated();
notifydatasetchanged 将查看列表中的任何更改
notifydatasetinvalidated 将检查是否有任何项目被删除,然后它将更新列表
您可以使用以下代码从适配器中完美删除项目。
mCollection.remove(position);
mListLayout.removeAllViews();
notifyDataSetChanged();
我想弄清楚当我的列表视图中的项目被删除时,我如何 "Refresh" 用户所在的列表视图。我已经尝试过 notifyDataSetChanged() 但无济于事,这让我感到困惑,因为这在我添加项目时有效。
P.S。我知道该项目正在被删除,因为如果我按下后退按钮并再次进入我的 activity,该项目将从列表视图中直观地删除。
public void deleteButtonClicked(View view){
dbHandler.deleteExerciseFromDatabase(exerciseClickedbyUser, workoutClicked);
exerciseListView.setAdapter(edsAdapter);
edsAdapter.notifyDataSetChanged();
Toast.makeText(getBaseContext(),"Exercise Deleted", Toast.LENGTH_SHORT).show();
}
当我在模拟器中 运行 时,Toast 确实出现了。
public class CustomExerciseAdapter 扩展 ArrayAdapter{
public CustomExerciseAdapter(Context context, ArrayList<String> workouts) {
super(context, R.layout.exercise_custom_row, workouts);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View customView = inflater.inflate(R.layout.exercise_custom_row, parent, false);
String singleExerciseItem = getItem(position);
TextView exerciseTV = (TextView) customView.findViewById(R.id.exerciseTV);
exerciseTV.setText(singleExerciseItem);
return customView;
}
这是我的 class,其中包含 deleteButtonClicked
public class ExercisesSection extends ActionBarActivity {
private EditText userWorkoutInput;
private Button addNewWorkoutButton;
private CustomExerciseAdapter edsAdapter;
private ArrayList<String> itemHold;
private MyDBHandler dbHandler;
private String workoutClicked;
private String exerciseClickedbyUser;
private ListView exerciseListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_exercises_section);
initViews();
handleIntentData();
inputTextHandler();
loadDataFromDatabase();
}
//This method initializes all the views
public void initViews(){
userWorkoutInput = (EditText) findViewById(R.id.userWorkoutInput);
addNewWorkoutButton = (Button) findViewById(R.id.addNewWorkoutButton);
exerciseListView = (ListView) findViewById(R.id.exerciseListView);
itemHold = new ArrayList<String>();
dbHandler = new MyDBHandler(this,null,null,1);
}
//This method makes the "Add new workout Button" clickable or not depending on user input
public void inputTextHandler(){
userWorkoutInput.addTextChangedListener(
new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
boolean isEmpty = false;
if ((userWorkoutInput.getText().toString().trim()).equals("")) {
isEmpty = true;
}
addNewWorkoutButton.setEnabled(!isEmpty);
}
@Override
public void afterTextChanged(Editable s) {
}
}
);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
THIS IS THE BUTTON LISTENER FOR @id+/addNewWorkoutButton
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
public void addWorkoutButtonClicked(View view){
String input = (userWorkoutInput.getText().toString().trim());
if (!input.equals("")){
addItemToList(input);
userWorkoutInput.setText(""); //Empties the edit text section
saveDataToDatabase(input);
}
}
public void saveDataToDatabase(String input){
//GIVE THE EXERCISES OBJ VALUES!
Exercises exercises = new Exercises(input, workoutClicked);
dbHandler.addExerciseToDatabase(exercises);
}
public void loadDataFromDatabase(){
String exerName = dbHandler.getExercisesForBodyParts(workoutClicked);
//IF STATEMENT WEEDS OUT EMPTY DATA
if(!(exerName.trim().equals(""))) {
String delim = ",";
String[] tokens = exerName.split(delim);
for (int i = 0; i < tokens.length; i++) {
addItemToList(tokens[i]);
}
}
}
public void addItemToList(String input){
itemHold.add(input);
edsAdapter = new CustomExerciseAdapter(this, itemHold);
exerciseListView.setAdapter(edsAdapter);
edsAdapter.notifyDataSetChanged();
exerciseListView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
exerciseClickedbyUser = String.valueOf(parent.getItemAtPosition(position));
textClicked(view, exerciseClickedbyUser); //starts intent and sends to Exercise Clicked Activity
}
}
);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method is an onClick Method from exercise_custom_row.xml
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
public void deleteButtonClicked(View view){
dbHandler.deleteExerciseFromDatabase(exerciseClickedbyUser, workoutClicked);
itemHold.remove(exerciseClickedbyUser);
edsAdapter.notifyDataSetChanged();
Toast.makeText(getBaseContext(),"Exercise Deleted", Toast.LENGTH_SHORT).show();
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method gets the data (name of section clicked) from MainActivity
and changes the textView in exercise_section accordingly
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
public void handleIntentData(){
Bundle workoutData = getIntent().getExtras();
if (workoutData == null){
return;
}
workoutClicked = workoutData.getString("exerciseChosen");
TextView exerciseChosenText = (TextView) findViewById(R.id.exerciseChosenText);
exerciseChosenText.setText(workoutClicked);
exerciseChosenText.setTypeface(null, Typeface.BOLD);
}
public void textClicked(View view, String exercise){
Intent i = new Intent(this, ExerciseClicked.class);
i.putExtra("exerciseClicked", exercise);
startActivity(i);
}
在我的应用程序中,我根本不使用 notifyDataSetChanged
。要刷新 ListView,我只需 运行 再次查询数据库 并使用 CursorAdapter.changeCursor
。它会根据需要自动调用notifyDataSetChanged
。
您的项目正在从数据库中删除,但列表视图未更新visually.Setting适配器是一个解决方案,但它会从头开始重置列表,这对于用户一直滚动的体验来说不是很好again.You 当您从数据库中删除项目时可以做一件事,同时您可以从列表中删除选定的项目。我认为您的列表视图侦听器在 activity:
中应该如下所示listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
deleteButtonClicked(postion);
}
});
public void deleteButtonClicked(int position){
int count=dbHandler.deleteExerciseFromDatabase(exerciseClickedbyUser, workoutClicked);
if(count>0){
list.remove(position);
edsAdapter.notifyDataSetChanged();
Toast.makeText(getBaseContext(),"Exercise Deleted", Toast.LENGTH_SHORT).show();
}
}
您在列表视图中似乎没有变化,因为您分配给适配器的 ArrayList 或 Array 没有变化。请也从 ArrayList 或数组中删除该项目。你只需要调用 notifyDataSetChanged() 。即,不需要再次调用 listview.setAdapter(adapter)。
编辑:
请用下面显示的代码替换您的 customArrayAdapter
private ArrayList<String> workouts;
public CustomExerciseAdapter(Context context, ArrayList<String> workouts) {
super(context, R.layout.exercise_custom_row, workouts);
this.workouts = workouts;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View customView = inflater.inflate(R.layout.exercise_custom_row, parent, false);
/////here change to
String singleExerciseItem = (String)workouts.get(position);
TextView exerciseTV = (TextView) customView.findViewById(R.id.exerciseTV);
exerciseTV.setText(singleExerciseItem);
return customView;
}
public void setList(ArrayList<String> workouts){
this.workouts = workouts;
notifyDatasetChanged();
}
}
在您的删除方法中,更新数据库和列表后,调用 adapter.setList(workouts)。它可能会帮到你。
感谢大家的帮助,但最后我得出的答案与你们的大相径庭。我最终使用了他的方法 [1]: http://jmsliu.com/2444/click-button-in-listview-and-get-item-position.html/ "here" 这对我来说绝对完美。无论如何,这就是那些可能 运行 遇到同样问题的人所做的。
将此代码粘贴到位于 .JAVA 文件中的 GetView() 方法中使 XML 文件膨胀。
Button deleteButton = (Button) customView.findViewById(R.id.deleteButton);
deleteButton.setTag(position);
然后将其添加到您的按钮点击侦听器/ onClick 方法中
int position = (Integer) view.getTag();
list.remove(position);
adapter.notifyDataSetChanged();
删除项目后始终添加以下两行
notifyDataSetChanged();
notifyDataSetInvalidated();
notifydatasetchanged 将查看列表中的任何更改 notifydatasetinvalidated 将检查是否有任何项目被删除,然后它将更新列表
您可以使用以下代码从适配器中完美删除项目。
mCollection.remove(position);
mListLayout.removeAllViews();
notifyDataSetChanged();