转盘选项自定义
一、需求
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