0

内のアイテムを正しく識別するのに問題がありますListView

重要なクラスは 4 つあります。コードが多いため、最初にそれらのクラスのロジックについて説明します。

  • を入力しListActivityて初期化しますListView
  • AsyncTaskJSON 応答をサーバーからダウンロードして解析し、ListViewオブジェクトを設定してアダプターを設定する を実行します。ProgressDialog
  • PlaylistItemクラスには、単一の JSONObject からデータを取得するだけのメソッドが含まれています。オブジェクトでArrayListをパラメータ化するために使用されます
    • 完了するAsyncTaskと、リストは項目で満たされ、|Button| のようになります。アーティスト( TextView) - タイトル( TextView)

アップデート

最初の問題は解決しましたが、ボタンの何が問題なのかまだわかりません

2)。OnClickListenerアダプタの getView() メソッドでボタンにを設定しました。ボタンが正しく識別されているかどうかを確認するために、背景を変更するだけで何もしませんでした。ただし、特定のボタンをクリックすると、11 番目または 12 番目のボタンごとに背景が強制的に変更されます。ここまで判りません。

これらの問題が解決されるまで、URL の取得とオーディオのストリーミングに進むことはできません。私のクラスは以下に続きます。不明な点があればお尋ねください。

オーディオリスト

         public class AudioList extends ListActivity {
private ListView lv;
private PlaylistLoader loader;
private AudioListAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_audio_list);
    init(); // initialize the ListView

    /*--- populate the list with user's audio in case network connection is available ---*/
    loader = new PlaylistLoader(this, lv, adapter);
    if (Utils.isNetworkAvailable(this)) {
        loader.execute();
    } else {
        APP_CONSTANTS.NO_DATA_CONNECTION(this);
    }

}

@Override
protected void onResume() {
    super.onResume();
    lv.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {

            Toast.makeText(getApplicationContext(), Integer.toString(arg2),
                    Toast.LENGTH_SHORT).show();
            }
    });

}

private void init() {
    lv = getListView();
    lv.setTranscriptMode(0x00000000);
    lv.setDividerHeight(1);
    lv.setSmoothScrollbarEnabled(true);
    lv.setVerticalFadingEdgeEnabled(true);

}

プレイリストローダー

      public class PlaylistLoader extends AsyncTask<Void, Void, Void> {

private JSONObject usersPlaylist, singleJSONItem;
private JSONArray responseJSONArray;
private ListView lv;
private ArrayList<PlaylistItem> playlist;
private Activity a;
private PlaylistItem audioList;
private SharedPreferences prefs;
private ProgressDialog pd;
AudioListAdapter adapter;

public PlaylistLoader(Activity a, ListView lv, AudioListAdapter adapter) {
    this.lv = lv;
    this.a = a;
    this.adapter = adapter;
}

@Override
protected Void doInBackground(Void... arg0) {
    /*--- create new ArrayList of PlaylistItem Objects ---*/
    playlist = new ArrayList<PlaylistItem>();
    /*--- get the preferences using context of calling activity ---*/
    prefs = PreferenceManager.getDefaultSharedPreferences(a);
    try {
        /*--- download the response JSONObject from server // access_token and 
         * user_id come from activity's defaultSharedPreferences ---*/
        usersPlaylist = Utils.retrieveJsonObjectFromUrl(new URL(
                APP_CONSTANTS.REQUEST_AUDIO_LIST(prefs)), a);
        /*--- get the response array from received object ---*/
        responseJSONArray = usersPlaylist.getJSONArray("response");
        /*--- populate the ArrayList with Objects from the response array ---*/
        for (int i = 0; i < responseJSONArray.length(); i++) {
            singleJSONItem = responseJSONArray.getJSONObject(i);
            audioList = new PlaylistItem(singleJSONItem);
            playlist.add(audioList);

        }

    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (JSONException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

@Override
protected void onPreExecute() {
    super.onPreExecute();
    pd = new ProgressDialog(a);
    pd.setTitle("Please wait");
    pd.setMessage("Retrieving audio list...");
    pd.show();

}

@Override
protected void onPostExecute(Void result) {
    super.onPostExecute(result);
    lv.setVisibility(View.VISIBLE);
    pd.dismiss();
    /*--- set the adapter passed in constructor as an adapter for passed ListView ---*/
    adapter = new AudioListAdapter(a, R.layout.playlist_item, playlist);
    lv.setAdapter(adapter);

}
    }

AudioListAdapter

           public class AudioListAdapter extends ArrayAdapter<PlaylistItem> {
private PlaylistItem pl;
private Context context;
private int layoutResourceId;
private PlaylistItem aud;
private ArrayList<PlaylistItem> data = null;

public AudioListAdapter(Context context, int layoutResourceId,
        ArrayList<PlaylistItem> data) {
    super(context, layoutResourceId, data);
    this.layoutResourceId = layoutResourceId;
    this.context = context;
    this.data = data;

}

@Override
public PlaylistItem getItem(int position) {
    return super.getItem(position);
}

@Override
public int getCount() {
    return data.size();
}

@Override
public int getPosition(PlaylistItem item) {
    return super.getPosition(item);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    pl = new PlaylistItem();
    aud = getItem(position);

    if (convertView == null) {
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        convertView = inflater.inflate(layoutResourceId, parent, false);
        pl.btnPlay = (Button) convertView.findViewById(R.id.btn_list_play);
        pl.imgSaved = (ImageView) convertView
                .findViewById(R.id.img_list_audio_saved);
        pl.tvArtist = (TextView) convertView
                .findViewById(R.id.tvListItemArtist);
        pl.tvTitle = (TextView) convertView
                .findViewById(R.id.tvListItemSong);

        convertView.setTag(pl);
    } else {
        pl = (PlaylistItem) convertView.getTag();
        pl.btnPlay.setBackgroundResource(R.drawable.list_button_play);
    }

    pl.tvArtist.setText(aud.getArtist() + " " + "-");
    pl.tvTitle.setText(aud.getTitle());

    pl.btnPlay.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            /*--- vibrate if this option is enabled in the preferences ---*/
            if (APP_CONSTANTS.isHapticFeedbackEnabled(getContext())) {
                APP_CONSTANTS.doVibrate(getContext());

            }
         pl.btnPlay.setBackgroundResource(R.drawable.list_button_pause);

        }
    });

    return convertView;
}

PlayListItem

     public class PlaylistItem {

private String artist, title;
private JSONObject obj;
public Button btnPlay;
public TextView tvArtist, tvTitle;
public ImageView imgSaved;
public int duration;
public int audio_id;
public String url;

/*--- the constructor takes a single JSONObject from the response array ---*/
public PlaylistItem(JSONObject obj) {
    this.obj = obj;
}

public PlaylistItem() {
    // default constructor
}

/*--- the methods below return values by key from the passed JSONObject ---*/

public String getArtist() {
    try {
        artist = obj.getString("artist");
    } catch (JSONException e) {

        e.printStackTrace();
    }
    return artist;

}

public String getTitle() {
    try {
        title = obj.getString("title");
    } catch (JSONException e) {

        e.printStackTrace();
    }
    return title;
}

public int getID() {
    try {
        audio_id = obj.getInt("aid");
    } catch (JSONException e) {

        e.printStackTrace();
    }
    return audio_id;
}

public String getURL() {
    try {
        url = obj.getString("url");
    } catch (JSONException e) {

        e.printStackTrace();
    }
    return url;
}
    }
4

2 に答える 2

1

ただし、特定のボタンをクリックすると、11番目または12番目のボタンごとに背景が変更されます。今のところそれを理解することはできません。

ListViewsが行レイアウトをリサイクルする方法と戦っています。
このように考えてください。10,000行のListViewがあり、画面に9行しか収まらない場合、10,000の一意のレイアウトを作成することは意味がありません。これはリソースを浪費するだけで、代わりにListViewは最大10個のレイアウトを作成し、それらを再利用します。

解決策:再利用されると、各行をデフォルトの状態に戻します。getView()追加で:

} else {
    pl = (PlaylistItem) convertView.getTag();
    pl.btnPlay.setBackgroundResource(R.drawable.list_button_play);
    // I guessed at the resource's name         ^^^^^^^^^^^^^^^^
}

(また、コードを高速化するためにいくつかの小さな変更を加えることができます。たとえば、すべて同じコードが含まれているため、必要なOnClickListenerは1つだけです。これをクラス変数にして、各再生ボタンに渡します。他にもあります。)

于 2013-03-01T19:41:11.057 に答える
1

編集

これを試して

ドローアブル button_play.xml でカスタム セレクターを取得します。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/pause_button"
          android:state_selected="true" />
    <item android:drawable="@drawable/play_button" />
</selector>

このようにアダプターを変更します

 public class AudioListAdapter extends ArrayAdapter<PlaylistItem> {
private PlaylistItem pl;
private Context context;
private int layoutResourceId;
private PlaylistItem aud;
private ArrayList<PlaylistItem> data = null;
Button previous;

public AudioListAdapter(Context context, int layoutResourceId,
        ArrayList<PlaylistItem> data) {
    super(context, layoutResourceId, data);
    this.layoutResourceId = layoutResourceId;
    previous=new Button(context);
    this.context = context;
    this.data = data;

}

....
....

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    pl = new PlaylistItem();
    aud = getItem(position);

    if (convertView == null) {
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        convertView = inflater.inflate(layoutResourceId, parent, false);
        pl.btnPlay = (Button) convertView.findViewById(R.id.btn_list_play);
pl.btnPlay.setBackGroundResouce(R.drawable.button_play); //you can set here or in xml

        pl.imgSaved = (ImageView) convertView
                .findViewById(R.id.img_list_audio_saved);
        pl.tvArtist = (TextView) convertView
                .findViewById(R.id.tvListItemArtist);
        pl.tvTitle = (TextView) convertView
                .findViewById(R.id.tvListItemSong);

        convertView.setTag(pl);
    } else {
        pl = (PlaylistItem) convertView.getTag();
    }


    pl.tvArtist.setText(aud.getArtist() + " " + "-");
    pl.tvTitle.setText(aud.getTitle());

    pl.btnPlay.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            /*--- vibrate if this option is enabled in the preferences ---*/
            if (APP_CONSTANTS.isHapticFeedbackEnabled(getContext())) {
                APP_CONSTANTS.doVibrate(getContext());
            }
                //for some reason, the background gets changed for every 11th or 12th button in the list
             Button current=((Button)v);
              current.setSelected(true);
              previous.setSelected(false);
              previous=current;
        }
    });

    return convertView;
}

    }

ボタンとリストアイテムがクリックできない理由は、リストにフォーカスアイテムボタンがあるためです。そのため、ボタンにFocusable = falseを設定する必要があります。xml でボタンに focusable=false を設定してみてください。それがうまくいかない場合は、このようにしてください

行xmlファイルで

1. ボタンに focusable=true を設定します。2.android:descendantFocusability="blocksDescendants"親アイテムの同じセット内(つまり、ビューが存在する親レイアウト)。

ボタンに onclickListener を設定した後、 getView() メソッドで、ボタンに focusable false を設定します。それは確かに機能します。これがあなたを助けることを願っています..

于 2013-03-01T15:39:45.310 に答える