如何在BroadcastReceiver.onReceive中设置RecyclerView.ViewHolder的颜色?

时间:2017-10-17 01:40:43

标签: android bluetooth broadcastreceiver kotlin

我正在创建一个扫描并配对蓝牙设备的应用。我正在RecyclerView中显示设备,并通过为该设备着色ViewHolder来指示绑定状态。我的问题是ViewHolder的颜色只有在再次扫描设备后才会更改,我希望它立即更新配对或取消配对的颜色。我试图通过使用广播接收器来做到这一点,但我无法获得对正确的ViewHolder的引用。我怎么能实现这个目标?我将下面的代码包含在我的RecyclerView.Adapter和包含广播接收器的BluetoothUtils文件中。提前致谢。我的适配器:

getAllUsers

和我的BluetoothUtils:

class DeviceAdapter(val mContext : Context) : RecyclerView.Adapter<DeviceAdapter.DeviceHolder>() {

companion object {
    val TAG = "Device Adapter"

    fun DeviceHolder.setColor(bonded: Boolean):Unit{
        val background = if (bonded)Color.CYAN else Color.TRANSPARENT
        this.itemView.setBackgroundColor(background)
    }

}

val mDevices = ArrayList<BluetoothDevice>()

fun updateItems(list: ArrayList<BluetoothDevice>) {
    mDevices.clear()
    mDevices.addAll(list)
    Log.d(TAG, "updating items : $mDevices")
    notifyDataSetChanged()
}

fun ViewGroup.inflate(@LayoutRes res: Int, attachToRoot: Boolean = false): View {
    return LayoutInflater.from(mContext).inflate(res, this, attachToRoot)
}

override fun onBindViewHolder(holder: DeviceHolder, position: Int) {
    Log.d(TAG, "onBindViewHolder called!")
    holder.bindItems(mDevices.get(position))
    if (mDevices.get(position).bondState==BluetoothDevice.BOND_BONDED) {
        holder.itemView.setBackgroundColor(CYAN)
    } else {
        holder.itemView.setBackgroundColor(Color.TRANSPARENT)
    }
}

override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): DeviceAdapter.DeviceHolder {
    Log.d(TAG, "onCreateViewHolder called!")
    val v = parent!!.inflate(R.layout.device_item, false)
    return DeviceHolder(v)
}

override fun getItemCount(): Int {
    return mDevices.size
}

inner class DeviceHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

    val nameView = itemView.findViewById(R.id.nameView) as TextView
    val addrView = itemView.findViewById(R.id.addressView) as TextView
    var dialog: AlertDialog? = null;

    fun bindItems(btDevice: BluetoothDevice) {
        Log.d(TAG, "holder created!")
        nameView.text = btDevice.name ?: "Unknown"
        addrView.text = btDevice.address
        itemView.setOnClickListener {
            dialog = AlertDialog.Builder(it.context)
                    .setTitle("Options")
                    .setView(R.layout.options_dialog_layout)
                    .setNegativeButton("Cancel", DialogInterface.OnClickListener { _, which -> })
                    .create()
            dialog!!.show()
            val ops = listOf(
                    dialog!!.findViewById(R.id.statOp),
                    dialog!!.findViewById(R.id.pairOp),
                    dialog!!.findViewById(R.id.connectOp),
                    dialog!!.findViewById(R.id.sendOp),
                    dialog!!.findViewById(R.id.unPairOp)
            )
            ops.forEach { it.setOnClickListener {
                Toast.makeText(it.context, it.id.toString(), Toast.LENGTH_SHORT).show()
                when(it.id){
                    R.id.statOp -> {}
                    R.id.connectOp -> {
                        Log.d(TAG, "connectOp reached")
                        BluetoothReflection.connectDevice(btDevice)
                        dialog!!.dismiss()
                    }// BluetoothUtils.connect(BluetoothAdapter.getDefaultAdapter(), btDevice)
                    R.id.pairOp -> {
                        Log.d(TAG, "pairOp reached")
                        BluetoothUtils.startPair(BluetoothAdapter.getDefaultAdapter(), btDevice)
                        if (btDevice.bondState==BluetoothDevice.BOND_BONDED){
                            this@DeviceHolder.itemView.setBackgroundColor(CYAN) //doesn't work
                        }
                        Log.d(TAG, "start pair complete")
                        dialog!!.dismiss()
                    }//
                    R.id.unPairOp -> {//no executable code found here
                        Log.d(TAG, "unPairOp reached")
                        BluetoothUtils.unPair(btDevice)
                        if (btDevice.bondState==BluetoothDevice.BOND_NONE){
                            this@DeviceHolder.itemView.setBackgroundColor(Color.TRANSPARENT) //doesn't work
                        }
                        Log.d(TAG, "unpair complete")
                        dialog!!.dismiss()
                    }
                    R.id.sendOp -> {}
                }
            } }
        }

    }
}
}

2 个答案:

答案 0 :(得分:1)

booleanint添加到BluetoothDevice模型以管理视图。

例如,

BluetoothDevice:添加了isOn州。 (对不起,这是Java)

class BluetoothDevice {
    boolean isOn;

    public boolean isOn() {
        return isOn;
    }

    public void setOn(boolean isOn) {
        this.isOn = isOn;
    }
}

DeviceHolder:更改了视图的颜色

fun bindItems(btDevice: BluetoothDevice) {
   stateView.textColor = btDevice.isOn() ? Color.RED : Color.GREEN
}

DeviceAdapter:已添加getItems

fun getItems() {
   return mDevices
}

如果您想更改isOn州,请更改型号并通知它。

adapter.getItems().get(i).setOn(true);
adapter.notifyDataSetChanged();

答案 1 :(得分:0)

我也喜欢上面的答案,但我完成这项工作的方法是将BroadcastReceiver传递给DeviceAdapter:

class DeviceAdapter(val mContext:Context, val mReceiver:MainBTStatusReceiver) : RecyclerView.Adapter<DeviceAdapter.DeviceHolder>()

然后使ViewHolder成为BroadcastReceiver的成员,并将ViewHolder的setter函数命名为setFocus。在调用BluetoothUtils类中的任何函数之前,我调用setFocus函数,然后广播接收器修改当前设置焦点的视图的颜色。我确实有一些担心,这可能不是可靠的,因为每次修改正确的ViewHolder是最准确的方法。如果您发现此问题,请发表评论告诉我。

我更新的BroadcastReceiver:

class MainBTStatusReceiver(): BroadcastReceiver() {

val TAG = "MainBTStatusReceiver"
var holder: DeviceAdapter.DeviceHolder? = null

fun setFocus(holder: DeviceAdapter.DeviceHolder) {
    this.holder = holder
}

override fun onReceive(context: Context?, intent: Intent) {
    val action = intent.action
    when (action) {
        BluetoothDevice.ACTION_BOND_STATE_CHANGED -> {
            val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
            when (device.bondState) {
                BluetoothDevice.BOND_BONDED -> {
                    holder!!.itemView.setBackgroundColor(Color.CYAN)
                    Log.d(TAG, "BONDED")
                }
                BluetoothDevice.BOND_BONDING -> {
                    Log.d(TAG, "BONDING")
                }
                BluetoothDevice.BOND_NONE -> {
                    holder!!.itemView.setBackgroundColor(Color.TRANSPARENT)
                    Log.d(TAG, "NONE")
                }
            }
        }
    }
}
}

和my表达式中的两个语句调用setFocus():

              R.id.pairOp -> {
                        Log.d(TAG, "pairOp reached")
                        mReceiver.setFocus(this@DeviceHolder)
                        BluetoothUtils.startPair(BluetoothAdapter.getDefaultAdapter(), btDevice)
                        Log.d(TAG, "start pair complete")
                        dialog!!.dismiss()
                    }
                    R.id.unPairOp -> {
                        Log.d(TAG, "unPairOp reached")
                        mReceiver.setFocus(this@DeviceHolder)
                        BluetoothUtils.unPair(btDevice)
                        Log.d(TAG, "unpair complete")
                        dialog!!.dismiss()
                    }