在膨胀布局中的 Switch 视图上设置的 OnCheckedChangeListener 不会触发
OnCheckedChangeListener set on Switch view in inflated layout is not triggering
我正在学习 Android 开发,我打算在 ListView 中显示任何 connected/paired 蓝牙设备。每个列表项在左侧都有一个设备名称,在右侧有一个开关。 截图有点大
我设计了如何在单独的 bluetooth_device_entry.xml
文件中显示每个项目。
bluetooth_device_entry.xml
文件使用 RelativeLayout 布局,它有两个 children TextView
和 Switch
在主布局 XML 文件 activity_connected_devices.xml
中,我有一个 ListView,我用 bluetooth_device_entry.xml
文件以编程方式填充它。
我的问题在JavaactivityConnectedDevicesActivity.java
。我可以将 setOnItemClickListener
附加到 ListView
项目,但即使在 bluetooth_device_entry.xml
充气后,附加到充气布局开关的 setOnChangeListener()
也不会被触发。
bluetoothConnectedDeviceItemClickListener
有效,但 switchCheckedListener
无效。
知道如何解决这个问题吗?谢谢。
bluetooth_device_entry.xml
(填充每个 ListView
项的内容)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bluetoothDeviceEntryLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:descendantFocusability="blocksDescendants">
<TextView
android:id="@+id/connectedDeviceName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/light_grey"
android:paddingBottom="12dp"
android:paddingEnd="8dp"
android:paddingStart="8dp"
android:paddingTop="12dp"
android:text="@string/txtPlaceHolderConnectedBluetoothText"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="@dimen/dimen_listTextSizeMedium" />
<Switch
android:id="@+id/deviceStateSwitch"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_alignBaseline="@+id/connectedDeviceName"
android:layout_alignBottom="@+id/connectedDeviceName"
android:layout_alignParentEnd="true"
android:layout_marginEnd="15dp"
android:switchMinWidth="@dimen/dimen_switchWidth" />
</RelativeLayout>
activity_connected_devices.xml
(Activity 最初由 onCreate()
中的 ConnectedDevicesActivity.java
加载)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activityConnectedDevicesLinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/txtTitleConnectedDevices"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/dark_blue"
android:gravity="center"
android:text="@string/txtConnectedDevices"
android:textColor="@color/light_blue"
android:textSize="@dimen/dimen_buttonTextSize" />
<ListView
android:id="@+id/bluetoothConnectedDevicesListView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3" />
</LinearLayout>
ConnectedDevicesActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.Switch;
import android.widget.Toast;
public class ConnectedDevicesActivity extends AppCompatActivity
{
ListView bluetoothConnectedDevicesListView;
Switch deviceSwitch;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_connected_devices);
setTitle("Connected Devices");
bluetoothConnectedDevicesListView = findViewById(R.id.bluetoothConnectedDevicesListView);
showConnectedBluetoothDevices();
}
public void showConnectedBluetoothDevices()
{
String[] connectedBluetoothDevices = new String[10];
for(int i=0; i<connectedBluetoothDevices.length; i++)
{
connectedBluetoothDevices[i] = "Device " + (i+1);
}
ArrayAdapter<String> connectedBluetoothDevicesAdapter =
new ArrayAdapter<String>(this,
R.layout.bluetooth_connected_devices_entry,
R.id.connectedDeviceName,
connectedBluetoothDevices);
bluetoothConnectedDevicesListView.setAdapter(connectedBluetoothDevicesAdapter);
bluetoothConnectedDevicesListView.setOnItemClickListener(new bluetoothConnectedDeviceItemClickListener());
View inflatedView = getLayoutInflater().inflate(R.layout.bluetooth_connected_devices_entry, null);
deviceSwitch = inflatedView.findViewById(R.id.deviceStateSwitch);
/* This is not responding to switch loaded from inflated view */
deviceSwitch.setOnCheckedChangeListener(new switchCheckedListener());
Toast.makeText(
ConnectedDevicesActivity.this,
String.format("Switch checked? %b", deviceSwitch.isChecked()),
Toast.LENGTH_SHORT).show();
}
public class bluetoothConnectedDeviceItemClickListener implements OnItemClickListener
{
/* When the user taps an item in the list view */
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Toast.makeText(
ConnectedDevicesActivity.this,
String.format("You tapped %s", bluetoothConnectedDevicesListView.getItemAtPosition(position)),
Toast.LENGTH_SHORT).show();
}
}
/* When the user toggles a switch */
public class switchCheckedListener implements CompoundButton.OnCheckedChangeListener
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
Toast.makeText(
ConnectedDevicesActivity.this,
String.format("Checked state is %s", isChecked),
Toast.LENGTH_SHORT).show();
}
}
}
您正在夸大与您 ListView
的项目无关的额外视图
bluetoothConnectedDevicesListView.setAdapter(connectedBluetoothDevicesAdapter);
bluetoothConnectedDevicesListView.setOnItemClickListener(new bluetoothConnectedDeviceItemClickListener());
View inflatedView = getLayoutInflater().inflate(R.layout.bluetooth_connected_devices_entry, null);
// ^^^^^^^^ totally a new item, has no relation with views inside list
deviceSwitch = inflatedView.findViewById(R.id.deviceStateSwitch);
deviceSwitch.setOnCheckedChangeListener(new switchCheckedListener());
Solution : You need to create a customize Adapter
并且它将负责提供每个行项目视图并且在 getView
中你可以应用操作(附加 listeners/manipulating 值)在您的 rowitem 视图中的子视图上。
注意:您还需要管理一个列表来跟踪切换视图状态,因为适配器会重新创建|重用视图。
我正在学习 Android 开发,我打算在 ListView 中显示任何 connected/paired 蓝牙设备。每个列表项在左侧都有一个设备名称,在右侧有一个开关。 截图有点大
我设计了如何在单独的 bluetooth_device_entry.xml
文件中显示每个项目。
bluetooth_device_entry.xml
文件使用 RelativeLayout 布局,它有两个 children TextView
和 Switch
在主布局 XML 文件 activity_connected_devices.xml
中,我有一个 ListView,我用 bluetooth_device_entry.xml
文件以编程方式填充它。
我的问题在JavaactivityConnectedDevicesActivity.java
。我可以将 setOnItemClickListener
附加到 ListView
项目,但即使在 bluetooth_device_entry.xml
充气后,附加到充气布局开关的 setOnChangeListener()
也不会被触发。
bluetoothConnectedDeviceItemClickListener
有效,但 switchCheckedListener
无效。
知道如何解决这个问题吗?谢谢。
bluetooth_device_entry.xml
(填充每个 ListView
项的内容)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bluetoothDeviceEntryLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:descendantFocusability="blocksDescendants">
<TextView
android:id="@+id/connectedDeviceName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/light_grey"
android:paddingBottom="12dp"
android:paddingEnd="8dp"
android:paddingStart="8dp"
android:paddingTop="12dp"
android:text="@string/txtPlaceHolderConnectedBluetoothText"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="@dimen/dimen_listTextSizeMedium" />
<Switch
android:id="@+id/deviceStateSwitch"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_alignBaseline="@+id/connectedDeviceName"
android:layout_alignBottom="@+id/connectedDeviceName"
android:layout_alignParentEnd="true"
android:layout_marginEnd="15dp"
android:switchMinWidth="@dimen/dimen_switchWidth" />
</RelativeLayout>
activity_connected_devices.xml
(Activity 最初由 onCreate()
中的 ConnectedDevicesActivity.java
加载)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activityConnectedDevicesLinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/txtTitleConnectedDevices"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/dark_blue"
android:gravity="center"
android:text="@string/txtConnectedDevices"
android:textColor="@color/light_blue"
android:textSize="@dimen/dimen_buttonTextSize" />
<ListView
android:id="@+id/bluetoothConnectedDevicesListView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3" />
</LinearLayout>
ConnectedDevicesActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.Switch;
import android.widget.Toast;
public class ConnectedDevicesActivity extends AppCompatActivity
{
ListView bluetoothConnectedDevicesListView;
Switch deviceSwitch;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_connected_devices);
setTitle("Connected Devices");
bluetoothConnectedDevicesListView = findViewById(R.id.bluetoothConnectedDevicesListView);
showConnectedBluetoothDevices();
}
public void showConnectedBluetoothDevices()
{
String[] connectedBluetoothDevices = new String[10];
for(int i=0; i<connectedBluetoothDevices.length; i++)
{
connectedBluetoothDevices[i] = "Device " + (i+1);
}
ArrayAdapter<String> connectedBluetoothDevicesAdapter =
new ArrayAdapter<String>(this,
R.layout.bluetooth_connected_devices_entry,
R.id.connectedDeviceName,
connectedBluetoothDevices);
bluetoothConnectedDevicesListView.setAdapter(connectedBluetoothDevicesAdapter);
bluetoothConnectedDevicesListView.setOnItemClickListener(new bluetoothConnectedDeviceItemClickListener());
View inflatedView = getLayoutInflater().inflate(R.layout.bluetooth_connected_devices_entry, null);
deviceSwitch = inflatedView.findViewById(R.id.deviceStateSwitch);
/* This is not responding to switch loaded from inflated view */
deviceSwitch.setOnCheckedChangeListener(new switchCheckedListener());
Toast.makeText(
ConnectedDevicesActivity.this,
String.format("Switch checked? %b", deviceSwitch.isChecked()),
Toast.LENGTH_SHORT).show();
}
public class bluetoothConnectedDeviceItemClickListener implements OnItemClickListener
{
/* When the user taps an item in the list view */
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Toast.makeText(
ConnectedDevicesActivity.this,
String.format("You tapped %s", bluetoothConnectedDevicesListView.getItemAtPosition(position)),
Toast.LENGTH_SHORT).show();
}
}
/* When the user toggles a switch */
public class switchCheckedListener implements CompoundButton.OnCheckedChangeListener
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
Toast.makeText(
ConnectedDevicesActivity.this,
String.format("Checked state is %s", isChecked),
Toast.LENGTH_SHORT).show();
}
}
}
您正在夸大与您 ListView
的项目无关的额外视图
bluetoothConnectedDevicesListView.setAdapter(connectedBluetoothDevicesAdapter);
bluetoothConnectedDevicesListView.setOnItemClickListener(new bluetoothConnectedDeviceItemClickListener());
View inflatedView = getLayoutInflater().inflate(R.layout.bluetooth_connected_devices_entry, null);
// ^^^^^^^^ totally a new item, has no relation with views inside list
deviceSwitch = inflatedView.findViewById(R.id.deviceStateSwitch);
deviceSwitch.setOnCheckedChangeListener(new switchCheckedListener());
Solution : You need to create a customize Adapter
并且它将负责提供每个行项目视图并且在 getView
中你可以应用操作(附加 listeners/manipulating 值)在您的 rowitem 视图中的子视图上。
注意:您还需要管理一个列表来跟踪切换视图状态,因为适配器会重新创建|重用视图。