Recycling View Android Plot becomes gray after Scr

2019-08-26 12:08发布

问题:

I got the following Problem.

When Including Android-XYPlot into Recycle-View, the Plots are not displayed after Scrolling Elements out of the Screen. It seems to me if Androidplot needs to be reinflated, but that's not really effective.

Links I have already found:

XYPlot (AndroidPlot library) in ScrollView does not appear

Is there any better Solution:

Here is my Code:

Activity:

package at.fs.recycleviewerdemo;

import android.graphics.Color;
import android.graphics.Paint;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import com.androidplot.ui.SizeMode;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.StepMode;
import com.androidplot.xy.XYGraphWidget;

import java.text.DecimalFormat;

public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;
    private String[] myDataset;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = (RecyclerView) findViewById(R.id.RecyListItems);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        // specify an adapter (see also next example)
        myDataset  = new String[100];
        fillDataSet(myDataset);
        mAdapter = new MyAdapter(this,myDataset);
        mRecyclerView.setAdapter(mAdapter);
        myDataset[9]="A";
        myDataset[99]="64";

    }
    private void fillDataSet(String[] dataset){
        if(dataset==null) return;
        for(int l=0;l<dataset.length;l++){
            dataset[l]=""+(l+1);
        }
    }

}

MyAdapter:

package at.fs.recycleviewerdemo;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.androidplot.ui.SizeMetric;
import com.androidplot.ui.SizeMode;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.StepMode;
import com.androidplot.xy.XYGraphWidget;
import com.androidplot.xy.XYPlot;

import org.w3c.dom.Text;

import java.text.DecimalFormat;
import java.util.Date;

/**
 * Author User
 * Date:25.01.2018
 * Class: ${CLASS}
 * Description:
 */

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private String[] mDataset;
    private Date[] mDateSet;
    private double[] sample;
    Context parentContext;

    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    public static class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public View mView;
        public TextView txtDateTime;
        public TextView txtResult;
        public TextView txtEntryInfo;

        private XYPlot mPlot;
        private SimpleXYSeries sPulsSeries;

        public ViewHolder(View v) {
            super(v);
            mView = v;
            txtDateTime = (TextView) mView.findViewById(R.id.txtDateTime);
            txtResult = (TextView) mView.findViewById(R.id.txtResult);
            txtEntryInfo = (TextView) mView.findViewById(R.id.txtEntryInfo);
            mPlot = (XYPlot) mView.findViewById(R.id.mPlot);
            //addSampleData();
            //mPlot.redraw();
            Log.d(this.getClass().getSimpleName(),"ViewHolder(View v)");
        }
        private void InitDiagramm(){
            SetHRPlot_Boundaries();
            SetHRPlot_Grid();
            setHRPlot_Texts();

            //Set Line Format
            mPlot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new DecimalFormat("##"));
            mPlot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).setFormat(new DecimalFormat("##"));

        }
        private void SetHRPlot_Boundaries(){
            //Set Y Boundaries
            mPlot.setRangeBoundaries(40,120, BoundaryMode.FIXED);
            mPlot.setRangeStepMode(StepMode.INCREMENT_BY_VAL);
            mPlot.setRangeStepValue(20.0);
            //Set X Boundaries
            mPlot.setDomainStepMode(StepMode.INCREMENT_BY_VAL);
            mPlot.setDomainStepValue(10);
            mPlot.setDomainBoundaries(0,60000,BoundaryMode.FIXED);

        }
        private void SetHRPlot_Grid(){
            //Set horizontal Grid
            //Set Grid Lines
            mPlot.getGraph().getDomainGridLinePaint().setColor(Color.rgb(255,255,255));
            //Set Archor Line
            mPlot.getGraph().getDomainOriginLinePaint().setColor(Color.rgb(0,110,104));
            mPlot.getGraph().getDomainOriginLinePaint().setStrokeWidth(10);
            //Set vertical Grid
            //Set Grid Lines
            mPlot.getGraph().getRangeGridLinePaint().setColor(Color.rgb(192,192,192));
            //Set Grid Borders
            mPlot.getGraph().getRangeOriginLinePaint().setColor(Color.rgb(0,110,104));
            mPlot.getGraph().getRangeOriginLinePaint().setStrokeWidth(5);
            mPlot.getLegend().setVisible(false);


            mPlot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new DecimalFormat("##"));
            mPlot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).setFormat(new DecimalFormat("##"));

        }
        private void setHRPlot_Texts(){
            mPlot.getDomainTitle().setWidth(mPlot.getWidth(), SizeMode.FILL);
            mPlot.getDomainTitle().getLabelPaint().setTextAlign(Paint.Align.CENTER);
            mPlot.getDomainTitle().getLabelPaint().setColor(Color.BLACK);
            mPlot.getRangeTitle().getLabelPaint().setColor(Color.BLACK);
            mPlot.getDomainTitle().setVisible(false);
            mPlot.getTitle().setVisible(false);
            mPlot.getRangeTitle().setVisible(false);
            mPlot.getRangeTitle().setHeight(0);
            mPlot.getDomainTitle().setHeight(0);
        }
        private void addSampleData(){
            LineAndPointFormatter formatter1 = new LineAndPointFormatter(
                    Color.rgb(153, 102, 204), null, null, null);
            formatter1.getLinePaint().setStrokeJoin(Paint.Join.ROUND);
            formatter1.getLinePaint().setStrokeWidth(5);
            sPulsSeries = new SimpleXYSeries("Puls");
            mPlot.addSeries(formatter1,sPulsSeries);
            for(int l=0;l<1200;l+=1) {
                sPulsSeries.addFirst(l * 50, 70 + 30 * Math.sin(l*Math.PI/180));
            }
            mPlot.redraw();
        }
    }

    // Provide a suitable constructor (depends on the kind of dataset)
    public MyAdapter(Context context,String[] myDataset) {
        mDataset = myDataset;
        parentContext=context;
        //mDateSet = mDates;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {

        // create a new view
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.my_text_view, parent, false);
        // set the view's size, margins, paddings and layout parameters
        //...
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        holder.InitDiagramm();
        holder.txtEntryInfo.setText(mDataset[position]);
        //holder.InitDiagramm();
        holder.mPlot.clear();
        Log.d(this.getClass().getSimpleName(),"onBindViewHolder():"+mDataset[position]);
        holder.addSampleData();
        holder.mPlot.redraw();
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDataset.length;
    }

}

Activity Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context="at.fs.recycleviewerdemo.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.01">
        <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:text="TextView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        tools:layout_editor_absoluteY="0dp" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/RecyListItems"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"/>
    </LinearLayout>
</LinearLayout>

CardView Adapter:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    xmlns:ap="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:background="@drawable/my_custom_background">
    <!-- A CardView that contains a TextView -->
    <android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_gravity="center"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    card_view:cardCornerRadius="4dp">
        <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
            <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
                <TextView
                android:id="@+id/txtDateTime"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="match_parent"
                android:text="20.Aug.2018"/>
                <TextView
                android:id="@+id/txtResult"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="match_parent"
                android:text="98 %"/>
            </LinearLayout>
            <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="200dp">

                <com.androidplot.xy.XYPlot
                android:id="@+id/mPlot"
                style="@style/APDefacto.Light"
                androidplot.renderMode="use_background_thread"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:visibility="visible"
                ap:lineLabels="left"
                android:minHeight="100dp"/>
            </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/txtEntryInfo"
                android:text="Time (TYPE) Quality "
                android:textAlignment="textEnd"/>
        </LinearLayout>
    </LinearLayout>
    </android.support.v7.widget.CardView>
    </LinearLayout>

Some Pictures to describe the situation:

Thanks for Help

回答1:

It looks like you're doing some stuff in the constructor of your ViewHolder that you probably shouldnt. In particular:

InitDiagramm();
addSampleData();
mPlot.redraw();

RecyclerView only contains a few View instances that are dynamically bound to your model data as the user scrolls, which means that you need to set the model data etc. every time the view is bound. This means that addSampleData and plot.Redraw should be done in onBindView.

You have the logic that actually adds the series data mixed between InitDiagramm and addSampleData. I'd suggest refactoring that a bit so that your plot style setup is separate from the code that actually sets data on the plot. At the very least, the addSeries call in InitDiagram should happen every bind, after your invocation of plot.clear but before your invocation of plot.redraw.



回答2:

The Problem was that I used the background Thread, after removing the Problem was solved

Before:

<com.androidplot.xy.XYPlot
                android:id="@+id/mPlot"
                style="@style/APDefacto.Light"
                androidplot.renderMode="use_background_thread"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:visibility="visible"
                ap:lineLabels="left"
                android:minHeight="100dp"/>

After:

<com.androidplot.xy.XYPlot
                android:id="@+id/mPlot"
                style="@style/APDefacto.Light"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:visibility="visible"
                ap:lineLabels="left"
                android:minHeight="100dp"/>