当前位置: 移动技术网 > 移动技术>移动开发>Android > 转盘选项自定义

转盘选项自定义

2020年09月28日  | 移动技术网移动技术  | 我要评论
一、需求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

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网