0

I have a listview where every item is textview and custom view. Here is layout of listview item:

<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 here is a custom view which draws a ruler and handles horizontal scrolling.

I want to pass same motion event to every item's ruler so that when i scroll one from the list others scroll simultaneously.

In adapter i set listener to custom view. Here is getView portion:

@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;
}

In Main Activity i find my list and set adapter to it. Let's say i have 4 items in listview. But only 2 move simultaneously. What is a proper way to pass same motion event to all rulers in list?

Aleksey Bulin
  • 85
  • 2
  • 9
  • It works partly. In the list of two items when i scroll the first one the second moves also but not contrariwise just as if there is no ontouchlistener set on the second view. But when there are three items in a list they scroll in pairs: one-three, two-three and last one scrolls only itself. – Aleksey Bulin Nov 23 '16 at 04:41

2 Answers2

0

if I understand, you want to make scroll all TimeScale if you scroll one of them. In this case I'd make a singletone manager class with a regsiter(TimeScale ts) method and a scrollAll() and unregisterAll() methods. In adapter getView() register the view to the manager, and when you scroll on a TimeScale call scrollAll() method too and when the list is destroyed call unregister all to delete Timescales references. But maybe it's better to register at view's onAttachToWindow() and unregister at onDetachFromWindow(). I don't know. In this case I would check this solution with LeakCanary doesn't it cause memory leaks. Other solution can be LocalBroadcastManager, but I don't know won't it cause performance issues.

user3057944
  • 701
  • 1
  • 8
  • 19
  • thx but a little bit complicated. I want to find solution to implement in adapter for now. – Aleksey Bulin Dec 01 '16 at 07:29
  • I see. Maybe you can loop trough the list of adapter elements when you change the value on one of them and set the same value at all elements. – user3057944 Dec 01 '16 at 11:06
  • that's what i want to do but i don't know how can i get acccess to particular widget from the list. I simplified my task: lets say i have a list with two items with textview. When i click one textview both change text. Of course i can change text of clicked textview in onclick method in getview: text.settext. But how do i get access to textview from another item? – Aleksey Bulin Dec 01 '16 at 11:50
0

Your adapter should implement an interface with a callback method, where you can pass the new value (or just add a public method to your adapter). Then pass the interface (or the adapter) to each view, and when you change the value you can call the callback method and pass the new value. In you adapter where you implemented this method you can loop trough your collection and set the new value by a setter method.

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);

}

user3057944
  • 701
  • 1
  • 8
  • 19