提问者:小点点

Android Studio:在ScrollView中调用多个画布以显示一个接一个的绘图(画布)


我正在为一个学校项目编写代码,其中必须加载数据文件(CSV文件,文本文件等),从获得的数据中,应用程序将数据传递给自定义绘制视图,onDraw方法将根据数据绘制/绘制图形。

我的目标是应用程序显示2张图,一个接一个(堆叠)。加载第一组数据并绘制第一张图。然后将加载的数据用于不同方法的不同计算。然后使用新数据再次调用自定义绘制视图以绘制第二张图。

当我运行应用程序时,两个图表都被绘制,但由于图形的x轴和y轴被编码为以某些固定像素绘制,因此第二个图形被绘制在第一个图形上,因此只有第二个图形可见。

有什么方法可以绘制这2个图形,使其不重叠,而是显示在ScrollView中堆叠?

我的代码如下所示,但我已经摆脱了我认为不太重要的计算。任何帮助和建议都将不胜感激!

MainActivity.java:

    @Override
    protected void onActivityResult(......) {
        super.onActivityResult(......);
        switch (1) {
            case 1:
                Graph graph = this.findViewById(R.id.graph1);
                graph.setData(data); // the loaded data is passed to Graph View
                Graph drawGraph2 = this.findViewById(R.id.graph2);
                graph2.setData(this.newCalculate(data));
                break;
        }
    }

Graph.java

    public  class Graph extends View {
    private Paint mPaint = new Paint();
    private final int zero = 700; // mark the 0 line of graph at 700 pixels


    public void setData(data){   
        ......
    }

    public Graph(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);

    }

    @Override
    protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(widthSize, heightSize);
    }

        @Override
        protected void onDraw(Canvas canvas) { 
        super.onDraw(canvas);

        plotUnit(canvas);    // plot points on graph

        axisLabel(canvas);    // label axis

        axisLine(canvas);     // draw axis

        xyAxisMarker(canvas);    // mark axis
    }

    private void plotUnit(Canvas canvas) {
        ......
        // Due to data having negative values, the graph is inverted and the 0 starts
        // of the graph is defined at 700 pixels (private final int zero)
    }

    private void axisLabel(Canvas canvas) {
        ......
    }

    private void axisLine(Canvas canvas, int inset) {
        ......
    }

    private void xyAxisMarker(Canvas canvas) {
        ......
    }

activity_main. xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <Button
                    android:id="@+id/loadbutton"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="Open Data File" />

                <firstapp.drawtwograph.Graph
                    android:id="@+id/graph1"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent" />

                <firstapp.drawtwograph.Graph
                    android:id="@+id/graph2"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent" />
            </LinearLayout>
        </ScrollView>
    </LinearLayout>

共1个答案

匿名用户

垂直方向的LinearLayout中不能有两个视图的高度与父级高度匹配。这是不可能的,因为这些视图的高度必须等于父级高度,但同时,它们必须一个接一个地排序,从而导致父级高度的两倍。

如果您将父级的高度想象为10dp,那么每个Graph视图也必须是10dp,这意味着父级的高度必须是20dp,而不是10dp。这将永远循环,因此Android做了一件简单的事情:低于android的第一个子视图的视图:layout_height="match_parent"将具有高度0dp,或者如果它们的高度是固定的,它们将被绘制在布局之外并且不可见。

Android StudioIDE中布局编辑器的设计选项卡的屏幕截图。

在这里你可以看到:

  • 红色视图作为父线性布局;
  • 紫色视图作为高度与父级高度匹配的第一个子级;
  • 在布局之外绘制的概述视图,因为它是由android的第一个孩子推出的:layout_height="match_parent"
  • 还有一个视图被压缩到0高度,因此不可见。您可以在XML代码中看到它。

此示例的XML代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="100dp"
    android:background="@android:color/holo_red_light">

    <LinearLayout
        android:background="@color/colorPrimary"
        android:layout_width="60dp"
        android:layout_height="match_parent" <!-- this view's height is a problem -->
        android:orientation="vertical"/>

    <LinearLayout
        android:background="@android:color/holo_green_dark"
        android:layout_width="120dp"
        android:layout_height="match_parent" <!-- height is not fixed, then it will be 0 -->
        android:orientation="vertical"/>

    <LinearLayout
        android:background="@android:color/holo_green_light"
        android:layout_width="120dp"
        android:layout_height="40dp" <!-- height is fixed, it is outlined outside of a layout -->
        android:orientation="vertical"/>

</LinearLayout>
  1. 设置固定高度。作为测试,尝试定义固定高度,例如100dp
  2. 重新设计您的布局。使用RelativeLayoutConstraintLayout将视图相对于彼此定位,以便无论屏幕大小、比例、密度如何,它们始终可见。

我个人更喜欢ConstraintLayout,因为它在定位和适应方面非常强大。

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/loadbutton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Open Data File"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <firstapp.drawtwograph.Graph
        android:id="@+id/graph1"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/graph2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/loadbutton" />

    <firstapp.drawtwograph.Graph
        android:id="@+id/graph2"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/graph1" />
</androidx.constraintlayout.widget.ConstraintLayout>

结果是(我使用了两个按钮而不是Graph视图):

提示:

  • 如果您想使用ScrollView,则需要在运行时设置固定高度或定义高度。
  • 摆脱私有最终整数0=700;//将图的0行标记为700像素。不要直接使用像素值,因为这会导致容易出错的UI。这将是“在我的手机上工作,在其他手机上不工作”的情况。使用视图的高度作为0线。