Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synchronize all the ListView in a ViewPager

In my application I have a ViewPager with each one a custom ListView in it linked toghether like row in a table. The problem is that when I scroll a ListView in the first page and then I scroll the ViewPager the ListView of the first page and the ListView of the second page are misaligned. The listView must be aligned because in the first one i have a TextView with a description and then 4 coloumns with datas and in the next ListViews 6 coloumns without the description so if they are misaligned it's very complicated. So how can I scroll all the listViews at once ??

EDIT:

Thank you very much to Rahul Parsani... I've finally managed how to do this... If you have the listView in separate fragment and the number of the fragment is undefined this is the answer:

final ArrayList<ListView> lvs = new ArrayList<ListView>();
        for (int j = 0; j < adapter.getCount(); j++) {
            YourFragment fragJ = (YourFragment) adapter.getItem(j);
            final ListView listViewJ = fragJ.lv;
            lvs.add(listViewJ);
        }

        for (int j = 0; j < lvs.size(); j++) {
            final int x = j;
            lvs.get(j).setOnTouchListener(new OnTouchListener() {

                boolean dispatched = false;
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (!dispatched) {
                        dispatched = true;
                        if (x != 0) {
                            lvs.get(x - 1).dispatchTouchEvent(event);
                        };
                        if (x != lvs.size() - 1) {
                            lvs.get(x + 1).dispatchTouchEvent(event);
                        }

                    }
                    dispatched = false;
                    return false;
                }
            });
        }
like image 344
Matteo Cardellini Avatar asked Nov 10 '13 16:11

Matteo Cardellini


2 Answers

What you are trying to do is synchronize the listviews. There is a library that already implements this for two listviews here. I will try to explain the part of the source code relevant to you which is located in the activity here.

Suppose if you have access to all your listviews through variables:

listViewOne = (ListView) findViewById(R.id.list_view_one);
listViewTwo = (ListView) findViewById(R.id.list_view_two);
listViewThree = (ListView) findViewById(R.id.list_view_three);
listViewFour = (ListView) findViewById(R.id.list_view_four);

Set the same touch listeners on them:

listViewOne.setOnTouchListener(touchListener);
listViewTwo.setOnTouchListener(touchListener);
// similarly for listViewThree & listViewFour

The basic idea of the touch listener is to dispatch events to the other views so that they also scroll synchronously with the listview being touched.

// Passing the touch event to the opposite list
OnTouchListener touchListener = new OnTouchListener() {                                        
    boolean dispatched = false;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (v.equals(listViewOne) && !dispatched) {
            dispatched = true;
            listViewTwo.dispatchTouchEvent(event);
            listViewThree.dispatchTouchEvent(event);
            listViewFour.dispatchTouchEvent(event);
        } else if (v.equals(listViewTwo) && !dispatched) {
            dispatched = true;
            listViewOne.dispatchTouchEvent(event);
            listViewThree.dispatchTouchEvent(event);
            listViewFour.dispatchTouchEvent(event);
         } // similarly for listViewThree & listViewFour 
         dispatched = false;
         return false;
    }
};

The library also has set a scroll listener, which I believe is used because the views may be of differing heights, which you don't have. Try and let me know if this works.

like image 137
rarp Avatar answered Sep 29 '22 11:09

rarp


The problem you are having is similar to this one Update ViewPager dynamically?. It has nothing to do with setting onTouchListener because you don't have access to all ListViews inside ViewPager.

Following is a working and tested code. Key point is getItemPosition() method in PagerAdapter.

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.ListFragment;
import android.support.v4.view.ViewPager;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends FragmentActivity implements ScrollListener {
private MyPagerAdapter mPagerAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    MyPagerAdapter pagerAdapter = mPagerAdapter = new MyPagerAdapter(
            getSupportFragmentManager(), this);
    pagerAdapter.addFragmentInfo(DummyFragment.class.getName(), "First",
            new Bundle());
    pagerAdapter.addFragmentInfo(DummyFragment.class.getName(), "Second",
            new Bundle());
    pagerAdapter.addFragmentInfo(DummyFragment.class.getName(), "Third",
            new Bundle());

    final ViewPager pager = (ViewPager) findViewById(R.id.pager);
    pager.setOffscreenPageLimit(2);
    pager.setAdapter(pagerAdapter);
}

@Override
public void onScrollChanged(int index) {
    mPagerAdapter.setIndex(index);
}

@Override
public int getCurrentScrollIndex() {
    return mPagerAdapter == null ? 0 : mPagerAdapter
            .getCurrentScrollIndex();
}

public static class MyPagerAdapter extends FragmentStatePagerAdapter {

    public static class FragmentInfo {

        public FragmentInfo(String fragmentName, String title, Bundle args) {
            super();
            this.fragmentName = fragmentName;
            this.title = title;
            this.args = args;
        }

        String fragmentName;
        String title;
        Bundle args;
    }

    private List<FragmentInfo> mFragmentInfos = new ArrayList<FragmentInfo>();
    private final Context mContext;
    private int mIndex;

    public MyPagerAdapter(FragmentManager fm, Context context) {
        super(fm);

        mContext = context;
    }

    @Override
    public Fragment getItem(int position) {
        FragmentInfo info = mFragmentInfos.get(position);
        Fragment fragment = Fragment.instantiate(mContext,
                info.fragmentName, info.args);
        return fragment;
    }

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

    @Override
    public int getItemPosition(Object object) {
        if (object instanceof ScrollRefreshable) {
            ((ScrollRefreshable) object).refreshScroll(mIndex);
        }
        return super.getItemPosition(object);
    }

    public void addFragmentInfo(String fragmentName, String title,
            Bundle args) {
        mFragmentInfos.add(new FragmentInfo(fragmentName, title, args));
    }

    public void setIndex(int index) {
        mIndex = index;
        notifyDataSetChanged();
    }

    public int getCurrentScrollIndex() {
        return mIndex;
    }
}


public static class DummyFragment extends ListFragment implements
        ScrollRefreshable {
    private ScrollListener mRefreshListener;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (activity instanceof ScrollListener) {
            mRefreshListener = (ScrollListener) activity;
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        String[] values = new String[] { "Android", "iPhone",
                "WindowsMobile", "Blackberry", "WebOS", "Ubuntu",
                "Windows7", "Max OS X", "Linux", "OS/2", "Android2",
                "iPhone2", "WindowsMobile2", "Blackberry2", "WebOS2",
                "Ubuntu2", "Windows72", "Max OS X2", "Linux2", "OS/22" };
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                getActivity(), android.R.layout.simple_list_item_1, values);
        setListAdapter(adapter);
        getListView().setOnScrollListener(new OnScrollListener() {

            @Override
            public void onScrollStateChanged(AbsListView view,
                    int scrollState) {
                if (scrollState == SCROLL_STATE_IDLE) {
                    if (mRefreshListener != null) {
                        mRefreshListener.onScrollChanged(view
                                .getFirstVisiblePosition());
                    }
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem,
                    int visibleItemCount, int totalItemCount) {
            }
        });
        // update scroll position at start
        if (mRefreshListener != null) {
            int index = mRefreshListener.getCurrentScrollIndex();
            scrollListViewTo(index);
        }
    }

    @Override
    public void refreshScroll(int index) {
        scrollListViewTo(index);
    }

    private void scrollListViewTo(int index) {
        ListView lv = getListView();
        if (lv != null) {
            lv.setSelection(index);
        }
    }
}
}

interface ScrollRefreshable {
public void refreshScroll(int index);
}

interface ScrollListener {
public void onScrollChanged(int index);

public int getCurrentScrollIndex();
}
like image 25
M-WaJeEh Avatar answered Sep 29 '22 09:09

M-WaJeEh