在RecyclerView上单击动态更改工具栏项目可见性(不使用LongClick)

时间:2018-01-24 09:40:45

标签: java android android-recyclerview toolbar toolbaritems

我有一个应用程序(基于this tutorial),它有一个活动,允许用户选择几个朋友发送消息。现在,我还在右上角有一个检查图标。当用户点击它时,所选联系人将被发送到父活动。当用户在recyclerview中单击联系人时,联系人的状态将从未选中更改为已选择,反之亦然。

大多数教程和堆栈溢出答案建议在长按时更改工具栏,但我想要做的是在recyclerview项目点击上更改它,即。 当用户点击recyclerview项目时我想显示检查按钮,如果所选用户的数量不是0(selectedContacts!= null),并隐藏按钮,如果它是0.我也想show在用户启动活动时隐藏它,基于相同的条件 。正如我所说,我已经看了很多SO答案,但我找不到任何对我有用的东西。我尝试过的一些答案:thisthisthisthisthisthis ......

这就是它的样子:

enter image description here

activity_choose_contacts_action.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
    android:id="@+id/add"
    android:icon="@drawable/ic_icon_check_white"
    android:title="@string/add"
    app:showAsAction="always" />
</menu>

choose_contacts.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"
tools:context=".contactprofile.ChooseContactsActivity">

    <android.support.v7.widget.Toolbar
    android:id="@+id/chooseContactsToolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/ppdColorOrange"
    android:fitsSystemWindows="true"
    android:minHeight="?attr/actionBarSize"
    app:theme="@style/ToolbarWhiteBackArrow">

       <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

            <TextView
            android:id="@+id/selectContactTextView"
            style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/select_contacts"
            android:textColor="@color/white" />
        </RelativeLayout>
    </android.support.v7.widget.Toolbar>

    <android.support.v7.widget.RecyclerView
    android:id="@+id/contacts_list"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:divider="@color/list_divider"
    android:dividerHeight="1dp"
    app:srcCompat="@drawable/ic_icon_user" />

</LinearLayout>

ChooseContactsActivity.java:

adapter = new ChooseContactsAdapter(contactList, getApplicationContext());
    recyclerView.setAdapter(adapter);

    recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), recyclerView, new ChooseContactsActivity.ClickListener() {
        @Override
        public void onClick(View view, int position) {
            if (selectedContacts != null) {
                addContacts.setImageResource(R.drawable.ic_icon_check_white);
            } else {
                addContacts.setVisibility(View.GONE);
            }
        }

        @Override
        public void onLongClick(View view, int position) {

        }
     }));

        recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), recyclerView, new ChooseContactsActivity.ClickListener() {
        @Override
        public void onClick(View view, int position) {

        }

        @Override
        public void onLongClick(View view, int position) {

        }
     }));

........

Call<ContactsResponse> call = apiService.getMyContact(userId);
    call.enqueue(new Callback<ContactsResponse>() {
        @Override
        public void onResponse(Call<ContactsResponse> call, retrofit2.Response<ContactsResponse> response) {
            List<Contact> contact = response.body().getResults();

            contactList.addAll(contact);
            adapter.notifyDataSetChanged();

            RecyclerView recyclerView = findViewById(R.id.contacts_list);

            // Checking previously selected contacts
            if (selectedContacts != null) {
                new Handler(Looper.getMainLooper()).postDelayed(() -> {

                    List<Integer> selectedIndexes = new ArrayList<>();

                    // Finding indexes of selected contact ids
                    for (int i = 0; i < contactList.size(); i++) {
                        if (selectedContacts.contains(contactList.get(i).getUserId())) {
                            selectedIndexes.add(i);
                        }
                    }

                    // Triggering click on each selected item
                    for (int j = 0; j < selectedIndexes.size(); j++) {
                        recyclerView.getChildAt(selectedIndexes.get(j)).performClick();
                    }
                }, 500);

            }


        }

........

interface ClickListener {
    void onClick(View view, int position);

    void onLongClick(View view, int position);
}

private static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {

    private GestureDetector gestureDetector;
    private ChooseContactsActivity.ClickListener clickListener;

    RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ChooseContactsActivity.ClickListener clickListener) {
        this.clickListener = clickListener;
        gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
                if (child != null && clickListener != null) {
                    clickListener.onLongClick(child, recyclerView.getChildLayoutPosition(child));
                }
            }
        });
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {

        View child = rv.findChildViewUnder(e.getX(), e.getY());
        if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
            clickListener.onClick(child, rv.getChildLayoutPosition(child));
        }
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.activity_choose_contacts_action, menu);
    if (getSupportActionBar() != null) {
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }
    getSupportActionBar().setDisplayShowHomeEnabled(true);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            finish();
            return true;
        case R.id.add:
            ArrayList<String> selectedIds = adapter.selectedIds;

            String text = "abc";

            Intent intent = new Intent();
            intent.putStringArrayListExtra("contacts_added", selectedIds);
            setResult(RESULT_OK, intent);
            finish();
            return true;
    }
    return super.onOptionsItemSelected(item);
}

ContactsAdapter.java:

 holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // toggle selection
            toggleSelection(position);

            // Change background color of the selected items in list view
            holder.itemView.setBackgroundColor(selectedItems.get(position) ? context.getResources().getColor(R.color.ppdColorOrangeSelection) : Color.TRANSPARENT);

            if (position != RecyclerView.NO_POSITION) {
                Contact contact = contactList.get(position);
                applyIconAnimation(holder, position);
                String userId = contact.getUserId();

                if (!selectedIds.contains(userId)) {
                    selectedIds.add(userId);
                } else {
                    selectedIds.remove(userId);
                }
            }

            applyIconAnimation(holder, position);
            getSelectedItemCount();
            getSelectedItems();
            resetAnimationIndex();
            getSelectedItemCount();
        }
    });
}

@Override
public int getItemViewType(int position) {
    return position;
}

private void applyProfilePicture(ChooseContactsViewHolder holder, Contact contact) {
    Picasso.with(context)
            .load(AppConfig.URL_PROFILE_PHOTO + contact.getThumbnailUrl())
            .placeholder(textDrawable)
            .error(textDrawable)
            .transform(new CircleTransform())
            .into(holder.thumbNail);
}

private void applyIconAnimation(ChooseContactsViewHolder holder, int position) {
    if (selectedItems.get(position, false)) {
        holder.iconFront.setVisibility(View.GONE);
        resetIconYAxis(holder.iconBack);
        holder.iconBack.setVisibility(View.VISIBLE);
        holder.iconBack.setAlpha(1);
        if (currentSelectedIndex == position) {
            FlipAnimator.flipView(context, holder.iconBack, holder.iconFront, true);
            resetCurrentIndex();
        }
    } else {
        holder.iconBack.setVisibility(View.GONE);
        resetIconYAxis(holder.iconFront);
        holder.iconFront.setVisibility(View.VISIBLE);
        holder.iconFront.setAlpha(1);
        if ((reverseAllAnimations && animationItemsIndex.get(position, false)) || currentSelectedIndex == position) {
            FlipAnimator.flipView(context, holder.iconBack, holder.iconFront, false);
            resetCurrentIndex();
        }
    }
}

private void toggleSelection(int pos) {
    currentSelectedIndex = pos;
    if (selectedItems.get(pos, false)) {
        selectedItems.delete(pos);
        animationItemsIndex.delete(pos);
    } else {
        selectedItems.put(pos, true);
        animationItemsIndex.put(pos, true);
    }
    //notifyItemChanged(pos);
}

private void clearSelections() {
    reverseAllAnimations = true;
    selectedItems.clear();
    notifyDataSetChanged();
}
@Override
public int getItemCount() {
    return contactList.size();
}

private int getSelectedItemCount() {
    return selectedItems.size();
}

private List<Integer> getSelectedItems() {
    List<Integer> items =
            new ArrayList<>(selectedItems.size());
    for (int i = 0; i < selectedItems.size(); i++) {
        items.add(selectedItems.keyAt(i));
    }

    return items;
}

2 个答案:

答案 0 :(得分:1)

这里为了简化我使用CheckBox作为RecyclerView项并隐藏它的按钮的方法。之后,它将像TextView一样运行,但也具有检查更改属性。然后我将OnCheckedChangeListener设置为CheckBox。我在每个真onCheckedChanged个结果上增加一个整数计数器,并在false时减少。然后通过Interface我将该计数器的值传递回基本活动。然后检查计数器是否大于0,这将设置项目的可见性。以下是该任务的参考代码。

<强>接口

public interface ShareValue {
void getValue(int count);
}

<强> onCheckedChanged

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean 
    isChecked) {
        count = isChecked ? count++ : count--;
        shareValue.getValue(count);
    }

<强> onCreateOptionsMenu

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    item = menu.getItem(0);
    item.setVisible(false);
    return true;
}


@Override
public void getValue(int count) {
    item.setVisible(count > 0);
  }
}

答案 1 :(得分:0)

所以我找到了解决方案。我补充说:

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.activity_choose_contacts_action, menu);

    if (adapter.getSelectedItemCount() == 0) {
        menu.findItem(R.id.add).setVisible(false);
    } else {
        menu.findItem(R.id.add).setVisible(true);
    }

    if (getSupportActionBar() != null) {
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }
    getSupportActionBar().setDisplayShowHomeEnabled(true);
    return true;
}
.....
// Checking previously selected contacts
        if (selectedContacts != null) {
            new Handler(Looper.getMainLooper()).postDelayed(() -> {

                List<Integer> selectedIndexes = new ArrayList<>();

                // Finding indexes of selected contact ids
                for (int i = 0; i < contactList.size(); i++) {
                    if (selectedContacts.contains(contactList.get(i).getUserId())) {
                        selectedIndexes.add(i);
                    }
                }

                // Triggering click on each selected item
                for (int j = 0; j < selectedIndexes.size(); j++) {
                    recyclerView.getChildAt(selectedIndexes.get(j)).performClick();
                }
                invalidateOptionsMenu();
            }, 500);
......
 @Override
        public void onClick(View view, int position) {
            // invalidateOptionsMenu(); (resetting onCreateOptionsMenu) executed with 600 millis delay, otherwise it will happen before the 500 millis
            // delay when checking previously selected contacts
            new Handler(Looper.getMainLooper()).postDelayed(() -> invalidateOptionsMenu(), 600);
        }