Android ListView 在 saveButton 之后没有更新,而是在 onItemSelected 之后更新

Posted

技术标签:

【中文标题】Android ListView 在 saveButton 之后没有更新,而是在 onItemSelected 之后更新【英文标题】:Android ListView is not updating after saveButton, but after onItemSelected 【发布时间】:2016-07-12 18:12:38 【问题描述】:

我目前正在开发一款适用于学校的 android 应用程序。我已经查看了论坛并尝试自己解决问题,但我似乎无法弄清楚为什么当我按下保存按钮时我的 ListView 不会自动更新。我实际上必须在更新之前按下下拉菜单并选择和项目。谁能看看它,让我知道我做错了什么?

谢谢!

activity_main.xml

<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/GridLayout1"
android:layout_
android:layout_
android:columnCount="1"
android:orientation="horizontal"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.physicalactivitytracker.MainActivity" >

<Spinner
    android:id="@+id/activityDropDown"
    android:layout_
    android:layout_
    android:layout_gravity="start"
    android:background="@android:drawable/btn_dropdown"
    android:entries="@array/activity_array"
    android:spinnerMode="dropdown" >

    <requestFocus/>
</Spinner>

<LinearLayout android:layout_gravity="fill_horizontal" 
    android:focusable="true" 
    android:focusableInTouchMode="true">

    <EditText
        android:id="@+id/infoText"
        android:layout_
        android:layout_
        android:layout_weight="1"
        android:layout_gravity="bottom|fill_horizontal"
        android:ems="10"
        android:hint="@string/infoHint"
        android:imeOptions="actionDone"
        android:singleLine="true"
        android:lines="1"
        android:inputType="number" />

    <ImageButton
        android:id="@+id/saveButton"
        android:layout_
        android:layout_
        android:contentDescription="@string/saveDescription"
        android:src="@android:drawable/ic_menu_save" />

</LinearLayout>

<LinearLayout android:gravity="fill_horizontal" >

    <Button
        android:id="@+id/soFarButton"
        style="android:buttonBarStyle"
        android:layout_
        android:layout_
        android:text="@string/psf" />

    <Button
        android:id="@+id/startOverButton"
        style="android:buttonBarStyle"
        android:layout_
        android:layout_
        android:text="@string/so" />

</LinearLayout>

<LinearLayout
    android:layout_
    android:layout_gravity="fill"
    android:layout_marginTop="@dimen/activity_vertical_margin"
    android:background="@android:color/holo_blue_bright"
    android:orientation="vertical"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin" >

    <TextView
        android:id="@+id/textView1"
        android:layout_
        android:layout_
        android:layout_gravity="fill_horizontal"
        android:gravity="center_horizontal"
        android:text="@string/taggedSearches"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <ListView
        android:id="@android:id/list"
        android:layout_
        android:layout_
        android:layout_gravity="fill"
        android:layout_weight="1" />

</LinearLayout>

activity_list.xml

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textView"
android:layout_
android:layout_
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceMedium" >

MainActivity.java

package com.example.physicalactivitytracker;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ListActivity 

private static final String SEARCHES = "searches";

private Spinner activityDropDown;
private ImageButton saveButton;
private EditText infoText;
private SharedPreferences savedSearches;
private ArrayList<String> tags; 
private ArrayAdapter<String> adapter;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    addItemsOnSpinner();

    // get references 
    activityDropDown = (Spinner) findViewById(R.id.activityDropDown);
    infoText = (EditText) findViewById(R.id.infoText);

    activityDropDown.setOnItemSelectedListener(acList);

    //Get Users Saved Searches
    savedSearches = getSharedPreferences(SEARCHES, MODE_PRIVATE);

    // Store Saved Info to List
    tags = new ArrayList<String>(savedSearches.getAll().keySet());

    // Create Array Adapter
    adapter = new ArrayAdapter<String>(this, R.layout.activity_list_item, tags);
    setListAdapter(adapter);

    // Register Listener to Save Searches
    ImageButton saveButton = (ImageButton) findViewById(R.id.saveButton);
    saveButton.setOnClickListener(saveButtonListener);

    // Register listener to touches on list
    getListView().setOnItemClickListener(itemClickListener);

    // Set Listener on long click item to edit/delete/etc
    getListView().setOnItemLongClickListener(itemLongClickListener);

 //end on create

//saveButtonListener for Saving Info to List
public OnClickListener saveButtonListener = new OnClickListener() 
    @Override
    public void onClick(View v)
    
        // create info tags that match drop down activity
        if (infoText.getText().length() > 0 && infoText.getText().toString().matches(".*\\d+.*")
                && activityDropDown.getSelectedItem().toString().matches("Walking"))
        
            addTaggedSearch(activityDropDown.getSelectedItem().toString() + " " + infoText.getText().toString()
                    + " Miles");
            infoText.setText(""); // clear infoText
        
        else if (infoText.getText().length() > 0 && infoText.getText().toString().matches(".*\\d+.*")
                && activityDropDown.getSelectedItem().toString().matches("Running"))
        
            addTaggedSearch(activityDropDown.getSelectedItem().toString() + " " + infoText.getText().toString()
                    + " Miles");
            infoText.setText(""); // clear infoText
        
        else if (infoText.getText().length() > 0 && infoText.getText().toString().matches(".*\\d+.*")
                && activityDropDown.getSelectedItem().toString().matches("Stairs"))
        
            addTaggedSearch(activityDropDown.getSelectedItem().toString() + " " + infoText.getText().toString()
                    + " Number of Floors");
            infoText.setText(""); // clear infoText
        
        else if (infoText.getText().length() > 0 && infoText.getText().toString().matches(".*\\d+.*")
                && activityDropDown.getSelectedItem().toString().matches("Generic"))
        
            addTaggedSearch(activityDropDown.getSelectedItem().toString() + " " + infoText.getText().toString()
                    + " Calories");
            infoText.setText(""); // clear infoText
        
        else // display message asking user to enter info
        
            // create new alert
            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

            // set alert message to display
            builder.setMessage(R.string.missingMessage);

            // provide an OK button to dismiss dialog
            builder.setPositiveButton(R.string.OK, null);

            // create the alert dialog from builder
            AlertDialog errorDialog = builder.create();
            errorDialog.show(); // displays error dialog
        
    
; // end OnClickListener

// add new search to save file and refresh buttons
private void addTaggedSearch(String tag)

    // get a SharedPrefrences.Editor to store info
    SharedPreferences.Editor preferencesEditor = savedSearches.edit();
    preferencesEditor.putString(tag, tag); // store search
    preferencesEditor.apply(); // store updated preference

    // add info
    if (!tags.add(tag))
    
        tags.add(tag); // add new tag
        adapter.notifyDataSetChanged(); // rebind tags to ListView
    
 // end add tag

// itemClickListenerListener opens tag info
OnItemClickListener itemClickListener =  new OnItemClickListener()

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
    
        //show tag info
    
; // end itemClickListener

//itemLongCLickListener displays a dialog allowing user to delete or edit saves list item
OnItemLongClickListener itemLongClickListener = new OnItemLongClickListener()

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id)
    
        // get tag that user clicked
        final String tag = ((TextView) view).getText().toString();

        // create new alert dialog
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

        // set the AlertDialog Title
        builder.setTitle(getString(R.string.shareEditDeleteTitle, tag));

        // set list of items to display in alert
        builder.setItems(R.array.dialog_items, new DialogInterface.OnClickListener()
        
            // respond to touch by sharing, editing or deleting
            @Override
            public void onClick(DialogInterface dialog, int which)
            
                switch (which)
                
                case 0: //share
                    shareSearch(tag);
                    break;
                case 1: //edit
                    // sets infoText to match tag
                    infoText.setText(tag);
                    infoText.setText(savedSearches.getString(tag,  ""));
                    break;
                case 2: // delete
                    deleteSearch(tag);
                    break;
                
            
         //end DialogInterface.OnClickListener
    ); // end call to builder.setItems

    // set AlertDialog negative Button
    builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener()
        
            // called when cancel button is clicked
            public void onClick(DialogInterface dialog, int id)
            
                dialog.cancel(); //dismiss AlertDialog
            
        
    ); // end call to setNegativeButon

    builder.create().show(); //display AlertDialog
    return true;
     // end method onItemLongClick
; // end onItemLongClick declaration

//allow user to choose an app for sharing saved items
private void shareSearch(String tag)

    // create Intent to share urlString
    Intent shareIntent = new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.shareSubject));
    shareIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.shareMessage));
    shareIntent.setType("text/plain");

    // display apps that can share text
    startActivity(Intent.createChooser(shareIntent, getString(R.string.shareSearch)));


// deletes search after user confirms the delete operation
private void deleteSearch(final String tag)

    // create new AlertDialog 
    AlertDialog.Builder confirmBuilder = new AlertDialog.Builder(this);

    // set the AlertDialog message
    confirmBuilder.setMessage(getString(R.string.confirmMessage, tag));

    // set AlertDialog negative message
    confirmBuilder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener()
        
            // called when Cancel is clicked
            public void onClick(DialogInterface dialog, int id)
            
                dialog.cancel(); // dismiss dialog
            
        
    ); // end call to setNegativeButton

    // set the AlertDialogs positive button
    confirmBuilder.setPositiveButton(getString(R.string.delete), new DialogInterface.OnClickListener()
        
            // called when Cancel button is clicked
            public void onClick(DialogInterface dialog, int id)
            
                tags.remove(tag); // remove tag from tags

                // get SharePrefrences.Editor to remove saved info
                SharedPreferences.Editor preferencesEditor = savedSearches.edit();
                preferencesEditor.remove(tag); // remove search
                preferencesEditor.apply(); // save the changes

                // rebind tags ArrayList to ListView to show updates list
                adapter.notifyDataSetChanged();
            
         // end OnClickListener
    ); // end call to setPositiveButton

    confirmBuilder.create().show(); // display AlertDialog
 // end method Delete Search

public void addItemsOnSpinner() 
    activityDropDown = (Spinner) findViewById(R.id.activityDropDown);
    List<String> list = new ArrayList<String>();
    list.add("Walking");
    list.add("Running");
    list.add("Stairs");
    list.add("Generic");
    ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, list);
    dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    activityDropDown.setAdapter(dataAdapter);


// on Item Select Update infoText Hint
public OnItemSelectedListener acList = new OnItemSelectedListener() 
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
    
        String selectedItem = parent.getItemAtPosition(position).toString();
        if(selectedItem.equals("Walking"))
        
            infoText.setHint("# of Miles Walked");
            
        else if(selectedItem.equals("Running"))
        
            infoText.setHint("# of Miles Ran");
            
        else if(selectedItem.equals("Stairs"))
        
            infoText.setHint("# of Floors Walked");
            
        else if(selectedItem.equals("Generic"))
        
            infoText.setHint("# of Calories Burned");
            
        
    @Override
    public void onNothingSelected(AdapterView<?> arg0) 
        // TODO Auto-generated method stub
    
;

public void addListenerOnSpinnerItemSelection() 
    activityDropDown = (Spinner) findViewById(R.id.activityDropDown);
    activityDropDown.setOnItemSelectedListener(new CustomOnItemSelectedListener());


public void addListenerOnButton() 
    activityDropDown = (Spinner) findViewById(R.id.activityDropDown);
    saveButton = (ImageButton) findViewById(R.id.saveButton);


@Override
public boolean onCreateOptionsMenu(Menu menu) 
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.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();
    if (id == R.id.action_settings) 
        return true;
    
    return super.onOptionsItemSelected(item);

【问题讨论】:

【参考方案1】:

我实际上找到了我的问题的答案……哈。

如果你仔细看看

public OnClickListener saveButtonListener = new OnClickListener() 
@Override
public void onClick(View v)

    // create info tags that match drop down activity
    if (infoText.getText().length() > 0 && infoText.getText().toString().matches(".*\\d+.*")
            && activityDropDown.getSelectedItem().toString().matches("Walking"))
    
        addTaggedSearch(activityDropDown.getSelectedItem().toString() + " " + infoText.getText().toString()
                + " Miles");
        infoText.setText(""); // clear infoText
    

你可以看到我忘记添加了

adapter.notifyDataSetChanged();

这会阻止应用正确更新。

感谢任何试图解决这个问题的人,很抱歉浪费了任何人的时间:)

【讨论】:

以上是关于Android ListView 在 saveButton 之后没有更新,而是在 onItemSelected 之后更新的主要内容,如果未能解决你的问题,请参考以下文章

android如何改变listview的每行高度

android listview每个Item放置多个图片

如何在 Android 中处理 ListView 点击

求助,如何在listview里addheadview-Android开发问答

在包含 ListView (Android) 的视图中滚动

android_ListView