欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

转盘选项自定义

程序员文章站 2022-04-15 18:01:01
一、需求1.转盘自定义选项二、实现步骤1.先创建选项表TurntableOptionpackage com.example.meetyou.dbimport androidx.room.ColumnInfoimport androidx.room.Entityimport androidx.room.PrimaryKey@Entity(tableName = "TurntableOption")data class TurntableOption ( @PrimaryKey(...

一、需求
1.转盘自定义选项
2.展示
转盘选项自定义

二、实现步骤
1.先创建选项表
TurntableOption

package com.example.meetyou.db

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "TurntableOption")
data class TurntableOption (
    @PrimaryKey(autoGenerate = true)
    var tOptionId: Int?,
    @ColumnInfo(name = "option_name")
    var tOptionName: String?
)

2.操作表的接口
TurntableOptionDao

@Dao
interface TurntableOptionDao: BaseDao<TurntableOption> {
    //增加选项
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(element: TurntableOption)

    //查询所有选项
    @Query("select * from TurntableOption")
    fun getAll():MutableList<TurntableOption>

    //修改文字
    @Query("update TurntableOption set option_name = :name where tOptionId = :id")
    fun updateName(name:String ,id: Int)

    //删除选项
    @Query("delete from TurntableOption where tOptionId = :id")
    fun deleteOption(id: Int)
}

3.通过recyclerview显示选项内容
recyclerview_option.xml(recyclerview的item布局)

<?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="wrap_content"
    android:orientation="vertical">

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

        <TextView
            android:id="@+id/tv_option"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:padding="10dp"
            android:layout_gravity="center"
            android:background="@drawable/rectangle_circle_skin"
            android:text="选项内容" />

        <ImageView
            android:id="@+id/im_option_delete"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_gravity="center"
            android:layout_marginRight="10dp"
            android:layout_weight="5"
            android:scaleType="fitCenter"
            android:src="@drawable/ic_delete" />
    </LinearLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="5dp"
        android:background="@color/white"/>

</LinearLayout>

recyclerview所在活动的布局:一个recyclerview和一个FloatingActionButton
activity_edit_option.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rl_edit_option"
    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"
    android:padding="10dp"
    android:background="@color/white"
    tools:context=".ui.activity.EditOptionActivity">
    
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/option_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab_edit_option"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="20dp"
        android:clickable="true"
        app:borderWidth="0dp"
        app:elevation="10dp"
        app:fabSize="normal"
        app:pressedTranslationZ="25dp"
        app:rippleColor="@color/colorSkin"
        android:backgroundTint="@color/colorLightPink"
        android:src="@drawable/ic_add"/>
</RelativeLayout>

recyclerview适配器:点击textview控件会弹出一个修改选项内容的dialog,点击imageview控件删除选项
TurntableRecyclerAdapter

class TurntableRecyclerAdapter : RecyclerView.Adapter<TurntableRecyclerAdapter.ViewHolder>
    {
    private lateinit var wholeHolder: ViewHolder
    private var wholePosition : Int = 0
    private val optionDao = AppDataBase.instance.getTurntableOptionDao()
    private var list = mutableListOf<TurntableOption>()
    private var mContext: Context? = null
    private var mActivity: ViewGroup? = null
    private var activity: EditOptionActivity?= null

    companion object{
        private const val OPTION_NAME = "name"
    }
    constructor(activity:EditOptionActivity,list:MutableList<TurntableOption>){
        this.list = list
        this.activity = activity
    }
    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): TurntableRecyclerAdapter.ViewHolder {
        mActivity = parent
        mContext = parent.context
        val v = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_option,parent,false)
        return ViewHolder(v)
    }
    class ViewHolder(view: View): RecyclerView.ViewHolder(view) {
        var tvOption = view.findViewById(R.id.tv_option) as TextView
        var imDelete = view.findViewById(R.id.im_option_delete) as ImageView

    }
    override fun getItemCount(): Int {
        return list.size
    }
    override fun onBindViewHolder(holder: TurntableRecyclerAdapter.ViewHolder, position: Int) {
        wholeHolder = holder
        wholePosition = position
        val optionContext = list[position].tOptionName
        holder.tvOption.text = "第"+(position+1)+"项:"+optionContext
        holder.tvOption.setOnClickListener {
            val fragment:ModifyOptionDialogFragment =
                ModifyOptionDialogFragment.newInstance(position,optionContext.toString()) as ModifyOptionDialogFragment
                fragment.show(activity!!.supportFragmentManager,OPTION_NAME)
        }
        holder.imDelete.setOnClickListener{
            list = optionDao.getAll()
            if(list.size <= 2){
                ShowToast.showToast(this!!.mContext!!,"选项不能少于2个")
            }else{
                optionDao.deleteOption(list[position].tOptionId!!)
                list.removeAt(position)
                notifyDataSetChanged()
                for(i in 0 until list.size){
                    var a = list[i]
                    Timber.d("list2===========$i=====$a")
                }
            }
        }
    }
}

对话框用的是dialogfragment:首先,需要将点击的textview中的值传给dialogfragment,将值保存在dialogfragment的argument bundle中,这样dialogfragment便可以直接获取到这个值。所以在dialogfragment中添加静态方法newInstance(),然后在onViewCreated中,从argument获取值。
在点击“确定”后,需要修改选项内容,因为修改后要回到recyclerview所在的活动,这时候就需要刷新recyclerview中的数据,将dialogfragment中重新得到的list传给主活动中,并且刷新recyclerview。
还有,选项内容长度控制在15个字以内,所以,需要监听EditText的文字变化,这时候dialogfragment需要实现TextWatcher这个接口。具体监听,超过15个字后不能再输入文字了。
最后,我还重写了onResume方法,这是因为onViewCreated展现出来的视图太窄了,所以需要重新设置对话框的宽、高。

ModifyOptionDialogFragment

class ModifyOptionDialogFragment : DialogFragment(),TextWatcher {
    private val turntableOptionDao = AppDataBase.instance.getTurntableOptionDao()
    private var list = mutableListOf<TurntableOption>()
    companion object{
        fun newInstance(id:Int,name:String): Fragment{
            val modifyFragment : ModifyOptionDialogFragment =
                ModifyOptionDialogFragment()
            val bundle : Bundle = Bundle();
            bundle.putString("name",name)
            bundle.putInt("id",id)
            modifyFragment.arguments = bundle
            return modifyFragment
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return View.inflate(activity, R.layout.fragment_modify_option,null)
    }

    @SuppressLint("UseRequireInsteadOfGet")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val name = arguments!!.getString("name")
        val id = arguments!!.getInt("id")
        edit_option.setText(name)
        edit_option.addTextChangedListener(this)
        tv_modify_option_cancel.setOnClickListener{
            dismiss()
        }
        tv_modify_option_confirm.setOnClickListener{
            val modifyValue = edit_option.text.toString()
            Timber.d("==查看修改内容==$modifyValue===$id")
            list = turntableOptionDao.getAll()
            turntableOptionDao.updateName(modifyValue, list[id].tOptionId!!)
            list = turntableOptionDao.getAll()
            for (i in 0 until list.size){
                var a = list[i]
                Timber.Forest.d("==修改数据内容==$a")
            }
            val callback: OnSendMessage = activity as OnSendMessage
            callback.sendMessage(list)
            dismiss()
        }
    }

    interface OnSendMessage{
        fun sendMessage(list:MutableList<TurntableOption>)
    }

    override fun afterTextChanged(s: Editable?) {

    }

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

    }

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        var editable: Editable = edit_option.text
        val length = editable.length
        val maxLength = 15

        if(length > maxLength){
            activity?.let { ShowToast.showToast(it,"输入字数超过15个字") }
            var selEndIndex: Int = Selection.getSelectionEnd(editable)
            val str: String = editable.toString()
            val newStr: String = str.substring(0,maxLength)
            edit_option.setText(newStr)
            editable = edit_option.text

            //新字符串长度
            val newLength = editable.length
            //旧光标位置超过字符串长度
            if(selEndIndex == newLength){
                selEndIndex = editable.length
            }
            //设置新光标所在的位置
            Selection.setSelection(editable,selEndIndex)
        }

    }

    override fun onResume() {
        val params = dialog?.window?.attributes
        if (params != null) {
            params.width = WindowManager.LayoutParams.MATCH_PARENT
        };
        if (params != null) {
            params.height = WindowManager.LayoutParams.WRAP_CONTENT
        };
        dialog?.window?.attributes = params;
        super.onResume();
    }
}

这是dialogfragment的布局
fragment_modify_option.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">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/modify_option"
        android:textSize="20sp"
        android:padding="15dp"
        android:textColor="@color/black"/>
    <EditText
        android:id="@+id/edit_option"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        android:text="@string/modify_option"
        android:background="@drawable/rectangle_circle_skin"
        android:paddingLeft="7dp"
        android:paddingRight="7dp"
        android:maxLength="15"
        />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="15dp"
        android:layout_marginRight="20dp"
        android:layout_marginBottom="15dp">
        <TextView
            android:id="@+id/tv_modify_option_cancel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="right"
            android:text="@string/cancel"
            android:textSize="15sp"/>
        <TextView
            android:id="@+id/tv_modify_option_confirm"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:gravity="right"
            android:text="@string/confirm"
            android:textSize="15sp"/>
    </LinearLayout>

</LinearLayout>

接下来就是在活动中用到刚刚写的适配器了,这里list用来放从数据库中获取的所有数据,数据库每次有修改后,list每次都重新获取数据,然后再写进recyclerview适配器中参数里面,刷新recyclerview.

class EditOptionActivity : SimpleActivity(), ModifyOptionDialogFragment.OnSendMessage {
    private val turntableOptionDao = AppDataBase.instance.getTurntableOptionDao()
    private var list = mutableListOf<TurntableOption>()
    private lateinit var mAdapter: TurntableRecyclerAdapter
    private lateinit var mTurntableAdapter: TurntableAdapter
    private var context :EditOptionActivity = this

    override fun getLayoutId(): Int {
       return  R.layout.activity_edit_option
    }

    override fun initData(savedInstanceState: Bundle?) {
        //如果数据库里没有东西,加入新的数据
        if(turntableOptionDao.getAll().size == 0){
            initList()
        }
        //获取数据库中的数据
        list= turntableOptionDao.getAll()
        setAdapter()
        //悬浮按钮点击事件,新增转盘选项
        fab_edit_option.setOnClickListener{
            list = turntableOptionDao.getAll()
            if(list.size > 15){
                ShowToast.showToast(this,"转盘选项不能超过15个")
            }else{
                turntableOptionDao.insert(TurntableOption(null," "))
                list = turntableOptionDao.getAll()
                for (i in 0 until list.size){
                    var a = list[i]
                    Timber.d("list3==$i====$a")
                }
                setAdapter()
            }
        }
    }
    private fun initList() {
        for(i in 0 until 10){
            turntableOptionDao.insert(TurntableOption(null,"第$i"+"个"))
        }
    }
    private fun setAdapter(){
        mAdapter = TurntableRecyclerAdapter(context,list)
        option_recyclerview.adapter = mAdapter
        option_recyclerview.layoutManager = LinearLayoutManager(this)
    }
    override fun sendMessage(list: MutableList<TurntableOption>) {
        this.list = list
        setAdapter()
    }
}

4.recyclerview的相关内容已经设置完,表的增删改查也实现了,现在需要根据获取选项表的内容画转盘,也就是画椭圆
需要注意的是:圆是360度,当圆被分为7份时,会产生余数,所以不能用int来当除数,除数要是float类型,这样所得的数就是float类型了。

private void initArc(Canvas canvas) {

    optionDao = AppDataBase.Companion.getInstance().getTurntableOptionDao();

    contents = optionDao.getAll().toArray(new TurntableOption[0]);

    float b = contents.length;
    float a = 360/b;
    int j = 0;
    Timber.d("浮点数=="+a+"====");

    for(int i = 0 ;i<contents.length;i++){
        Timber.d(contents[i]+"====5555555555");
    }

    for(int i=0;i<contents.length;i++){

        if(i>=6){
            j = i - 5;
            if(j>= 6){
               j = j - 5;
            }
            mPaint.setColor(colors[j]);
        }else{
            mPaint.setColor(colors[i]);
        }

        canvas.drawArc(rectF,(i-1)*a+a,a,true,mPaint);

    }

    for(int i=0;i<contents.length;i++){

        mPaint.setColor(Color.BLACK);

        Path path = new Path();

        path.addArc(rectF,(i-1)*a+a,a);

        canvas.drawTextOnPath(contents[i].getTOptionName(),path,a,a,mPaint);

    }

}

本文地址:https://blog.csdn.net/weixin_41650019/article/details/108857946