Android ListView :: Scrolling ListView while item is selected causes display problems

432 views Asked by At

Alright, so I'm using a ListView with a custom adapter. Everything works fine and dandy...until the user selects a ListView row and tries to scroll.

When the user selects a row, the background color of that row changes to blue (which is good).

But, problems occur when we begin scrolling: When we scroll past the selected row, the blue fixes itself to either the bottom or the top of the ListView, depending on which way we were scrolling.

Selected row changes color on touch (good)
Selected Row Looks Good


Part of the background of selected row is fixed to top when scrolling down (not good)
enter image description here


Part of the background of selected row is fixed to bottom when scrolling up (not good)
enter image description here



Here is my source code:

List View that I'm populating dynamically

<ListView
     android:id="@+id/tallyDataListView"
     android:layout_height="wrap_content"
     android:layout_width="fill_parent"
     android:divider="#000000"
     android:dividerHeight="1dp"
     android:fadeScrollbars="false"
     android:listSelector="#0099FF" >


layout_list_view_row.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <View
        android:focusable="false"
        android:focusableInTouchMode="false"
        style="@style/tableSideBorderLine" />

    <TextView
        android:id="@+id/COLUMN_PIPE_NUMBER"
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:layout_weight="1"
        style="@style/tableColumn"
        xmlns:android="http://schemas.android.com/apk/res/android" />

    <View
        android:focusable="false"
        android:focusableInTouchMode="false"
        style="@style/tableColumnDivider" />

    <TextView
        android:id="@+id/COLUMN_TOTAL_LENGTH"
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:layout_weight="1"
        style="@style/tableColumn"
        xmlns:android="http://schemas.android.com/apk/res/android" />

    <View
        android:focusable="false"
        android:focusableInTouchMode="false"
        style="@style/tableColumnDivider" />

    <TextView
        android:id="@+id/COLUMN_ADJUSTED"
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:layout_weight="1"
        style="@style/tableColumn"
        xmlns:android="http://schemas.android.com/apk/res/android" />

    <View
        android:focusable="false"
        android:focusableInTouchMode="false"
        style="@style/tableSideBorderLine" />

</LinearLayout>



My Custom Adapter

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.util.ArrayList;

public class ListViewAdapter extends ArrayAdapter<String>{

    LayoutInflater inflater;
    private final ArrayList<String> adjustedValues;
    private final ArrayList<String> pipeNumbers;
    private final ArrayList<String> totalLengthValues;

    public ListViewAdapter(Activity pContext, ArrayList<String> pPipeNumbers,
                           ArrayList<String> pTotalLengthValues, ArrayList<String> pAdjustedValues)
    {

        super(pContext, R.layout.layout_list_view_row, pAdjustedValues);

        adjustedValues = pAdjustedValues;
        pipeNumbers = pPipeNumbers;
        totalLengthValues = pTotalLengthValues;

        inflater = pContext.getLayoutInflater();

    }

    @Override
    public View getView(int pPosition, View pView, ViewGroup pParent)
    {

        View view = inflater.inflate(R.layout.layout_list_view_row, pParent, false);

        TextView col1 = (TextView)view.findViewById(R.id.COLUMN_PIPE_NUMBER);
        col1.setText(pipeNumbers.get(pPosition));
        TextView col2 = (TextView)view.findViewById(R.id.COLUMN_TOTAL_LENGTH);
        col2.setText(totalLengthValues.get(pPosition));
        TextView col3 = (TextView)view.findViewById(R.id.COLUMN_ADJUSTED);
        col3.setText(adjustedValues.get(pPosition));

        return view;

    }
}
2

There are 2 answers

0
desidigitalnomad On

Keep a reference for selected row position in your Adapter, say

int selectedPos = -1;

The value will be -1 when no row is selected. And in the OnItemClickListener of the listview,update selectedPos with the clicked position and call notifyDatasetChanged() on the adapter. In the getView method of the adapter, check for the selectedPos value and highlight the row accordingly.

0
rawhost On

This is the common problem about the listview. When you scroll down it creates the new view every time. That is why the selected element from the top gets out of the focus and another element is selected. For this problem you have to extend the BaseAdapter class and

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    Vehical vehical = vehicals.get(position);
    ViewHolder viewHolder = null;

    if(convertView==null)
    {
        viewHolder = new ViewHolder();
        convertViewactivity.getLayoutInflater().inflate(R.layout.list_item,null);
        convertView.setTag(viewHolder);
    }
    else
    {
        viewHolder = (ViewHolder) convertView.getTag();
    }

    viewHolder.tvVehicalName = (TextView) convertView.findViewById(R.id.vehicle_name);
    viewHolder.tvVehicalName.setText(vehical.getVehicalName());

    if(vehical.isSelected()){
        viewHolder.tvVehicalName.setTextColor(Color.RED);
    }
    else
    {
        viewHolder.tvVehicalName.setTextColor(Color.BLACK);
    }
    return convertView;
}
//On listener of the listview
searchList.setOnItemClickListener(

    new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3) {

            if(searchAdapter.isItemSelected(position))
            {
                searchAdapter.setSelectedItem(position,false);
                selectedList.remove(((Vehical)searchAdapter.getItem(position)).getVehicalName());
            }
            else
            {
                if(selectedList.size()<new_vehiclelimit){
                    searchAdapter.setSelectedItem(position,true);
                    selectedList.add(((Vehical)searchAdapter.getItem(position)).getVehicalName());
                }
                else
                {
                    Toast.makeText(getApplicationContext(), "Vechicle Limit is Over", Toast.LENGTH_SHORT).show();
                }
            }