androidlistviewandroid-listviewandroid-parsequeryadapter

Set onTouchListener for evey item in ParseQueryAdapter


I have a HorizontalScrollView as an item of ListView. There is clickable image in each HorizontalScrollView. Also Horizontal scroll view should have specific behavior of scrolling. I have already implemented it for single HorizontalScrollView. But now I need to make a List of these scroll views and each of them should have this behavior. I'm using ParseQueryAdapter, because I get information from parse.com. When I tried to use the code for specific scroll on each item, only the last item had this behavior. And laso it worked quite bad. But maybe it's my fault. Please help me to set the onTouchListener for each item. And the onClickListener for each ImageView in each item. This is my code

public class CustomParseQueryAdapter extends ParseQueryAdapter<Lighter> {
    Activity activity;
    int rankNumber;
    Bitmap bitmap;
    int currentScrollViewPosition;
    int middlePosition;

    HorizontalScrollView itemScrollView;
    RelativeLayout rankParentLayout;
    RelativeLayout lighterNameAndMilesLayout;

    GestureDetector gestureDetector;

    public CustomParseQueryAdapter(Context context){
        super(context, new QueryFactory<Lighter>() {
            @Override
            public ParseQuery<Lighter> create() {
                ParseQuery<Lighter> query = new ParseQuery<>("Lighter");
                query.orderByDescending("miles");
                query.include("master");
                return query;
            }
        });
        activity = (Activity) context;
        rankNumber = 1;
    }

    @Override
    public View getItemView(Lighter lighter, View v, ViewGroup parent) {
        if (v == null){
            v = View.inflate(getContext(), R.layout.ranking_list_item, null);
        }

        super.getItemView(lighter, v, parent);

        gestureDetector = new GestureDetector(new CustomGestureDetector());

        itemScrollView = (HorizontalScrollView) v.findViewById(R.id.item_scroll_view);



        LinearLayout itemParentLayout = (LinearLayout) v.findViewById(R.id.rank_item_linear_scroll_view);
        RelativeLayout crossedCitiesParentLayout = (RelativeLayout) v.findViewById(R.id.item_crossed_cities_layout);
        RelativeLayout timesCheckedParentLayout = (RelativeLayout) v.findViewById(R.id.item_times_checked_layout);
        rankParentLayout = (RelativeLayout) v.findViewById(R.id.item_rank_layout);
        lighterNameAndMilesLayout = (RelativeLayout) v.findViewById(R.id.item_lighter_name_and_miles_layout);

        TextView crossedCitiesAmount = (TextView) v.findViewById(R.id.item_crossed_cities);
        TextView timesCheckedAmount = (TextView) v.findViewById(R.id.item_times_checked);
        TextView itemRankNumber = (TextView) v.findViewById(R.id.item_rank_number);

        ImageView lighterImage = (ImageView) v.findViewById(R.id.item_lighter_image);
        TextView lighterName = (TextView) v.findViewById(R.id.item_lighter_name);
        TextView milesTravelled = (TextView) v.findViewById(R.id.item_lighter_miles_travelled);

// This userImage ImageView should have the onClickListener to start another fragment
        ImageView userImage = (ImageView) v.findViewById(R.id.item_user_image);

        String lighterColor = lighter.getColor();
        itemParentLayout.setBackgroundColor(FragmentMap.getColor(lighterColor, activity.getResources()));
        crossedCitiesParentLayout.setBackgroundColor(FragmentMap.getAnotherColor(lighterColor, activity.getResources()));
        timesCheckedParentLayout.setBackgroundColor(FragmentMap.getAnotherColor(lighterColor, activity.getResources()));
        rankParentLayout.setBackgroundColor(FragmentMap.getAnotherColor(lighterColor, activity.getResources()));
        lighterNameAndMilesLayout.getLayoutParams().width = FragmentMap.getScreenSize(activity).x - FragmentMap.MARGIN;

        crossedCitiesAmount.setText(lighter.getCitiesAmount() + " CITIES");
        timesCheckedAmount.setText(lighter.getTimesChecked() + " TIMES");
        itemRankNumber.setText(String.valueOf(rankNumber));
        rankNumber++;

        setUpLighterImage(lighterImage, lighterColor);
        lighterName.setText(lighter.getLighterName().toUpperCase());
        milesTravelled.setText(lighter.getIntMiles() + " MILES TRAVELLED");
        final ParseUser lighterMasterUser = lighter.getParseUser("master");
        final String userProfileID = lighterMasterUser.getString("profileID");
        Thread thread = new Thread(new Runnable() {
            public void run() {
                bitmap = FragmentMap.getBitmap(userProfileID, activity);
            }
        });
        thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        userImage.setImageBitmap(FragmentMap.getBitmapWithTineCircle(bitmap, activity));

        middlePosition = rankParentLayout.getBottom() - FragmentMap.MARGIN;

        v.post(new Runnable() {
            @Override
            public void run() {
                itemScrollView.scrollTo(middlePosition, 0);
                currentScrollViewPosition = 0;
            }
        });

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

        return v;
    }

    private void setUpLighterImage(ImageView view, String color){
        switch (color){
            case "red":
                view.setImageResource(R.drawable.red);
                break;
            case "pink":
                view.setImageResource(R.drawable.pink);
                break;
            case "green":
                view.setImageResource(R.drawable.green);
                break;
            case "orange":
                view.setImageResource(R.drawable.orange);
                break;
            case "yellow":
                view.setImageResource(R.drawable.yellow);
                break;
            case "silver":
                view.setImageResource(R.drawable.silver);
                break;
            // it is gold, but was light brown
            case "gold":
                view.setImageResource(R.drawable.gold);
                break;
            case "copper":
                view.setImageResource(R.drawable.copper);
                break;
        }
    }

    class CustomGestureDetector extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                               float velocityY) {
            if (e1.getX() < e2.getX()) {
                getScrollPosition("left");
            } else {
                getScrollPosition("right");
            }
//            mapTitleScrollView.smoothScrollTo(scrollPosition, 0);
            return true;
        }
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
                                float distanceY){
            return true;
        }
    }

    private void getScrollPosition(String direction){
        switch (direction){
            case "left":
                if (currentScrollViewPosition == 1){ // if scrollview is in rightmost position move to center
                    toCenterPosition();
                } else if (currentScrollViewPosition == 0){ // if scrollview is in center position move left
                    toLeftPosition();
                }
                break;
            case "right":
                if (currentScrollViewPosition == -1){ // if scrollview is in leftmost position move to center
                    toCenterPosition();
                } else if (currentScrollViewPosition == 0){ // if scrollview is in center position move right
                    toRightPosition();
                }
                break;
        }
    }

    private void toLeftPosition(){
        currentScrollViewPosition = -1;
        itemScrollView.fullScroll(HorizontalScrollView.FOCUS_LEFT);
    }

    private void toRightPosition(){
        currentScrollViewPosition = 1;
        itemScrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
    }

    private void toCenterPosition(){
        currentScrollViewPosition = 0;
        itemScrollView.smoothScrollTo(middlePosition, 0);
    }
}

This is my ListView fragment code

public class FragmentList extends ListFragment {

    ApplicationInterface fragmentHolder;

    CustomParseQueryAdapter mainAdapter;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            fragmentHolder = (ApplicationInterface) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString());
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_list, container, false);

        mainAdapter = new CustomParseQueryAdapter(getActivity());
        setListAdapter(mainAdapter);

        return view;
    }
}

And XML for ListView:

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

Also I need onClickListener on whole item of the list view. But I think it should be implemented in my FragmentList class


Solution

  • Ok, so if anyone is interested in my solution, here it is: The reason why my gesture detector was working only on the last item of the list view is the global variable for storing HorizontalScrollView. I made it local and passed it as a parameter to my gesture detector. Also I have changed the onFling method detection, because it has conflicts with onClick listener. It trhows the NullPointerException, telling me that I'm trying to use method MotionEvent.getX() on a null object. This is how my code looks now:

    public class CustomParseQueryAdapter extends ParseQueryAdapter<Lighter> {
        Activity activity;
        int rankNumber;
        Bitmap bitmap;
        int currentScrollViewPosition;
    
        ApplicationInterface fragmentHolder;
    
        public CustomParseQueryAdapter(Context context, ApplicationInterface fragmentHolder){
            super(context, new QueryFactory<Lighter>() {
                @Override
                public ParseQuery<Lighter> create() {
                    ParseQuery<Lighter> query = new ParseQuery<>("Lighter");
                    query.orderByDescending("miles");
                    query.include("master");
                    return query;
                }
            });
            activity = (Activity) context;
            rankNumber = 1;
    
            this.fragmentHolder = fragmentHolder;
        }
    
        @Override
        public View getItemView(final Lighter lighter, View v, ViewGroup parent) {
            if (v == null){
                v = View.inflate(getContext(), R.layout.ranking_list_item, null);
            }
    
    
    
            final HorizontalScrollView itemScrollView = (HorizontalScrollView) v.findViewById(R.id.item_scroll_view);
            itemScrollView.setSmoothScrollingEnabled(true);
    
            v.post(new Runnable() {
                @Override
                public void run() {
                    itemScrollView.fullScroll(View.FOCUS_RIGHT);
                    currentScrollViewPosition = 1;
                }
            });
    
            LinearLayout itemParentLayout = (LinearLayout) v.findViewById(R.id.rank_item_linear_scroll_view);
            RelativeLayout crossedCitiesParentLayout = (RelativeLayout) v.findViewById(R.id.item_crossed_cities_layout);
            RelativeLayout timesCheckedParentLayout = (RelativeLayout) v.findViewById(R.id.item_times_checked_layout);
            RelativeLayout rankParentLayout = (RelativeLayout) v.findViewById(R.id.item_rank_layout);
            RelativeLayout lighterNameAndMilesLayout = (RelativeLayout) v.findViewById(R.id.item_lighter_name_and_miles_layout);
    
            TextView crossedCitiesAmount = (TextView) v.findViewById(R.id.item_crossed_cities);
            TextView timesCheckedAmount = (TextView) v.findViewById(R.id.item_times_checked);
            TextView itemRankNumber = (TextView) v.findViewById(R.id.item_rank_number);
    
            ImageView lighterImage = (ImageView) v.findViewById(R.id.item_lighter_image);
            TextView lighterName = (TextView) v.findViewById(R.id.item_lighter_name);
            TextView milesTravelled = (TextView) v.findViewById(R.id.item_lighter_miles_travelled);
            ImageView userImage = (ImageView) v.findViewById(R.id.item_user_image);
    
            final String lighterColor = lighter.getColor();
            final String lighterObjectId = lighter.getObjectId();
            itemParentLayout.setBackgroundColor(FragmentMap.getColor(lighterColor, activity.getResources()));
            crossedCitiesParentLayout.setBackgroundColor(FragmentMap.getColor(lighterColor, activity.getResources()));
            timesCheckedParentLayout.setBackgroundColor(FragmentMap.getAnotherColor(lighterColor, activity.getResources()));
            rankParentLayout.setBackgroundColor(FragmentMap.getAnotherColor(lighterColor, activity.getResources()));
            lighterNameAndMilesLayout.getLayoutParams().width = FragmentMap.getScreenSize(activity).x - FragmentMap.MARGIN;
    
            crossedCitiesAmount.setText(lighter.getCitiesAmount() + " CITIES");
            timesCheckedAmount.setText(lighter.getTimesChecked() + " TIMES");
            itemRankNumber.setText("#" + String.valueOf(rankNumber));
            rankNumber++;
    
            setUpLighterImage(lighterImage, lighterColor);
            lighterName.setText(lighter.getLighterName().toUpperCase());
            milesTravelled.setText(lighter.getIntMiles() + " MILES TRAVELLED");
            final ParseUser lighterMasterUser = lighter.getParseUser("master");
            final String userProfileID = lighterMasterUser.getString("profileID");
            Thread thread = new Thread(new Runnable() {
                public void run() {
                    bitmap = FragmentMap.getBitmap(userProfileID, activity);
                }
            });
            thread.start();
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            userImage.setImageBitmap(FragmentMap.getBitmapWithTineCircle(bitmap, activity));
    
            final GestureDetector gestureDetector = new GestureDetector(
                    new CustomGestureDetector(currentScrollViewPosition, itemScrollView));
    
            lighterNameAndMilesLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    fragmentHolder.onMapRedirect(lighterObjectId, lighterColor);
                }
            });
    
            itemScrollView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    return gestureDetector.onTouchEvent(event);
                }
            });
    
            super.getItemView(lighter, v, parent);
    
            return v;
        }
    
        private void setUpLighterImage(ImageView view, String color){
            switch (color){
                case "red":
                    view.setImageResource(R.drawable.red);
                    break;
                case "pink":
                    view.setImageResource(R.drawable.pink);
                    break;
                case "green":
                    view.setImageResource(R.drawable.green);
                    break;
                case "orange":
                    view.setImageResource(R.drawable.orange);
                    break;
                case "yellow":
                    view.setImageResource(R.drawable.yellow);
                    break;
                case "silver":
                    view.setImageResource(R.drawable.silver);
                    break;
                // it is gold, but was light brown
                case "gold":
                    view.setImageResource(R.drawable.gold);
                    break;
                case "copper":
                    view.setImageResource(R.drawable.copper);
                    break;
            }
        }
    
        class CustomGestureDetector extends GestureDetector.SimpleOnGestureListener {
            int currentScrollViewPosition;
            HorizontalScrollView itemScrollView;
    
            public CustomGestureDetector(int currentPosition, HorizontalScrollView scrollView){
                currentScrollViewPosition = currentPosition;
                itemScrollView = scrollView;
            }
    
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                                   float velocityY) {
                if (velocityX > 0){
                    getScrollPosition("left");
                } else {
                    getScrollPosition("right");
                }
                return true;
            }
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
                                    float distanceY){
                if (distanceX < 0){
                    getScrollPosition("left");
                } else {
                    getScrollPosition("right");
                }
                return true;
            }
    
            private void getScrollPosition(String direction){
                switch (direction){
                    case "left":
                        if (currentScrollViewPosition == 1){
                            toLeftPosition();
                        } else if (currentScrollViewPosition == 0){
                        toLeftPosition();
                    }
                        break;
                    case "right":
                        if (currentScrollViewPosition == -1){
                            toRightPosition();
                        } else if (currentScrollViewPosition == 0){
                        toRightPosition();
                    }
                        break;
                }
            }
    
            private void toLeftPosition(){
                currentScrollViewPosition = -1;
                itemScrollView.fullScroll(HorizontalScrollView.FOCUS_LEFT);
            }
    
            private void toRightPosition(){
                currentScrollViewPosition = 1;
                itemScrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
            }
        }
    }