当dataSet更改时,listView中的Android numberPicker停止滚动

时间:2018-08-23 14:13:29

标签: android listview numberpicker

在我的应用程序中,我有一个带自定义布局和自定义适配器的listView。布局包含一个textView和一个numberPicker。 我希望numberPicker控制我的数据值,所以我想向其中添加setOnValueChangedListener。没有监听器,它可以正常工作-当我滚动numberPicker时,数字滚动,而当我滚动到它外面时,它滚动列表视图,如gif所示:

numberPicker scrolling fine

但是,当我将setOnValueChangedListener附加到numberPicker时,事情表现就很奇怪。滚动numberPicker时,它将卡住并导致布局本身滚动:

numberPicker scrolling weirdly

(在gif中,我仅在numberPickers上滚动,但是在值更改后,它滚动listView并停止滚动numberPicker。)

在进一步调查中,似乎是notifyDataSetChanged()是导致它发生的原因,并且禁用它使一切正常。

我认为发生的事情是,当我滚动浏览numberPicker时,侦听器会触发每个更改的值。因此,仅执行一次增量操作便会触发并调用notifyDataSetChanged(),从而以某种方式重置视图并导致滚动停止并转移到listView。

以下是所有相关代码:

应用程序(方法不相关,仅在按下一个按钮并创建对话框时才使用):

package com.chdev.mypianopractice;

import android.app.DialogFragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

import java.util.ArrayList;

public class EditPracticeActivity extends AppCompatActivity implements ChoosePracticeStageDialogFragment.PracticeStageDialogListener {

    ArrayList<Practice.PracticeStage> practice;
    ListView listView;
    EditPracticeListViewAdapter adapter;

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

        findViewById(R.id.practiceNameEditText).clearFocus();

        practice = new ArrayList<>();

        listView = findViewById(R.id.editPracticeListView);
        listView.setAdapter(new EditPracticeListViewAdapter(this, practice));
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                ((EditPracticeListViewAdapter) parent.getAdapter()).setClickedPosition(position);
            }
        });

        adapter = (EditPracticeListViewAdapter) listView.getAdapter();
    }

    // Creates a dialog in order to add a new stage.
    public void addStage(View view) {
        DialogFragment fragment = new ChoosePracticeStageDialogFragment();
        fragment.show(getFragmentManager(), "chooseStage");
    }

    // Used by the dialog when adding new stages to the practice.
    @Override
    public void onDialogOK(Practice.PracticeType typeChosen) {
        String name = (typeChosen == null) ? "NULL" : getString(typeChosen.id);
        if (typeChosen != null) {
            practice.add(new Practice.PracticeStage(typeChosen, 30));
            adapter.notifyDataSetChanged();
        }
        System.out.println("The chosen activity: " + name);
    }
}

自定义适配器:

package com.chdev.mypianopractice;

import android.content.Context;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.NumberPicker;
import android.widget.TextView;

import java.util.ArrayList;

/**
 * The adapter for the listView in EditPracticeActivity, using the custom layout.
 */

public class EditPracticeListViewAdapter extends ArrayAdapter<Practice.PracticeStage> {

    // Used for selecting items.
    private int lastClickedStage;

    public EditPracticeListViewAdapter(@NonNull Context context, ArrayList<Practice.PracticeStage> stages) {
        super(context, R.layout.practice_stage_row, stages);
        lastClickedStage = 0;
    }

    @NonNull
    @Override
    public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        View rowView = convertView;
        if (rowView == null) {
            LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            rowView = inflater.inflate(R.layout.practice_stage_row, parent, false);
        }
        Practice.PracticeStage stage = getItem(position);

        TextView text = rowView.findViewById(R.id.practiceStageNameTextView);
        text.setText(stage.type.id);

        NumberPicker picker = rowView.findViewById(R.id.practiceStageNumberPicker);
        picker.setMinValue(0);
        picker.setMaxValue(60*60);
        picker.setValue(stage.time);

        picker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
            @Override
            public void onValueChange(NumberPicker numberPicker, int oldVal, int newVal) {
                getItem(position).time = newVal;
                notifyDataSetChanged();
            }
        });

        rowView.setBackgroundColor(position == lastClickedStage ? Color.LTGRAY : Color.WHITE);

        return rowView;
    }

    // Used for selecting items.
    public void setClickedPosition(int position) {
        lastClickedStage = position;
        notifyDataSetChanged();
    }
}

活动的布局:

    

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="32dp"
        android:text="@string/edit_practice_title"
        android:textAlignment="center"
        android:textSize="36sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/practiceNameEditText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="@string/new_practice_default_text"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView4" />

    <ListView
        android:id="@+id/editPracticeListView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintBottom_toTopOf="@+id/button3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/practiceNameEditText" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="24dp"
        android:layout_marginStart="32dp"
        android:onClick="addStage"
        android:text="@string/add_practice_stage_edit"
        app:layout_constraintBottom_toTopOf="@+id/button5"
        app:layout_constraintEnd_toStartOf="@+id/button4"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="32dp"
        android:text="@string/remove_practice_stage_edit"
        app:layout_constraintBaseline_toBaselineOf="@+id/button3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/button3" />

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginStart="24dp"
        android:text="@string/save_practice_edit"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/button10"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="24dp"
        android:text="@string/quit_practice_edit"
        app:layout_constraintBaseline_toBaselineOf="@+id/button5"
        app:layout_constraintEnd_toEndOf="parent" />
</android.support.constraint.ConstraintLayout>

listView中使用的自定义布局:

    

    <TextView
        android:id="@+id/practiceStageNameTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <NumberPicker
        android:id="@+id/practiceStageNumberPicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

很抱歉,这有点冗长。非常感谢您的帮助,在此先感谢!

0 个答案:

没有答案