如何将相同的动作事件传递给listview中的所有项目?

时间:2016-11-16 07:06:55

标签: android adapter ontouchlistener motionevent

我有一个列表视图,其中每个项目都是textview和自定义视图。这是listview项目的布局:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<net.manualuser.calibr.TimeScale
    android:id="@+id/my_scale"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingLeft="20dp"
    android:paddingTop="40dp">

    <TextView
        android:id="@+id/counter"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

TimeScale是一个自定义视图,可以绘制标尺并处理水平滚动。

我想将相同的动作事件传递给每个项目的标尺,这样当我从列表中滚动一个时,其他项目同时滚动。

在适配器中,我将侦听器设置为自定义视图。这是getView部分:

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
    View v = view;
    if(view == null) {
        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.time_scale_item, viewGroup, false);
    }

    scale = (TimeScale)v.findViewById(R.id.my_scale);

    scale.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            scale.onTouchEvent(event);
            return false;
        }
    });

    TextView text = (TextView)v.findViewById(R.id.counter);
    text.setText(Cities.get(i));
    return v;
}

在主要活动中,我找到我的列表并设置适配器。 假设我在listview中有4个项目。但只有2个同时移动。将相同的运动事件传递给列表中的所有标尺的正确方法是什么?

2 个答案:

答案 0 :(得分:0)

如果我理解,如果你滚动其中一个,你想要滚动所有TimeScale。 在这种情况下,我使用regsiter(TimeScale ts)方法和scrollAll()以及unregisterAll()方法创建单一管理器类。 在适配器中,getView()将视图注册到管理器,当您在TimeScale上滚动时也调用scrollAll()方法,当列表被销毁时,调用unregister all来删除Timescales引用。 但也许最好在观看onAttachToWindow()注册并注销atDetachFromWindow()。我不知道。 在这种情况下,我会检查这个解决方案与LeakCanary不会导致内存泄漏。 其他解决方案可以是LocalBroadcastManager,但我不知道它是否会导致性能问题。

答案 1 :(得分:0)

您的适配器应该使用回调方法实现一个接口,您可以在其中传递新值(或者只是向您的适配器添加一个公共方法)。然后将接口(或适配器)传递给每个视图,当您更改该值时,可以调用回调方法并传递新值。 在您实现此方法的适配器中,您可以循环收集集合并通过setter方法设置新值。

public class MyAdapter extends BaseAdapter implements OnValueChanged {
ArrayList<ListItem> listItems = new ArrayList<>();

public MyAdapter() {
    super();
}

@Override
public int getCount() {
    return 0;
}

@Override
public Object getItem(int position) {
    return null;
}

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    return null;
}

@Override
public void onValueChanged(int newValue) {
    for (ListItem listItem : listItems) listItem.setValue(newValue);
}

class ListItem extends View implements View.OnClickListener {
    private int value;
    private OnValueChanged onValueChanged;

    public ListItem(Context context, OnValueChanged onValueChanged) {
        super(context);
        this.onValueChanged = onValueChanged;
        setOnClickListener(this);
    }

    public void setValue(int value) {
        this.value = value;
    }

    @Override
    public void onClick(View v) {
        int newValue = 1;
        onValueChanged.onValueChanged(newValue);
    }
}

}

interface OnValueChanged {
void onValueChanged(int newValue);

}