listview with a custom adapter - every other item element are duplicates

青春壹個敷衍的年華 提交于 2019-12-20 07:01:30

问题


I have come accross a bit of a weird problem (i think) with my listview and its customadapter.

The problem is that I have some different view elements for every item in my listview, such as EditText fields among others. Whenever I have more than 2 items in the listview, entries to these elements are now in every other item.

Let me give an example: - I am adding 8 items to the listview. - I enter a value in the first textfield - Now the same value repeats in the textfields: 3, 5 and 7 - If I enter a value in the second item's textfield, this value is repeated in textfield of item number: 4, 6 and 8

I hope that you can see the problem now.

Here is some of the relevant code for this problem:

First, the code for my customadapter (CreateProgramAdapter):

    public class CreateProgramAdapter extends BaseAdapter {

    private LayoutInflater inflater;
    private ArrayList<TrainingPass> trainingPasses;
    private List<TrainingPass> items;
    private int layoutResourceId;
    private Context context;

    public CreateProgramAdapter(Context context, List<TrainingPass> items) {
        this.context = context;
        this.items = items;
        this.inflater = LayoutInflater.from(this.context);
    }

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

    @Override
    public TrainingPass getItem(int position) {
        return items.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        TrainingPassHolder holder;

        if(convertView == null) {
            view = inflater.inflate(R.layout.adapter_createprogram_trainingpasses_item, parent, false);
            holder = new TrainingPassHolder();
            view.setTag(holder);

        } else {
            view = convertView;
            holder = (TrainingPassHolder)view.getTag();
        }

        holder.trainingPass = this.getItem(position);
        holder.trainingPass.trainingPassID = position + 1;
        holder.trainingPassContainer = (RelativeLayout) view.findViewById(R.id.trainingPassContainer);
        holder.trainingPassHeadlineShowHide = (TextView) view.findViewById(R.id.trainingpass_headline);
        holder.noExercisesYet = (TextView) view.findViewById(R.id.txt_no_exercises_yet);
        holder.exerciseSearchField = (EditText) view.findViewById(R.id.trainingpass_exercise_searchfield);
        holder.trainingPassSetsListView = (ListView) view.findViewById(R.id.trainingpass_sets_listview);
        holder.exercisesListView = (ListView) view.findViewById(R.id.exercises_listview);
        holder.addSetButton = (Button) view.findViewById(R.id.add_set_button);
        holder.addExerciseButton = (Button) view.findViewById(R.id.add_exercise_button);
        holder.deleteTrainingpass = (Button) view.findViewById(R.id.delete_trainingpass_button);
        holder.doneTrainingpass = (Button) view.findViewById(R.id.done_trainingpass_button);

        setupItems(holder);

        return view;
    }


    private void setupItems(TrainingPassHolder trainingPassHolder) {
        final TrainingPassHolder holder = trainingPassHolder;
        int trainingPassID = trainingPassHolder.trainingPass.trainingPassID;

        TextView showHide         = holder.trainingPassHeadlineShowHide;
        Button addSet             = holder.addSetButton;
        Button deleteTrainingPass = holder.deleteTrainingpass;
        final EditText exerciseNameField = holder.exerciseSearchField;

        // Set title of the trainingpass
            showHide.setText("Trainingpass " + trainingPassID);

        // Set name of exercise


        if (trainingPassHolder.trainingPass.tempExerciseName != null) {
            System.out.println(holder.trainingPass.tempExerciseName);
            exerciseNameField.setText(holder.trainingPass.tempExerciseName);
        } else {
            exerciseNameField.setText("");
        }

        // Add 1 default set to exercise
            if (holder.sets.size() == 0) {
                holder.sets.add(1);
            }

        /*
            Set adapter for sets of the listview for the trainingpass
         */

        final TrainingPassSetsAdapter createProgramAdapter = new TrainingPassSetsAdapter(context, holder.sets);
        holder.trainingPassSetsListView.setAdapter(createProgramAdapter);


        exerciseNameField.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                holder.trainingPass.tempExerciseName = exerciseNameField.getText().toString();
                return false;
            }
        });


        /*
            Show / hide the trainingpass
         */
        showHide.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (holder.trainingPass.visible) {
                    holder.trainingPass.visible = false;
                    holder.trainingPassContainer.setVisibility(View.GONE);
                } else {
                    holder.trainingPass.visible = true;
                    holder.trainingPassContainer.setVisibility(View.VISIBLE);
                }
            }
        });

        /*
            Add set to the listview
         */
        addSet.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                holder.sets.add(1);
                createProgramAdapter.notifyDataSetChanged();
            }
        });

        /*
            Delete training pass
         */
        deleteTrainingPass.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                items.remove(holder.trainingPass);
                notifyDataSetChanged();
            }
        });
    }

    private static class TrainingPassHolder {
        ArrayList<Integer> sets = new ArrayList<Integer>();
        TrainingPass    trainingPass;
        RelativeLayout  trainingPassContainer;
        TextView        trainingPassHeadlineShowHide;
        TextView        noExercisesYet;
        EditText        exerciseSearchField;
        ListView        trainingPassSetsListView;
        ListView        exercisesListView;
        Button          addSetButton;
        Button          addExerciseButton;
        Button          deleteTrainingpass;
        Button          doneTrainingpass;
    }
}

And here is the code for the class TrainingPass:

public class TrainingPass {

    public String trainingPassName;
    public ArrayList<Exercise> exercises;
    public int trainingPassID;
    public boolean visible = false;
    public String tempExerciseName;


    public TrainingPass() {
        exercises = new ArrayList<Exercise>();
    }

    public void addExercise(Exercise exercise ) {
        exercises.add(exercise);
    }

}

An the code for the activity class CreateProgramActivity:

public class CreateProgramActivity extends CustomActivity {

    private ArrayList<TrainingPass> trainingPasses;
    private CreateProgramAdapter createProgramAdapter;
    private ListView trainingPassesListView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(R.style.AppTheme);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_create_program);

        trainingPasses = new ArrayList<TrainingPass>();


        trainingPassesListView = (ListView)findViewById(R.id.listView_trainingpasses);
        createProgramAdapter = new CreateProgramAdapter(CreateProgramActivity.this, trainingPasses);
        trainingPassesListView.setAdapter(createProgramAdapter);

    }

    public void addTrainingPass(View v) {
        TrainingPass trainingPass = new TrainingPass();
        trainingPasses.add(trainingPass);

        createProgramAdapter.notifyDataSetChanged();
    }
    public void addTrainingPassHelp(View v) {
        Toast.makeText(this, "Add training pass HELP!", Toast.LENGTH_SHORT).show();
    }
    public void createProgram(View v) {
        Toast.makeText(this, "Create program", Toast.LENGTH_SHORT).show();
    }
}

Here is the xml layout for the CreateProgramActivity, containing the parent listview:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.mobileplatformexam.activities.CreateProgramActivity"
    android:id="@+id/relativeLayoutCreateProgram">


    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Add training pass"
        android:id="@+id/btn_add_trainingpass"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_toLeftOf="@+id/btn_add_trainingpass_help"
        android:layout_toStartOf="@+id/btn_add_trainingpass_help"
        android:onClick="addTrainingPass"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="\?"
        android:id="@+id/btn_add_trainingpass_help"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:onClick="addTrainingPassHelp"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Create program"
        android:id="@+id/btn_create_program"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignRight="@+id/btn_add_trainingpass_help"
        android:layout_alignEnd="@+id/btn_add_trainingpass_help"
        android:onClick="createProgram"/>

    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/listView_trainingpasses"
        android:layout_above="@+id/btn_create_program"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/btn_add_trainingpass" />


</RelativeLayout>

And lastly, here is my xml layout for the item of the parent listview:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_gravity="center_horizontal"
    android:orientation="horizontal"
    android:padding="10dp">

    <TextView
        android:id="@+id/trainingpass_headline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="false"
        android:layout_alignParentTop="true"
        android:text="Trainingpass"
        android:textSize="16dp"
        android:textColor="@android:color/white"
        android:background="@android:color/holo_blue_dark"
        android:height="35dp"
        android:gravity="center_vertical"
        android:paddingLeft="10dp"
        android:textIsSelectable="true"
        android:textStyle="bold"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" />

    <ImageView
        android:id="@+id/trainingpass_showhide_imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_blue_dark"
        android:height="25dp"
        android:minWidth="50dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:padding="7dp"
        android:layout_alignBottom="@+id/trainingpass_headline"
        android:src="@mipmap/arrows_up_down"
        android:layout_alignParentTop="true" />

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@+id/trainingpass_headline"
        android:layout_alignLeft="@+id/trainingpass_headline"
        android:layout_alignStart="@+id/trainingpass_headline"
        android:id="@+id/trainingPassContainer"
        android:background="@color/blue_bg_neutral"
        android:visibility="visible"
        android:paddingBottom="10dp">

        <EditText
            android:id="@+id/trainingpass_exercise_searchfield"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="Name of exercise"
            android:padding="6dp"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:background="@color/blue_bg_inputField"
            android:layout_margin="10dp" />

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/trainingpass_exercise_searchfield"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:id="@+id/sets_container"
            android:background="@color/blue_bg_inputField"
            android:padding="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="10dp">

            <TextView
                android:id="@+id/txt_sets_for_exercise"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Sets for exercise"
                android:textSize="14dp"
                android:textColor="@android:color/black"
                android:paddingRight="30dp"
                android:paddingLeft="0dp"
                android:paddingTop="0dp"
                android:paddingBottom="10dp"
                android:textStyle="bold"
                android:layout_alignParentTop="true"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_alignRight="@+id/add_set_button"
                android:layout_alignEnd="@+id/add_set_button" />

            <ListView
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:id="@+id/trainingpass_sets_listview"
                android:nestedScrollingEnabled="true"
                android:layout_alignParentRight="true"
                android:layout_alignParentEnd="true"
                android:layout_alignTop="@+id/txt_no_sets"
                android:layout_alignBottom="@+id/txt_no_sets" />

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Add set"
                android:id="@+id/add_set_button"
                android:layout_below="@+id/trainingpass_sets_listview"
                android:layout_alignParentRight="true"
                android:layout_alignParentEnd="true" />

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Add exercise"
                android:id="@+id/add_exercise_button"
                android:layout_below="@+id/add_set_button"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_alignParentRight="true"
                android:layout_alignParentEnd="true" />

            <TextView
                android:id="@+id/txt_no_sets"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="No sets yet"
                android:textSize="14dp"
                android:textColor="@android:color/black"
                android:paddingRight="30dp"
                android:paddingLeft="10dp"
                android:paddingTop="20dp"
                android:paddingBottom="10dp"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_alignParentRight="true"
                android:layout_alignParentEnd="true"
                android:layout_below="@+id/txt_sets_for_exercise"
                android:visibility="invisible" />
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:layout_below="@+id/sets_container"
            android:id="@+id/exercises_container"
            android:background="@color/blue_bg_inputField"
            android:padding="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="10dp">

            <TextView
                android:id="@+id/txt_exercises"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Exercises"
                android:textSize="14dp"
                android:textColor="@android:color/black"
                android:paddingRight="30dp"
                android:paddingLeft="0dp"
                android:paddingTop="0dp"
                android:paddingBottom="10dp"
                android:textStyle="bold"
                android:layout_alignParentTop="true"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_alignRight="@+id/txt_no_exercises_yet"
                android:layout_alignEnd="@+id/txt_no_exercises_yet" />

            <TextView
                android:id="@+id/txt_no_exercises_yet"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="No exercises yet"
                android:textSize="14dp"
                android:textColor="@android:color/black"
                android:paddingRight="30dp"
                android:paddingLeft="10dp"
                android:paddingTop="20dp"
                android:paddingBottom="10dp"
                android:layout_below="@+id/txt_exercises"
                android:layout_alignParentRight="true"
                android:layout_alignParentEnd="true"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true" />

            <ListView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:id="@+id/exercises_listview"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_below="@+id/txt_exercises"
                android:layout_alignBottom="@+id/txt_no_exercises_yet" />

        </RelativeLayout>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Delete"
            android:id="@+id/delete_trainingpass_button"
            android:layout_alignRight="@+id/exercises_container"
            android:layout_alignEnd="@+id/exercises_container"
            android:layout_below="@+id/exercises_container"
            android:background="@color/btn_red"
            android:layout_marginLeft="10dp" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Done"
            android:id="@+id/done_trainingpass_button"
            android:layout_below="@+id/exercises_container"
            android:layout_alignLeft="@+id/exercises_container"
            android:layout_alignStart="@+id/exercises_container"
            android:layout_toStartOf="@+id/delete_trainingpass_button"
            android:background="@color/btn_green"
            android:layout_marginRight="10dp" />

    </RelativeLayout>

</RelativeLayout>

I really hope that someone can see what the problem is.

Any help will be greatly appreciated.


回答1:


I think this behavior is predictable as adapter utilizes views replacing its content with new data. As you didn't set new text value to EditText in the getView() method you get EditText with old value, which is that you entered. So try to add TextWatcher to your EditText and save entered value in the corresponding instance of TrainingPass object. And in the getView() method you have to add of holder.exerciseSearchField.setText(). If corresponding TrainingPass object contains previously entered value you have to set it to EditText, otherwise you have to set empty string.




回答2:


@Oleg Osipenko said its because reuse/recycle of listview.. A Sample

class Items {
    String name;
    String searchField=""; //to stored edit text values , init with empty string

    //create getter and setter
}

Adapter's getView()

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


    final ViewHolder holder;
    if (convertView == null) {

        holder = new ViewHolder();
        convertView = inflater.inflate(R.layout.your_adapter_layout, null);
        holder.textView1 = (TextView) convertView.findViewById(R.id.textView1);
        holder.editText1 = (EditText) convertView.findViewById(R.id.editText1);    
        convertView.setTag(holder);

    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    //holder.position to store view position
    holder.position= position;  

    item=items.get(position);

    holder.textView1.setText(item.getName());
    holder.editText1.setText(item.getSearchField());
    holder.editText1.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {

        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                int arg3) {

        }

        @Override
        public void afterTextChanged(Editable arg0) {
            //set more conditions if needed - like arg0=null, or empty
            items.get(holder.position).setSearchField(arg0.toString());
        }
    });

    return convertView;
}

private class ViewHolder {
    TextView textView1;
    EditText editText1;
    int position;
}

Get brief explanation about this Visit : Creating ListView with EditText and TextWatcher in Android



来源:https://stackoverflow.com/questions/29814620/listview-with-a-custom-adapter-every-other-item-element-are-duplicates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!