简体   繁体   中英

Android Listview autoscroll makes items invisible

I have progress listview of progress items. Whenever the item is finished I checkmark it.

This Progress items are divided into Phases. Each phase can contain Steps. After all steps are done and marked with checkmark, code marks whole phase as done.

At the end what I do is just render a listview of phases and for each phase I dynamicly add another listview in it. I end up with listview with more listviews in it.

This works fine and I don't have any problems with it.

My boss asked me to create auto scroller which would follow the steps as being completed. This I implemented and was happy to see that It works.

Problem: I was happy that It works only to the point when the something little over of half is reached. Then suddenly items disapear. When I touch the list, List goes back to top and all the items are visible.

Any idea what could couse this behavior?

The code for this is quite large so I will share only the parts I think are needed.

//Adapters

public class ProcessFeedbackAdapter extends android.widget.BaseAdapter {

    public static final String TAG = "ProcessFeedbackAdapter";
    public Context appContext;
    public ProgressOverviewData ProgressOverviewData;
    public ListView Listview;
    public int FirstNotCompletedIndex=0;



    public void UpdateList(){

        HotApplication.getHandler().post(new Runnable(){
            @Override
            public void run() {
                notifyDataSetChanged();
            }
        });

    }

    public ProcessFeedbackAdapter(Context Context,ProgressOverviewData ProgressOverviewData,ListView listview){
        this.appContext=Context;
        this.ProgressOverviewData=ProgressOverviewData;
        this.Listview=listview;
    }
    @Override
    public int getCount() {
        return ProgressOverviewData.Phases.size();
    }

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

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

    public void ScrollToCurrentlyActiveTask(int y){

        int listviewBottom = Listview.getBottom();
        if(listviewBottom <y*50){

            Listview.scrollTo(0, listviewBottom);
        }
        else {
            Listview.scrollTo(0,y*50);
        }
        Listview.computeScroll();
    }


    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        try {

            Phase curItem = ProgressOverviewData.Phases.get(i);
            LayoutInflater inflater = (LayoutInflater) appContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.progress_list_item, null);
            ListView ChildList=view.findViewById(R.id.childrenList);
            ViewGroup.LayoutParams params = ChildList.getLayoutParams();
            int ListHeight=curItem.PhaseSteps.size()*50;
            params.height=ListHeight;
            ChildList.setLayoutParams(params);

            TextView ProgressMessage = (TextView) view.findViewById(R.id.ProgressMessage);
            ImageView Check = (ImageView) view.findViewById(R.id.CheckMark);
            ImageView ErrorMark = (ImageView) view.findViewById(R.id.ErrorMark);

            ProcessFeedbackChildrenAdapter ChilAdapter=new ProcessFeedbackChildrenAdapter(appContext,curItem.PhaseSteps);
            ChildList.setAdapter(ChilAdapter);

            int CheckVisibility = 0;
            int ErrorVisibility=0;
            if(curItem.Status.equals(AppEnums.StepResult.NotCompleted)){
                CheckVisibility=View.INVISIBLE;
                ErrorVisibility=View.INVISIBLE;
            }
            else if(curItem.Status.equals(AppEnums.StepResult.Completed)){
                    CheckVisibility=View.VISIBLE;
                    ErrorVisibility=View.INVISIBLE;
            }
            else if(curItem.Status.equals(AppEnums.StepResult.Failed)){
                ErrorVisibility=View.VISIBLE;
                CheckVisibility=View.INVISIBLE;
            }

            Check.setVisibility(CheckVisibility);
            ErrorMark.setVisibility(ErrorVisibility);
            ProgressMessage.setText(curItem.PhaseName);


            return view;
        } catch (Exception e) {
            System.out.println("Something went wrong.");
        }
        return view;
    }
}

class ProcessFeedbackChildrenAdapter extends android.widget.BaseAdapter {

    public static final String TAG = "ProcessFeedbackChildrenAdapter";
    public Context appContext;
    public ArrayList<Step> Steps= new ArrayList<Step>();



    public void UpdateList(){

        HotApplication.getHandler().post(new Runnable(){
            @Override
            public void run() {
                notifyDataSetChanged();
            }
        });

    }

    public ProcessFeedbackChildrenAdapter(Context Context,ArrayList<Step> Steps){
        this.appContext=Context;
        this.Steps=Steps;
    }
    @Override
    public int getCount() {
        return Steps.size();
    }

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

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



    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        try {

            LayoutInflater inflater = (LayoutInflater) appContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.progress_list_item_children, null);


            TextView ProgressMessage = (TextView) view.findViewById(R.id.ProgressMessage);
            ImageView Check = (ImageView) view.findViewById(R.id.CheckMark);
            ImageView ErrorMark = (ImageView) view.findViewById(R.id.ErrorMark);
            Step curItem = Steps.get(i);


            int CheckVisibility = 0;
            int ErrorVisibility=0;
            if(curItem.Status== AppEnums.StepResult.NotCompleted){
                CheckVisibility=View.INVISIBLE;
                ErrorVisibility=View.INVISIBLE;
            }else {
                if(curItem.Status== AppEnums.StepResult.Completed){
                    CheckVisibility=View.VISIBLE;
                    ErrorVisibility=View.INVISIBLE;
                }
                else if(curItem.Status==AppEnums.StepResult.Failed){
                    ErrorVisibility=View.VISIBLE;
                    CheckVisibility=View.INVISIBLE;
                }
            }



            ProgressMessage.setText(curItem.StepName);

            Check.setVisibility(CheckVisibility);
            ErrorMark.setVisibility(ErrorVisibility);

            return view;
        } catch (Exception e) {
            System.out.println("Something went wrong.");
        }
        return view;
    }
}

// Main list view

        <ListView
            android:id="@+id/ProgressStepsContainer"
            android:layout_width="0dp"
            android:layout_height="267dp"
            android:fastScrollEnabled="false"
            android:scrollbarThumbVertical="@drawable/scrollbar_vertical_thumb"
            android:verticalScrollbarPosition="left"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/ProgressErrorContainer"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/ProgressMessage">

        </ListView>

// Phases list item

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="0dp">

    <ImageView
        android:id="@+id/CheckMark"
        android:layout_width="50dp"
        android:layout_height="50dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_overview_check" />

    <ImageView
        android:id="@+id/ErrorMark"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:visibility="visible"
        app:layout_constraintStart_toStartOf="@+id/CheckMark"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_overview_error" />

    <TextView
        android:id="@+id/ProgressMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="TextView"
        android:textAlignment="center"
        android:textColor="@color/colorWhitish"
        android:textSize="18sp"
        app:layout_constraintBottom_toBottomOf="@+id/CheckMark"
        app:layout_constraintStart_toEndOf="@+id/CheckMark"
        app:layout_constraintTop_toTopOf="parent" />

    <ListView
        android:id="@+id/childrenList"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        app:layout_constraintStart_toEndOf="@+id/CheckMark"
        app:layout_constraintTop_toBottomOf="@+id/ProgressMessage" />

</androidx.constraintlayout.widget.ConstraintLayout>

// Steps (inner) list item

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="50dp">

    <ImageView
        android:id="@+id/CheckMark"
        android:layout_width="50dp"
        android:layout_height="50dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_overview_check" />

    <ImageView
        android:id="@+id/ErrorMark"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:visibility="visible"
        app:layout_constraintStart_toStartOf="@+id/CheckMark"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_overview_error" />

    <TextView
        android:id="@+id/ProgressMessage"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="TextView"
        android:textAlignment="center"
        android:textColor="@color/colorWhitish"
        android:textSize="18sp"
        app:layout_constraintBottom_toBottomOf="@+id/CheckMark"
        app:layout_constraintStart_toEndOf="@+id/CheckMark"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

在此处输入图片说明 在此处输入图片说明

Your adapter code does not work in my phone. Only part of the child list is shown. In addition, I think your requirements are easier to implement by ExpandableListView. Therefore I followed your data structure and created the following demo codes which use ExpandableListView. You can start a new project and try it.

MainActivity.java:

public class MainActivity extends AppCompatActivity {
ProgressOverviewData sampleData;
ProcessFeedbackAdapter1 adapter;
ExpandableListView listView;
TextView textView;
int completedPhase = 0;

@Override
protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    sampleData = new ProgressOverviewData("Project", new ArrayList<Phase>());
    textView = findViewById(R.id.ProgressMessage);
    textView.setText(sampleData.projectName);

    listView = findViewById(R.id.ProgressStepsContainer);
    adapter = new ProcessFeedbackAdapter1(this, sampleData);
    listView.setAdapter(adapter);
    // Disable ExpandableListView from group collapse by override OnGroupClickListener.
    listView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
        @Override
        public boolean onGroupClick(ExpandableListView expandableListView, View view, int i, long l) {
            return true;
        }
    });
    for (int i = 0; i < sampleData.Phases.size(); i++) listView.expandGroup(i);

    Button btAddPhase = findViewById(R.id.bt_add_phase);
    btAddPhase.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Phase newPhase = genNewPhase();
            sampleData.Phases.add(newPhase);
            adapter.notifyDataSetChanged();
            listView.expandGroup(sampleData.Phases.size() - 1);
            textView.setText(sampleData.projectName + " [" + completedPhase + "/" + sampleData.Phases.size() + "]");
        }
    });
    Button btCompletedStep = findViewById(R.id.bt_completed_step);
    btCompletedStep.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            boolean stepCompleted = false;
            Step step;
            String msg = "";
            int viewPosition = 0;
            for (int i = 0; i < adapter.getGroupCount(); i++) {
                viewPosition++;
                for (int j = 0; j < adapter.getChildrenCount(i); j++) {
                    viewPosition++;
                    if (adapter.getChild(i, j).Status == AppEnums.StepResult.NotCompleted) {
                        step = adapter.getChild(i, j);
                        step.Status = AppEnums.StepResult.Completed;
                        msg = step.StepName + " Completed!";
                        if (j == adapter.getGroup(i).PhaseSteps.size() - 1) {
                            adapter.getGroup(i).Status = AppEnums.StepResult.Completed;
                            completedPhase++;
                            textView.setText(sampleData.projectName + " [" + completedPhase + "/" + sampleData.Phases.size() + "]");
                            msg += "\n" + adapter.getGroup(i).PhaseName + " Completed!!!!!";
                        }
                        stepCompleted = true;
                        break;
                    }
                }
                if (stepCompleted) break;
            }
            if (stepCompleted) {
                Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(getApplicationContext(), "All Completed", Toast.LENGTH_LONG).show();
            }
            listView.smoothScrollToPositionFromTop(viewPosition - 1, 0);
            adapter.notifyDataSetChanged();
        }
    });
}

private Phase genNewPhase() {
    int phaseId = sampleData.Phases.size() + 1;
    Random random = new Random();
    int numberOfSteps = random.nextInt(5) + 1;
    ArrayList<Step> steps = new ArrayList<>();
    for (int j = 0; j < numberOfSteps; j++) {
        Step step = new Step("Step " + (phaseId) + "-" + (j + 1));
        steps.add(step);
    }
    return new Phase("Phase " + (phaseId) + " [" + steps.size() + "]", steps);
}
}

ProcessFeedbackAdapter1.java:

public class ProcessFeedbackAdapter1 extends BaseExpandableListAdapter {
public static final String TAG = "ProcessFeedbackAdapter";
public Context appContext;
public ProgressOverviewData ProgressOverviewData;

public ProcessFeedbackAdapter1(Context Context, ProgressOverviewData ProgressOverviewData) {
    this.appContext = Context;
    this.ProgressOverviewData = ProgressOverviewData;
}

@Override
public int getGroupCount() {
    return ProgressOverviewData.Phases.size();
}

@Override
public int getChildrenCount(int i) {
    return ProgressOverviewData.Phases.get(i).PhaseSteps.size();
}

@Override
public Phase getGroup(int i) {
    return ProgressOverviewData.Phases.get(i);
}

@Override
public Step getChild(int i, int i1) {
    return ProgressOverviewData.Phases.get(i).PhaseSteps.get(i1);
}

@Override
public long getGroupId(int i) {
    return 0;
}

@Override
public long getChildId(int i, int i1) {
    return 0;
}

@Override
public boolean hasStableIds() {
    return false;
}

@Override
public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
    try {
        Phase curItem = getGroup(i);
        LayoutInflater inflater = (LayoutInflater) appContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.progress_list_item, null);

        TextView ProgressMessage = view.findViewById(R.id.ProgressMessage);
        ImageView Check = view.findViewById(R.id.CheckMark);
        ImageView ErrorMark = view.findViewById(R.id.ErrorMark);

        int CheckVisibility = 0;
        int ErrorVisibility = 0;
        if (curItem.Status.equals(AppEnums.StepResult.NotCompleted)) {
            CheckVisibility = View.INVISIBLE;
            ErrorVisibility = View.INVISIBLE;
        } else if (curItem.Status.equals(AppEnums.StepResult.Completed)) {
            CheckVisibility = View.VISIBLE;
            ErrorVisibility = View.INVISIBLE;
        } else if (curItem.Status.equals(AppEnums.StepResult.Failed)) {
            ErrorVisibility = View.VISIBLE;
            CheckVisibility = View.INVISIBLE;
        }

        Check.setVisibility(CheckVisibility);
        ErrorMark.setVisibility(ErrorVisibility);
        ProgressMessage.setText(curItem.PhaseName);

    } catch (Exception e) {
        System.out.println("Something went wrong.");
    }
    return view;
}

@Override
public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) {
    try {
        LayoutInflater inflater = (LayoutInflater) appContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.progress_list_item_children, null);

        TextView ProgressMessage = view.findViewById(R.id.ProgressMessage);
        ImageView Check = view.findViewById(R.id.CheckMark);
        ImageView ErrorMark = view.findViewById(R.id.ErrorMark);
        Step curItem = getChild(i, i1);

        int CheckVisibility = 0;
        int ErrorVisibility = 0;
        if (curItem.Status == AppEnums.StepResult.NotCompleted) {
            CheckVisibility = View.INVISIBLE;
            ErrorVisibility = View.INVISIBLE;
        } else {
            if (curItem.Status == AppEnums.StepResult.Completed) {
                CheckVisibility = View.VISIBLE;
                ErrorVisibility = View.INVISIBLE;
            } else if (curItem.Status == AppEnums.StepResult.Failed) {
                ErrorVisibility = View.VISIBLE;
                CheckVisibility = View.INVISIBLE;
            }
        }

        ProgressMessage.setText(curItem.StepName);

        Check.setVisibility(CheckVisibility);
        ErrorMark.setVisibility(ErrorVisibility);

    } catch (Exception e) {
        System.out.println("Something went wrong.");
    }
    return view;
}

@Override
public boolean isChildSelectable(int i, int i1) {
    return false;
}
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
tools:context=".MainActivity">

<TextView
    android:id="@+id/ProgressMessage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Progress Messages:"
    android:textColor="#F8F8F8"
    android:textSize="20sp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<Button
    android:id="@+id/bt_add_phase"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingStart="20dp"
    android:text="Add Phase"
    app:layout_constraintRight_toLeftOf="@id/bt_completed_step"
    app:layout_constraintTop_toTopOf="parent"
    tools:ignore="RtlSymmetry" />

<Button
    android:id="@+id/bt_completed_step"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingStart="20dp"
    android:text="Completed Step"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:ignore="RtlSymmetry" />

<ImageView
    android:id="@+id/ProgressErrorContainer"
    android:layout_width="50dp"
    android:layout_height="50dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/ProgressMessage" />

<ExpandableListView
    android:id="@+id/ProgressStepsContainer"
    android:layout_width="0dp"
    android:layout_height="267dp"
    android:background="#000033"
    android:fastScrollEnabled="false"
    android:verticalScrollbarPosition="left"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toStartOf="@+id/ProgressErrorContainer"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/ProgressMessage" />

</androidx.constraintlayout.widget.ConstraintLayout>

progress_list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="0dp">

<ImageView
    android:id="@+id/CheckMark"
    android:layout_width="50dp"
    android:layout_height="50dp"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:srcCompat="@android:drawable/checkbox_on_background" />

<ImageView
    android:id="@+id/ErrorMark"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:visibility="visible"
    app:layout_constraintStart_toStartOf="@+id/CheckMark"
    app:layout_constraintTop_toTopOf="parent"
    app:srcCompat="@android:drawable/ic_delete" />

<TextView
    android:id="@+id/ProgressMessage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:textAlignment="center"
    android:textColor="#F8F8F8"
    android:textSize="18sp"
    app:layout_constraintBottom_toBottomOf="@+id/CheckMark"
    app:layout_constraintStart_toEndOf="@+id/CheckMark"
    app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

progress_list_item_children.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:paddingStart="50dp"
android:layout_width="wrap_content"
android:layout_height="50dp">

<ImageView
    android:id="@+id/CheckMark"
    android:layout_width="50dp"
    android:layout_height="50dp"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:srcCompat="@android:drawable/checkbox_on_background" />

<ImageView
    android:id="@+id/ErrorMark"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:visibility="visible"
    app:layout_constraintStart_toStartOf="@+id/CheckMark"
    app:layout_constraintTop_toTopOf="parent"
    app:srcCompat="@android:drawable/ic_delete" />

<TextView
    android:id="@+id/ProgressMessage"
    android:layout_width="wrap_content"
    android:layout_height="50dp"
    android:gravity="center"
    android:textAlignment="center"
    android:textColor="#F8F8F8"
    android:textSize="18sp"
    app:layout_constraintBottom_toBottomOf="@+id/CheckMark"
    app:layout_constraintStart_toEndOf="@+id/CheckMark"
    app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

For the classes that related to your data structure, you can copy from your original project.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM