Android Studio: การเรียก Canvas หลายอันใน ScrollView เพื่อแสดง 1 ภาพวาด (canvas) หลังจากนั้นอีกอัน

ฉันกำลังเขียนโค้ดสำหรับโครงการของโรงเรียนที่ต้องโหลดไฟล์ข้อมูล (ไฟล์ CSV ไฟล์ข้อความ ฯลฯ) และจากข้อมูลที่ได้รับ แอปจะส่งข้อมูลไปยังมุมมองการวาดที่กำหนดเอง และวิธีการ onDraw จะวาด /plot กราฟตามข้อมูล

เป้าหมายของฉันคือให้แอปแสดงกราฟ 2 อันต่อกัน (ซ้อนกัน) โหลดข้อมูลชุดแรกแล้ววาดกราฟชุดที่ 1 ข้อมูลที่โหลดจะถูกนำมาใช้สำหรับการคำนวณที่แตกต่างกันด้วยวิธีการอื่น มุมมองการวาดแบบกำหนดเองจะถูกเรียกอีกครั้งพร้อมกับข้อมูลใหม่เพื่อวาดกราฟที่ 2

เมื่อฉันเรียกใช้แอป แผนภูมิทั้งสองจะถูกวาด แต่เนื่องจากแกน x และ y' ของกราฟถูกเขียนโค้ดให้วาดที่พิกเซลคงที่บางพิกเซล กราฟที่ 2 จะถูกวาดทับกราฟแรก ดังนั้นจึงมองเห็นเฉพาะกราฟที่ 2 เท่านั้น

มีวิธีใดบ้างที่ฉันสามารถวาดกราฟ 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) {
        ......
    }

อัปเดต

กิจกรรม_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>

person Jaclyn    schedule 15.07.2020    source แหล่งที่มา
comment
โพสต์เค้าโครง XML ของคุณ ปัญหาอาจจะอยู่ที่นั่น   -  person Jenea Vranceanu    schedule 15.07.2020
comment
@JeneaVranceanu ฉันได้แก้ไขโพสต์และเพิ่มเค้าโครง XML ของฉันแล้ว   -  person Jaclyn    schedule 17.07.2020


คำตอบ (1)


คุณไม่สามารถให้ความสูงของสองมุมมองตรงกับความสูงของพาเรนต์ภายใน LinearLayout ที่มีการวางแนวในแนวตั้ง เป็นไปไม่ได้เนื่องจากความสูงของมุมมองเหล่านี้จะต้องเท่ากับความสูงของพาเรนต์ แต่ในขณะเดียวกัน จะต้องเรียงลำดับกันส่งผลให้ความสูงของพาเรนต์เป็นสองเท่า

หากคุณจินตนาการถึงความสูงของผู้ปกครองเป็น 10dp ดังนั้น แต่ละมุมมอง Graph จะต้องเป็น 10dp เช่นกัน ซึ่งหมายความว่าความสูงของผู้ปกครองจะต้องเป็น 20dp ไม่ใช่ 10dp นั่นจะเป็นการวนซ้ำตลอดไป ดังนั้น Android จึงทำสิ่งง่ายๆ: มุมมองที่อยู่ต่ำกว่ามุมมองลูกแรกที่มี android:layout_height="match_parent" จะมีความสูง 0dp หรือหากความสูงได้รับการแก้ไข มุมมองเหล่านั้นจะถูกดึงออกไปนอกเค้าโครงและจะไม่สามารถมองเห็นได้

ตัวอย่าง

ตัวอย่างปัญหา

ภาพหน้าจอจากแท็บการออกแบบของเครื่องมือแก้ไขเค้าโครงใน Android Studio IDE

ที่นี่คุณสามารถดู:

  • มุมมองสีแดงเป็นรูปแบบเชิงเส้นของพาเรนต์
  • มุมมองสีม่วงเป็นลูกคนแรกที่มีความสูงตรงกับความสูงของผู้ปกครอง
  • มุมมองเค้าร่างที่วาดนอกโครงร่างเนื่องจากถูกผลักออกโดยลูกคนแรกที่มี 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. ออกแบบเค้าโครงของคุณใหม่ ใช้ RelativeLayout หรือ ConstraintLayout เพื่อวางตำแหน่งมุมมองให้สัมพันธ์กัน เพื่อให้มองเห็นได้เสมอ ไม่ว่าขนาดหน้าจอ อัตราส่วน และความหนาแน่นจะเป็นอย่างไร

ตัวอย่างวิธีการแก้ไข

โดยส่วนตัวแล้วฉันชอบ 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>

ผลลัพธ์คือ (ฉันใช้สองปุ่มแทนมุมมองกราฟ):

ตัวอย่างวิธีแก้ปัญหา

คำแนะนำ:

  • หากคุณต้องการใช้ ScrollView คุณจะต้องตั้งค่าความสูงคงที่หรือกำหนดความสูง ณ รันไทม์
  • กำจัด private final int zero = 700; // mark the 0 line of graph at 700 pixels อย่าใช้ค่าพิกเซลโดยตรงเพราะจะทำให้เกิดข้อผิดพลาดกับ UI ได้ มันจะเป็นกรณีของการทำงานบนโทรศัพท์ของฉันไม่ทำงานอื่นๆ ใช้ความสูงของมุมมองเป็นเส้น 0
person Jenea Vranceanu    schedule 17.07.2020