【问题标题】:Chip Group OnCheckedChangeListener() not triggered芯片组 OnCheckedChangeListener() 未触发
【发布时间】:2018-11-26 08:46:57
【问题描述】:

我正在尝试制作基于 ChipGroup 和 Chip 的 recyclerview 过滤器

我在我的应用程序上使用片段,因此,包含 RecyclerView 的片段包含一个 frameLayout,它膨胀了 ChipGroup 过滤器片段

当用户取消选择 ChipGroup 中的所有芯片时,我试图触发一个监听器(我已经在芯片上放置了监听器以在用户检查芯片时触发)

我已经在chipgroup上放了一些监听器,但没有人被触发

FilterFragment.java

public class FilterFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
public ChipGroup chipGroup;

// TODO: Rename and change types of parameters
public View.OnClickListener chipClickListener;

private OnFragmentInteractionListener mListener;

public FilterFragment() {
    // Required empty public constructor
}


public static FilterFragment newInstance(View.OnClickListener 
param1) {
    CoachFilterFragment fragment = new CoachFilterFragment();
    Bundle args = new Bundle();

    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {

    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup 
container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_filter, 
container, false);
    this.chipGroup = view.findViewById(R.id.chipGroup);
    for(Skill skill : ((MainActivity)getContext()).api.skills){

        Chip chip = new Chip(getContext());
        chip.setId(skill.getId());


        chip.setText(skill.getName());
        chip.setOnClickListener(chipClickListener);
        chip.setCheckable(true);
        chipGroup.addView(chip);

    }

    chipGroup.setOnCheckedChangeListener((chipGroup, id) -> {
      Log.d("test","ok");
    });


    return view;
}

public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);

}

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}



public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
  }
}

FilterFragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".Fragment.FilterFragment">

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <com.google.android.material.chip.ChipGroup
        android:id="@+id/chipGroup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

       </com.google.android.material.chip.ChipGroup>
   </androidx.constraintlayout.widget.ConstraintLayout>

</FrameLayout>

有人知道为什么我的 ChipGroup 没有触发任何侦听器吗?也许我缺少某些参数或什么?

【问题讨论】:

  • 你为什么要将监听器两次设置为同一个芯片组?在你的第一个监听器中尝试登录 Log.d("test","ok");。
  • @KaranMer 只是为了测试,我尝试添加很多不同的侦听器,但我没有删除它以显示我尝试过的内容
  • 移除第二个并在第一个监听器中记录值,记得在移除第二个监听器后清理你的项目。
  • @KaranMer 我已经删除了监听器,只保留了 setOnCheckedChangeListener,清理并重建项目但没有变化,当我选择或取消选择 ChipsGroup 中的任何子项时,不会触发监听器
  • 你能用修改后的代码更新你的问题吗?

标签: android android-chips


【解决方案1】:

您的代码很好,唯一的问题是 setOnCheckedChangeListener() 仅在您的 ChipGroup 用于 singleSelection

时才有效

阅读ChipGroup

的文档

setOnCheckedChangeListener()

  • 注册一个回调,以便在该组中检查的芯片发生变化时调用。
  • 此回调仅在single selection mode.中调用

还请阅读

Handling Checked Chips

调用 setOnCheckedChangeListener(OnCheckedChangeListener) 注册一个回调,该回调将在该组中被检查芯片发生变化时调用。此回调仅在单选模式下调用。

如果您想使用 ChipGroup 中的 setOnCheckedChangeListener(),则需要使用 app:singleSelection="true"

更新

根据您的以下评论,我添加了示例代码,以便在选择 ChipGroup 时设法处理

ChipGroup 中维护选择的示例代码

布局.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.chip.ChipGroup
            android:id="@+id/chipGroup"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginRight="8dp"
            android:layout_marginBottom="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            >

        </com.google.android.material.chip.ChipGroup>
    </androidx.constraintlayout.widget.ConstraintLayout>

    <Button
        android:layout_width="match_parent"
        android:text="Get Result"
        android:id="@+id/btnShowResult"
        android:layout_gravity="bottom"
        android:layout_height="wrap_content" />
</LinearLayout>

活动代码

public class Main3Activity extends AppCompatActivity {

    public ChipGroup chipGroup;
    public Button btnShowResult;
    public ArrayList<Boolean> booleanArrayList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);

        chipGroup = findViewById(R.id.chipGroup);
        btnShowResult = findViewById(R.id.btnShowResult);


        btnShowResult.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                for (int i = 0; i < booleanArrayList.size(); i++) {
                    Log.e("RESULT", i + " :" + booleanArrayList.get(i));
                }
            }
        });

        for (int i = 0; i < 5; i++) {

            Chip chip = new Chip(this);
            chip.setId(i);
            chip.setTag(i);

            booleanArrayList.add(false);
            chip.setText("Chip No : " + i);
            chip.setCheckable(true);

            chip.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean b) {

                    int tag = (int) compoundButton.getTag();
                    booleanArrayList.set(tag, b);

                }
            });
            chipGroup.addView(chip);

        }

        chipGroup.invalidate();


        chipGroup.setOnCheckedChangeListener(new ChipGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(ChipGroup chipGroup, int i) {

                Chip chip = chipGroup.findViewById(i);


                if (chip != null)
                    Toast.makeText(getApplicationContext(), "Chip is " + chip.getText().toString(), Toast.LENGTH_SHORT).show();

                Log.e("OnCheckedChangeListener", "Called");
            }
        });

    }

    ChipGroup.OnCheckedChangeListener onCheckedChangeListener = new ChipGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(ChipGroup chipGroup, int i) {

        }
    };

}

欲了解更多信息,请查看以下文章

【讨论】:

  • ChipGroup 的所有子节点都未选中时没有办法处理吗?
  • @Benjamin 检查更新的答案我添加了演示代码来维护ChipGroup 选择让我知道是否需要任何帮助
  • 首先,感谢您提供此示例,但是是与否,更多解释:芯片上的侦听器位于父片段中,因此当我检查任何芯片时,父片段在 RV 上应用过滤器取决于所选芯片上的哪个值,我试图找到在未选择所有芯片时具有相同“逻辑”的方法(用于触发父片段并删除过滤器)。我认为最好的方法是像你一样做,添加一个按钮来应用过滤器和一个重置过滤器,因为实际的芯片组监听器看起来不可能。
  • 为什么还要在每个 Chip 和 ChipGroup 上添加setOnCheckedChangeListener?
【解决方案2】:

所有芯片都需要有android:checkable="true" 属性,触发器才能存在于它们上面。

除了设置任何芯片的初始检查(无需点击),执行顺序必须首先创建侦听器,使用chipGroup.setOnCheckedChangeListener(),然后是chip.isChecked = true。

因此您可以动态处理 xml 和 isChecked 中的 checkable 属性。

.xml

<com.google.android.material.chip.ChipGroup
    ..
    app:singleSelection="true">
    <com.google.android.material.chip.Chip
        ..
        android:checkable="true"/>

.kt

binding.chipGroup.setOnCheckedChangeListener { chipGroup, i -> 

}
binding.firstChip.isChecked = true   //default

GL

【讨论】:

    【解决方案3】:

    只有在 chipGroup 中将单选设置为 true 时,Chip Click 侦听器才会起作用。

    app:singleSelection="true"
    

    如果您使用的是下面的样式,请确保也将其分配给每个单独的芯片。

    style="@style/Widget.MaterialComponents.Chip.Choice"
    

    像这样:

    <com.google.android.material.chip.ChipGroup
                    android:id="@+id/chip_group"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginEnd="10dp"
                    app:singleSelection="true"
                    style="@style/Widget.MaterialComponents.Chip.Choice">
    
                <com.google.android.material.chip.Chip
                        android:id="@+id/chip_2"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        style="@style/Widget.MaterialComponents.Chip.Choice"
                        android:text="@string/announcements"
                        android:textAppearance="@style/ChipThemeBold"/>
                <com.google.android.material.chip.Chip
                        android:id="@+id/chip_3"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        style="@style/Widget.MaterialComponents.Chip.Choice"
                        android:text="@string/fyi"
                        android:textAppearance="@style/ChipThemeBold"/>
                <com.google.android.material.chip.Chip
                        android:id="@+id/chip_4"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        style="@style/Widget.MaterialComponents.Chip.Choice"
                        android:text="@string/heartbeat"
                        android:textAppearance="@style/ChipThemeBold"  />
                <com.google.android.material.chip.Chip
                        android:id="@+id/chip_5"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        style="@style/Widget.MaterialComponents.Chip.Choice"
                        android:text="@string/pitch"
                        android:textAppearance="@style/ChipThemeBold"  />
                <com.google.android.material.chip.Chip
                        android:id="@+id/chip_6"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        style="@style/Widget.MaterialComponents.Chip.Choice"
                        android:text="@string/question"
                        android:textAppearance="@style/ChipThemeBold" 
                        android:layout_marginEnd="15dp" />
    
            </com.google.android.material.chip.ChipGroup>
    

    【讨论】:

      【解决方案4】:

      它是这样工作的。

      <com.google.android.material.chip.ChipGroup
          ...
          ...
          style="@style/Widget.MaterialComponents.Chip.Choice"
          app:singleSelection="true">
      
          <!-- Declare your chips or add them programmatically -->
      
      </com.google.android.material.chip.ChipGroup>
      
          
          // Inflate instead of NEW instance
          val chip = layoutInflater.inflate(R.layout.chip, chipGroup, false) as Chip
          chip.text = "Text"
          chipGroup.addView(chip)
          
          // setOnCheckedChangeListener
          chipGroup.setOnCheckedChangeListener { group, checkedId ->
              // The same checked chip
              if (checkedId == -1) {
                  return@setOnCheckedChangeListener
              }
          
              // TODO
          }
      

      【讨论】:

        【解决方案5】:

        您可以为所有芯片组子代添加setOnCheckedChangeListener。 (在 Kotlin 中)

        for (index in 0 until chipGroup!!.childCount) {
                val chip: Chip = chipGroup!!.getChildAt(index) as Chip
        
                // Set the chip checked change listener
                chip.setOnCheckedChangeListener{view, isChecked ->
                    if (isChecked){
                        list.add(view.text.toString())
                    }else{
                        list.remove(view.text.toString())
                    }
        
                    if (list.isNotEmpty()){
                        // Show the selection
                        Log.d(LOGTAG,"Selected $list")
                    }
                }
            }
        

        【讨论】:

          【解决方案6】:

          我有同样的问题,但它与ChipGroup 无关,因为我将ChipGroup 放在了这样的错误位置:

          <androidx.constraintlayout.widget.ConstraintLayout>
          
             <com.google.android.material.chip.ChipGroup />
          
             <other full screen view />
          <androidx.constraintlayout.widget.ConstraintLayout/>
          

          它使我的ChipGroup 无法聚焦,所以只需将ChipGroup 移动到父视图的底部

          <androidx.constraintlayout.widget.ConstraintLayout>
             <other full screen view />
          
             <-- change here -->
             <com.google.android.material.chip.ChipGroup />
          <androidx.constraintlayout.widget.ConstraintLayout/>
          

          确实有效,希望对你有帮助

          【讨论】:

            【解决方案7】:

            如果你愿意,我建议不要使用带有芯片的 recyclerview 水平滚动,因为你有 HorizontalScrollView 和它 与芯片组配合得很好:

            基于 Nilesh Rathod 的回答。要动态添加芯片,您需要以下代码:

            活动文件代码:

            String[] fileNameChip = getIntent().getStringArrayExtra(Constants.CHIPS_NAME_ARRAY);
            
                    for (final String chipName : fileNameChip) {
                         LayoutInflater layoutInflater = getLayoutInflater();
                         Chip chip = (Chip) 
                         layoutInflater.inflate(R.layout.cat_chip_group_item_choice, chipGroup, false);
                         chip.setText(chipName);
                         chip.setId(i); //HERE SET ID THAT WILL BE CHECKED_ID ON setOnCheckedChangeListener
            
                         chip.setOnClickListener(new View.OnClickListener() {
                              @Override
                              public void onClick(View v) {
                                 Log.d(TAG, "onClick: " + chipName );
                                 }
                              });
                              chipGroup.addView(chip);
                          }  
                          chipGroup.setOnCheckedChangeListener(new ChipGroup.OnCheckedChangeListener() {
                               @Override
                               public void onCheckedChanged(ChipGroup group, int checkedId) {
                                      Log.d(TAG, "onCheckedChanged: " + checkedId);
                                   }
                                });
            

            活动 XML 文件:

            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            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">
            
            <HorizontalScrollView
                android:layout_width="match_parent"
                android:scrollbars="none"
                android:layout_height="wrap_content">
            
                <com.google.android.material.chip.ChipGroup
                    android:id="@+id/chip_group_code_files"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    app:singleLine="true"
                    app:singleSelection="true" />
            </HorizontalScrollView>
            

            cat_chip_group_item_choice.xml:(指定筹码类型:Choice,filter,Action,Normal)

            <?xml version="1.0" encoding="utf-8"?>
            <com.google.android.material.chip.Chip
                xmlns:android="http://schemas.android.com/apk/res/android"
                style="@style/Widget.MaterialComponents.Chip.Choice"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
            

            【讨论】:

              【解决方案8】:

              发现这是使用多选芯片组最简单的方法:

                  chipGroup.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
                          @Override
                          public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
                              List<Integer> ids = chipGroup.getCheckedChipIds();
                              if (ids.contains(R.id.chip1)) {
                              // do your stuff 
                           }
                         }
                      });
              

              【讨论】:

              • 如果取消所有选择,则不会触发。
              猜你喜欢
              • 2020-08-25
              • 2021-04-05
              • 2015-03-30
              • 2020-09-02
              • 2020-02-03
              • 1970-01-01
              • 1970-01-01
              • 2018-12-14
              • 2019-05-23
              相关资源
              最近更新 更多