Android的Kotlin尝试之记账APP4

前言:

现在我们已经做好了点击饼图后该区域旋转至正下方,接下来的目标是将饼图点击后再在下方出现一个TextView显示详情.这就需要考虑到饼图不能再占据屏幕正中,而是要靠于上方,腾出一些空间,在下方显示详情文本,以防出现适配问题.

将饼图移到界面上方

这里可以采取两个方案来将实现该目的:

  • 直接修改PieChart类或其父类的onMeasure方法(此方法只适用于从GitHub下载的源码添加到工程的方式)
  • 创建一个类继承自PieChart类,重写onMeasure方法(通用)
    这里作为一名强迫症患者,并且因为采用的是Gradle依赖添加方式,就自己创建了一个继承自PieChart的类,这里需要改动两个地方,一个在xml界面文件中,需要将com.github.mikephil.charting.charts.PieChart换成自己包里的PieChart,另一个是PieFragment.kt中:
    源码:
/*MPieChart.kt*/
import android.content.Context
import android.util.AttributeSet
import android.view.View
import com.github.mikephil.charting.charts.PieChart
import com.github.mikephil.charting.utils.Utils


/**
 * Created by Administrator on 2018/2/12.
 */

class MPieChart : PieChart {

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val size = Utils.convertDpToPixel(MeasureSpec.getSize(widthMeasureSpec).toFloat()).toInt()//这里size定死50f不合理,改一下
        setMeasuredDimension(
                Math.max(suggestedMinimumWidth,
                        View.resolveSize(size,
                                widthMeasureSpec)),
                Math.max(suggestedMinimumHeight,
                        View.resolveSize(size,
                                widthMeasureSpec)))//这里将heightMeasureSpec改成widthMeasureSpec
    }
}

这里涉及到了Kotlin的构造方法知识,该类没有主构造方法,使用了constructor关键字声明了三个从构造方法,修改过后的效果图如下:
这里写图片描述

在下方添加TextView

依赖:

/*百分比布局*/
compile"com.android.support:percent:27.0.2"

这里的版本号根据'com.android.support:appcompat-v7:27.0.2'版本号设置

源码:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.view.ViewPager
        android:id="@+id/vpMain"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/black">

        <android.support.v4.view.PagerTabStrip
            android:id="@+id/chartTab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </android.support.v4.view.ViewPager>

</android.support.constraint.ConstraintLayout>

这里增加了个android.support.v4.view.PagerTabStrip,只需在适配器里多重写一个getPageTitle方法,设置标题

<!--fragment_pie_chart.xml-->
<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentRelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <com.example.administrator.spendingnote.MPieChart
        android:id="@+id/pieChart"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        app:layout_widthPercent="80%" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_below="@id/pieChart"
        android:layout_marginTop="10dp"
        android:orientation="vertical"
        app:layout_widthPercent="80%">

        <View
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_gravity="center_horizontal"
            android:background="@drawable/triangle" />

        <TextView
            android:id="@+id/tv_des"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_des"
            android:gravity="center" />
    </LinearLayout>

</android.support.percent.PercentRelativeLayout>

这里对VIewTextView的背景做了设置又一个三角图形的View与圆角矩形的TextView组合成聊天气泡图形:

<!--tv_des.xml-->
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="30dp"/>
    <solid android:color="@android:color/white"/>
</shape>
<!--triangle.xml-->
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="45"
    android:toDegrees="45"
    android:pivotX="-40%"
    android:pivotY="87">
    <shape android:shape="rectangle" >
        <solid android:color="@android:color/white"/>
    </shape>
</rotate>
/*这里只改动了此方法,增添了详情显示*/
override fun onValueSelected(e: Entry?, h: Highlight?) {//当区域被选取的动作实现,这里的功能是区域被选取时,被选取区域旋转至正下方
                    val ratio = 360 / mChart.data.yValueSum//比例系数,每单位值所占度数
                    val index = (h?.x ?: 0f).toInt()
                    val angleByIndex = { i: Int -> mChart.data.dataSet.getEntryForIndex(i).value }//根据编号获得区域的值
                    var angle = 90f//初始旋转90度,加上默认的270度正好回原点
                    for (i in index downTo 0) {
                        angle -= angleByIndex(i) * ratio//旋转度数减去所选区域与前编号区域的度数
                    }
                    angle += angleByIndex(index) * ratio / 2//回退本区域一半度数,正好指向正下方
                    isRotationEnabled = true
                    rotationAngle = angle
                    isRotationEnabled = false
                    //以下为详情显示
                    val des="${data.dataSet.getEntryForIndex(index).label}花费${h?.y?:0}元,占比${String.format("%.0f", angleByIndex(index)/data.yValueSum*100)}%"
                    tvDes.text=des
                }

这里遇到个问题,已经改正,总结一下:

由于是参考的别的教程,而自己对Fragment和ViewPager的认识不足,导致我实现了前面所有功能后在这里却遇到个很棘手的问题,TextView控件无法显示!
问题来自于多处的巧合,花了不少功夫才摸清问题,这是错误的代码:

<!--activity_main.xml-->
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.view.ViewPager
        android:id="@+id/vpMain"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/background_dark">

        <android.support.v4.view.PagerTabStrip
            android:id="@+id/chartTab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@android:color/background_light"/>

    </android.support.v4.view.ViewPager>

</android.support.constraint.ConstraintLayout>
/*PieFragment.kt*/
private fun setData() {
        val entries = ArrayList<PieEntry>()
        mData.obj.mapTo(entries) { PieEntry(it.value.toFloat(), it.title) }
        val mPieDataSet = PieDataSet(entries, "MoneySpending")
        mPieDataSet.colors = listOf(Color.rgb(216, 77, 219), Color.rgb(183, 56, 63), Color.rgb(247, 85, 47))
        val mPieData = PieData(mPieDataSet)
        mChart.data = mPieData
        tvDes.text=mData.date//新增,设置默认显示为当前账单时间
    }
/*PieFragment.kt*/
 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        mView = inflater.inflate(R.layout.fragment_pie_chart, container, false)
        mChart = mView.find(R.id.pieChart)
        tvDes=mView.find(R.id.tv_des)
        initView()
        return mChart 
    }

解析一下:
<include layout="@layout/fragment_pie_chart"/>把fragment_pie_chart.xml引用到了activity_main.xml中,然后在Kotlin代码中又加载fragment_pie_chart.xml布局到Fragment

  • return mChart时是将mChart控件覆盖了Fragment,填充在ViewPager中,所以看见的效果看起来是正常的,但是这样就只能显示一个控件,所以这必然是错误的用法.
  • 而我在没改动布局文件的情况下尝试使用return mView这个正确用法时会不显示加载的fragment_pie_chart.xml布局.

原因在于之前把此布局已经引用在了ViewPager中,这里又加载此布局,引起了这种晦涩的问题.,这个问题也印证了在当return mChart之前不对mChart做解除父视图引用时会抛异常java.lang.IllegalStateException The specified child already has a parent. You must call removeView().


效果图:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_37258787/article/details/79316995