DialogFragment, созданный событием из кнопки в пользовательском ArrayAdapter, всегда имеет одну и ту же позицию

Я новичок, так что постарайтесь быть терпеливым со мной.

Вот некоторая справочная информация о проблеме, с которой я столкнулся:

У меня есть фрагмент ViewFragment, состоящий из двух компонентов: Spinner и ListView. Spinner - это Spinner по умолчанию с обычным ArrayAdapter, который заполняет Spinner значениями, взятыми из ArrayList, называемого «metaList», который в основном представляет собой ArrayList объектов, каждый из которых имеет ArrayList, называемый «mainList».

ListView имеет пользовательский ArrayAdapter (называемый «CustomAdapter»), о котором я упоминал в заголовке. CustomAdapter заполняет ListView значениями, взятыми из «mainList» выбранного элемента в Spinner.

Теперь CustomAdapter для ListView имеет две кнопки. Единственная кнопка, которая еще что-то делает (называется «viewButton»), при нажатии создает DialogFragment.

Проблема, с которой я столкнулся, связана с этим DialogFragment. Каждый элемент в ListView должен создавать уникальный DialogFragment при нажатии его viewButton. Однако независимо от того, кнопка какого элемента в ListView нажата, DialogFragment всегда один и тот же и отображает DialogFragment для последнего элемента в ListView.

Я думаю, что эта проблема связана с тем, что сами элементы ListView не нажимаются, а только их кнопки, поэтому значение позиции в методе getView() для CustomAdapter никогда не меняется.

Как решить эту проблему?

Вот код ViewFragment, который содержит компоненты Spinner и ListView:

package com.statbot;

import java.util.ArrayList;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.AdapterView.OnItemSelectedListener;

public class ViewFragment extends Fragment{

static int spinPos;
private ArrayList<String> names;
private ArrayList<String> nums;
private Spinner spinner;
private View view;
private ViewGroup container;
private ListView listView;
private Fragment frag;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
        Bundle savedInstanceState) {    

    view = inflater.inflate(R.layout.view_layout, container, false);
    this.container = container;
    frag = this;
    names = new ArrayList<String>();
    nums = new ArrayList<String>();
    spinner = (Spinner)view.findViewById(R.id.view_frag_spinner1);
    listView = (ListView) view.findViewById(R.id.view_frag_listView2);


    for(int k = 0; k < MainActivity.metaList.size(); k++)
    {
        names.add(MainActivity.metaList.get(k).getName());
    }

    ArrayAdapter<String> adapter = new ArrayAdapter<String>      (container.getContext(),android.R.layout.simple_spinner_item, names);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);
    spinner.setOnItemSelectedListener(new SpinListener());

    return view;
}

private class SpinListener extends Activity implements OnItemSelectedListener{

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int pos,
            long id) {
        // TODO Auto-generated method stub
        spinPos = pos;
        nums.clear();
        for(int k = 0; k < MainActivity.metaList.get(pos).mainList.size(); k++)
        {
            nums.add("" + MainActivity.metaList.get(pos).mainList.get(k).quantity);
        }
        CustomAdapter adapter2 = new CustomAdapter(container.getContext(),   android.R.layout.simple_spinner_item, nums);
        adapter2.setFrag(frag);
        listView.setAdapter(adapter2);
    }

    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
        // TODO Auto-generated method stub
        spinPos = 0;
    }
}
}

Вот код CustomAdapter:

package com.statbot;

import java.util.List;

import android.app.Fragment;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;

public class CustomAdapter extends ArrayAdapter{

private TextView quantity;
private ImageButton editButton;
private ImageButton deleteButton;
private ImageButton viewButton;
private Context mContext;
private int id;
private Fragment frag;
private int pos;
private List<String> objects;

@SuppressWarnings("unchecked")
public CustomAdapter (Context context, int textViewResourceId, List<String> objects){   
    super(context, textViewResourceId, objects);    
    mContext = context;
    id = textViewResourceId;
    this.objects = objects;
}   

public View getView(int position, View v, ViewGroup parent){
    this.pos = position;
    final int POSITION = position;
    View mView = v;

    if (mView == null){     
        LayoutInflater vi = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mView = vi.inflate(R.layout.cust_list_view, parent, false);
    }


    editButton = (ImageButton) mView.findViewById(R.id.cust_list_view_button1);
    viewButton = (ImageButton) mView.findViewById(R.id.cust_list_view_button2);
    quantity = (TextView) mView.findViewById(R.id.cust_list_view_textView1);
    if(quantity == null)
    {
        System.out.println("The poop is a lie");
    }
    quantity.setText("" + pos + "," + ViewFragment.spinPos);


    viewButton.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            System.out.println("" + POSITION);
            showContents(ViewFragment.spinPos, POSITION);
        }

    });

    return mView;
}
private void showContents(int metaPos, int mainPos){
    NumStatDialog contents = new NumStatDialog();
    contents.setMainPosition(pos);
    contents.setMetaPosition();
    contents.show(frag.getFragmentManager(), "content_dialog");
}
public void setFrag(Fragment f){
    frag = f;
}

}

Вот код для DialogFragment, который называется NumStatDialog:

package com.statbot;

import android.annotation.SuppressLint;
import android.app.DialogFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

@SuppressLint("ValidFragment")
public class NumStatDialog extends DialogFragment{

private View view;
private int metaPosition;
private int mainPosition;
private TextView title;
private TextView info;
private boolean type;//if true, sets up a dialog to display information on a list. if false, displays information on an item of that list.


public NumStatDialog(int metaPos, int mainPos){
    type = false;
    metaPosition = metaPos;
    mainPosition = mainPos;
}

public NumStatDialog(int metaPos){
    type = true;
    metaPosition = metaPos;
}
public NumStatDialog(){

}

public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.numstat_dialog_layout, container);

    info = (TextView) view.findViewById(R.id.numstat_dialog_textView2);
    title = (TextView) view.findViewById(R.id.numstat_dialog_textView1);
    if(!type){
        //info.setText((CharSequence) MainActivity.metaList.get(metaPosition).mainList.get(mainPosition).toString());
        info.setText((CharSequence) ("" + mainPosition));
        //title.setText((CharSequence) ("" + MainActivity.metaList.get(metaPosition).mainList.get(mainPosition).quantity));
        title.setText((CharSequence) ("" + metaPosition));
    }
    if(type){
        info.setText((CharSequence) MainActivity.metaList.get(metaPosition).toString());
        title.setText((CharSequence) MainActivity.metaList.get(metaPosition).getName());
    }


    return view;
}
public void setMainPosition(int mp){
    mainPosition = mp;
}
public void setMetaPosition(){
    metaPosition = ViewFragment.spinPos;
}
}

и вот несколько скриншотов, чтобы было легче понять. Спиннер находится вверху, а ListView прямо под ним. Первое число каждого элемента ListView — это его позиция, а второе число — позиция счетчика. Интересующая кнопка имеет форму бумаги. игнорируйте карандаш, он еще ничего не делает.

введите здесь описание изображения

и вот DialogFragment. Заголовок — это позиция Spinner, а нижний номер — это позиция элемента, кнопка которого была нажата, но обратите внимание, что, хотя у 1-го элемента в ListView была нажата кнопка для отображения этого диалогового окна, число в нижней части фрагмента отображается тройка за 4-й пункт.

введите здесь описание изображения

Любая помощь по этой проблеме будет очень признательна, это одно из последних серьезных препятствий, которые мне нужно преодолеть для этого проекта, все остальное должно быть довольно простым. Спасибо!


person scottysseus    schedule 16.06.2013    source источник


Ответы (1)


В вашем showContents() вы полностью игнорируете два переданных параметра и вместо этого используете this.pos, который действительно будет позицией последнего представления, увеличенного ListView. Просто используйте свои параметры (и настройте свою IDE, чтобы она предупреждала вас о неиспользуемых переменных и параметрах).

С другой стороны, передача данных во фрагмент, подобный этому, не выдержит изменений конфигурации (если только у вас нет setRetainInstance везде, но это пронизано различными проблемами). Рассмотрите возможность использования setArguments, сериализации состояния в onSaveInstanceState и десериализации его в onCreate (используя getArguments или savedInstanceState, если это возможно).

person Delyan    schedule 16.06.2013
comment
вау, спасибо, это оказалось единственной проблемой. не могу поверить, что я сделал эту ошибку. Однако я не очень понимаю вторую часть вашего ответа. Можете ли вы объяснить, что такое сериализация? - person scottysseus; 17.06.2013
comment
Сериализация относится к унифицированному способу сохранения и восстановления объектов. В обычной Java это делается через интерфейс Serializable. В Android Java предпочтительным способом является Parcelable и Bundles. Я на самом деле имел в виду, что вы должны сохранять свои переменные экземпляра (т. е. поля) в onSaveInstanceState и восстанавливать их из savedInstanceState в onCreate. Таким образом, вы знаете, что независимо от того, что Android решит сделать с вашим фрагментом и активностью, ваше состояние может быть постоянно сохранено и восстановлено, и вы защищены. - person Delyan; 18.06.2013