RecyclerView внутри фрагмента не отображается должным образом - PullRequest
0 голосов
/ 18 апреля 2020

В настоящее время я работаю над WhatsApp-подобным Android приложением, и недавно я столкнулся с проблемой, которая вызывала у меня головную боль. Я пытаюсь создать RecyclerView внутри фрагмента, принадлежащего TabLayout. По сути, у меня есть 3 вкладки, каждая из которых содержит фрагмент. Первая вкладка предназначена для разговоров пользователя, вторая - для групп, а третья - для контактов. Каждая вкладка должна содержать RecyclerView, который отображает данные из FireFase Firestore в соответствии с текущим идентификатором пользователя, предоставленным Firebase Authentication. Я думаю, что проблема заключается в том, что внутри фрагмента, кроме RecyclerView, у меня также есть кнопка FloatingActionButton. Эта кнопка используется в каждом фрагменте для выполнения таких действий, как отправка нового сообщения или создание новой группы или добавление нового контакта. При нажатии, скажем, на вкладке групп, FAB отображает AlertDialog, запрашивая у пользователя имя группы, а затем выбирает «Создать», и группа создается и добавляется в базу данных. Теперь проблема в том, что когда пользователь входит в приложение и получает доступ к вкладке групп, его группы не отображаются, но если пользователь нажимает на FAB, появляется AlertDialog, и если пользователь нажимает EditText, чтобы выбрать имя для новой группы внезапно группы пользователей отображаются внутри фрагмента. Мне нужна помощь с этим, у меня нет большого опыта работы с Android, и я думаю, что я испортил макеты, но я не могу понять это сам.

Вот мой код :

MainActivity. java

    package com.example.snakemessenger;

    import android.content.Intent;
    import android.os.Bundle;

    import androidx.annotation.NonNull;

    import android.view.MenuItem;
    import com.google.android.material.tabs.TabLayout;
    import com.google.firebase.auth.FirebaseAuth;
    import com.google.firebase.auth.FirebaseUser;
    import com.google.firebase.firestore.FirebaseFirestore;
    import com.google.firebase.storage.FirebaseStorage;
    import com.google.firebase.storage.StorageReference;

    import androidx.appcompat.app.AppCompatActivity;
    import androidx.appcompat.widget.Toolbar;
    import androidx.viewpager.widget.ViewPager;

    import android.view.Menu;
    import android.widget.Toast;

    public class MainActivity extends AppCompatActivity {
        public static final String TAG = "SnakeMessenger";
        private FirebaseAuth mAuth;
        private FirebaseFirestore db;
        private StorageReference storageReference;

        private ViewPager mViewPager;
        private TabLayout mTabLayout;
        private TabsAccessorAdapter mTabsAccessorAdapter;

        private FirebaseUser currentUser;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Toolbar mToolbar = findViewById(R.id.main_page_toolbar);
            setSupportActionBar(mToolbar);
            getSupportActionBar().setTitle("Snake Messenger");

            mAuth = FirebaseAuth.getInstance();
            db = FirebaseFirestore.getInstance();
            storageReference = FirebaseStorage.getInstance().getReference();

            currentUser = mAuth.getCurrentUser();

            if (currentUser == null) {
                sendUserToLoginActivity();
            }

            mViewPager = findViewById(R.id.main_tabs_pager);
            mTabsAccessorAdapter = new TabsAccessorAdapter(getSupportFragmentManager());
            mViewPager.setAdapter(mTabsAccessorAdapter);

            mTabLayout = findViewById(R.id.main_tabs);
            mTabLayout.setupWithViewPager(mViewPager);
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            super.onCreateOptionsMenu(menu);

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

            return true;
        }

        @Override
        public boolean onOptionsItemSelected(@NonNull MenuItem item) {
            super.onOptionsItemSelected(item);

            if (item.getItemId() == R.id.main_find_friends_option) {
                // TODO
            } else if (item.getItemId() == R.id.main_settings_option) {
                sendUserToSettingsActivity();
            } else if (item.getItemId() == R.id.main_sign_out_option) {
                mAuth.signOut();
                sendUserToLoginActivity();
                Toast.makeText(MainActivity.this, "Signed out", Toast.LENGTH_SHORT).show();
            }

            return true;
        }

        private void sendUserToSettingsActivity() {
            Intent settingsIntent = new Intent(MainActivity.this, SettingsActivity.class);
            startActivity(settingsIntent);
        }

        private void sendUserToLoginActivity() {
            Intent loginIntent = new Intent(MainActivity.this, SignInActivity.class);
            loginIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(loginIntent);
            finish();
        }
    }

TabsAccessorAdapter. java


    package com.example.snakemessenger;

    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    import androidx.fragment.app.FragmentManager;
    import androidx.fragment.app.FragmentPagerAdapter;

    public class TabsAccessorAdapter extends FragmentPagerAdapter {
        public TabsAccessorAdapter(@NonNull FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    return new ChatsFragment();
                case 1:
                    return new GroupsFragment();
                case 2:
                    return new FriendsFragment();
                default:
                    return null;
            }
        }

        @Override
        public int getCount() {
            return 3;
        }

        @Nullable
        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
                case 0:
                    return "Chats";
                case 1:
                    return "Groups";
                case 2:
                    return "Friends";
                default:
                    return null;
            }
        }
    }

GroupsFragment. java


    package com.example.snakemessenger;

    import android.content.DialogInterface;
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.util.Log;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.EditText;
    import android.widget.LinearLayout;
    import android.widget.Toast;

    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.appcompat.app.AlertDialog;
    import androidx.fragment.app.Fragment;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;

    import com.google.android.gms.tasks.OnCompleteListener;
    import com.google.android.gms.tasks.OnFailureListener;
    import com.google.android.gms.tasks.OnSuccessListener;
    import com.google.android.gms.tasks.Task;
    import com.google.android.material.floatingactionbutton.FloatingActionButton;
    import com.google.firebase.auth.FirebaseAuth;
    import com.google.firebase.auth.FirebaseUser;
    import com.google.firebase.firestore.FirebaseFirestore;
    import com.google.firebase.firestore.QueryDocumentSnapshot;
    import com.google.firebase.firestore.QuerySnapshot;

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    import de.hdodenhof.circleimageview.CircleImageView;


    /**
     * A simple {@link Fragment} subclass.
     */
    public class GroupsFragment extends Fragment {
        private View groupFragmentView;
        private RecyclerView mGroupsRecyclerView;
        private List<Group> groups;
        private FloatingActionButton mCreateGroup;
        private FirebaseAuth mAuth;
        private FirebaseUser currentUser;
        private FirebaseFirestore db;

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

        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            mAuth = FirebaseAuth.getInstance();
            currentUser = mAuth.getCurrentUser();
            db = FirebaseFirestore.getInstance();

            groups = new ArrayList<>();
            db.collection("users")
                    .document(currentUser.getUid())
                    .collection("groups")
                    .get()
                    .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                        @Override
                        public void onComplete(@NonNull Task<QuerySnapshot> task) {
                            if (task.isSuccessful()) {
                                for (QueryDocumentSnapshot document : task.getResult()) {
                                    groups.add(document.toObject(Group.class));
                                }

                                Toast.makeText(getActivity(), "Groups received successfully", Toast.LENGTH_SHORT).show();
                            } else {
                                Log.d(MainActivity.TAG, "Error getting document: ", task.getException());
                                Toast.makeText(getContext(), "Failed getting groups", Toast.LENGTH_SHORT).show();
                            }
                        }
                    });
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment

            groupFragmentView = inflater.inflate(R.layout.fragment_groups, container, false);
            mCreateGroup = groupFragmentView.findViewById(R.id.create_group_btn);
            mCreateGroup.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    requestNewGroup();
                }
            });

            initView();
            setLayoutManager();
            setAdapter();

            return groupFragmentView;
        }

        private void initView() {
            mGroupsRecyclerView = groupFragmentView.findViewById(R.id.groups_recycler_view);
        }

        private void setLayoutManager() {
            RecyclerView.LayoutManager layoutManager =
                    new LinearLayoutManager(getActivity());
            mGroupsRecyclerView.setLayoutManager(layoutManager);
        }

        private void setAdapter() {
            GroupsAdapter groupsAdapter = new GroupsAdapter(getContext(), groups);
            mGroupsRecyclerView.setAdapter(groupsAdapter);
        }

        private void requestNewGroup() {
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AlertDialog);
            builder.setTitle("Enter group name");

            final LinearLayout layout = new LinearLayout(groupFragmentView.getContext());
            layout.setOrientation(LinearLayout.VERTICAL);

            final CircleImageView mGroupImage = new CircleImageView(groupFragmentView.getContext());
            mGroupImage.setId(R.id.set_group_image);
            mGroupImage.setImageResource(R.drawable.group_image);

            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(200, 200);
            layout.addView(mGroupImage);

            final EditText mGroupName = new EditText(groupFragmentView.getContext());
            mGroupName.setId(R.id.set_group_name);
            mGroupName.setGravity(Gravity.CENTER);
            mGroupName.setHint("Group name");
            layout.addView(mGroupName);

            builder.setView(layout);

            builder.setPositiveButton("Create", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    EditText mGroupName = layout.findViewById(R.id.set_group_name);
                    String groupName = mGroupName.getText().toString();

                    if (TextUtils.isEmpty(groupName)) {
                        Toast.makeText(getActivity(), "Please write the name of the group", Toast.LENGTH_SHORT).show();
                    } else {
                        createNewGroup(groupName);
                    }
                }
            });

            builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    dialogInterface.cancel();
                }
            });

            AlertDialog mCreateGroupDialog = builder.create();
            mCreateGroupDialog.show();
            mCreateGroupDialog.getWindow().setLayout(900, 1200);
        }

        private void createNewGroup(String groupName) {
            Map<String, Object> groupData = new HashMap<String, Object>();
            groupData.put("name", groupName);
            groupData.put("adminID", currentUser.getUid());
            groupData.put("users", Arrays.asList(currentUser.getUid()));
            db.collection("users")
                    .document(currentUser.getUid())
                    .collection("groups")
                    .document(groupName)
                    .set(groupData)
                    .addOnSuccessListener(new OnSuccessListener<Void>() {
                        @Override
                        public void onSuccess(Void aVoid) {
                            Toast.makeText(getContext(), "Group created successfully", Toast.LENGTH_SHORT).show();
                            sendUserToGroupConversation();
                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            Log.w(MainActivity.TAG, "Error adding document", e);
                            Toast.makeText(getActivity(), "There was an error processing the request.",
                                    Toast.LENGTH_SHORT).show();
                        }
                    });
        }

        private void sendUserToGroupConversation() {
            // TODO
        }
    }

Group . java


    package com.example.snakemessenger;
    import java.util.List;

    class Group {
        private String name;
        private String adminID;
        private List<String> users;

        public Group() {

        }

        public Group(String name, String adminID, List<String> users) {
            this.name = name;
            this.adminID = adminID;
            this.users = users;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getAdminID() {
            return adminID;
        }

        public void setAdminID(String adminID) {
            this.adminID = adminID;
        }

        public List<String> getUsers() {
            return users;
        }

        public void setUsers(List<String> users) {
            this.users = users;
        }
    }

GroupsAdapter. java


    package com.example.snakemessenger;

    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;

    import androidx.annotation.NonNull;
    import androidx.recyclerview.widget.RecyclerView;

    import java.util.List;

    class GroupsAdapter extends RecyclerView.Adapter<GroupsViewHolder> {
        private Context mContext;
        private List<Group> mGroups;

        public GroupsAdapter(Context mContext, List<Group> mGroups) {
            this.mContext = mContext;
            this.mGroups = mGroups;
        }

        @NonNull
        @Override
        public GroupsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View itemView = LayoutInflater.from(mContext)
                    .inflate(R.layout.group_item, parent, false);

            return new GroupsViewHolder(itemView);
        }

        @Override
        public void onBindViewHolder(@NonNull GroupsViewHolder holder, int position) {
            Group currentGroup = mGroups.get(position);

            holder.getTextViewName().setText(currentGroup.getName());
            holder.getCircleImageViewGroup().setImageResource(R.drawable.group_image);
        }

        @Override
        public int getItemCount() {
            return mGroups.size();
        }
    }

GroupsViewHolder. java


    package com.example.snakemessenger;

    import android.view.View;
    import android.widget.TextView;

    import androidx.annotation.NonNull;
    import androidx.recyclerview.widget.RecyclerView;

    import de.hdodenhof.circleimageview.CircleImageView;

    class GroupsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private TextView mGroupName;
        private CircleImageView mGroupImage;

        public GroupsViewHolder(@NonNull View itemView) {
            super(itemView);

            mGroupName = itemView.findViewById(R.id.group_name_item);
            mGroupImage = itemView.findViewById(R.id.group_image_item);
            itemView.setOnClickListener(this);
        }

        public TextView getTextViewName() {
            return mGroupName;
        }

        public CircleImageView getCircleImageViewGroup() {
            return mGroupImage;
        }

        @Override
        public void onClick(View view) {
            // TODO
        }
    }

А вот файлы XML:

activity_main. 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"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        android:orientation="vertical">

        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/appBarLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <include
                android:id="@+id/main_page_toolbar"
                layout="@layout/app_bar_layout">
            </include>

            <com.google.android.material.tabs.TabLayout
                android:id="@+id/main_tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:tabIndicatorColor="#FFFFFF"
                app:tabMode="fixed"
                app:tabGravity="fill">
            </com.google.android.material.tabs.TabLayout>
        </com.google.android.material.appbar.AppBarLayout>

        <androidx.viewpager.widget.ViewPager
            android:id="@+id/main_tabs_pager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

app_bar_layout. xml


    <?xml version="1.0" encoding="utf-8"?>
    <androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/main_app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    </androidx.appcompat.widget.Toolbar>

фрагмент_групп. xml


    <?xml version="1.0" encoding="utf-8"?>
    <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        tools:context=".GroupsFragment">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/groups_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/create_group_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            app:fabSize="normal"
            android:backgroundTint="@color/colorPrimary"
            android:elevation="6dp"
            android:src="@drawable/ic_group_add_black_24dp"
            />
    </androidx.coordinatorlayout.widget.CoordinatorLayout>

group_item. 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="wrap_content"
        android:orientation="horizontal"
        android:padding="5dp">

        <de.hdodenhof.circleimageview.CircleImageView
            android:layout_gravity="start"
            android:id="@+id/group_image_item"
            android:layout_width="56dp"
            android:layout_height="56dp"
            android:src="@drawable/group_image"/>

        <LinearLayout
            android:layout_marginStart="20dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/group_name_item"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:textSize="25sp"
                android:textStyle="bold"
                android:text="Contact Name"/>
        </LinearLayout>
    </LinearLayout>

Прошу прощения за длинный пост, но я не знаю, как я могу объяснить проблему в меньшем количестве слов. Я предоставил вам весь код, потому что я не уверен, где проблема может быть. Как я уже сказал, список отображается только тогда, когда пользователь нажимает на FAB, чтобы создать новую группу, после нажатия на EditText, чтобы выбрать имя. Пожалуйста помоги. Спасибо!

Ответы [ 2 ]

0 голосов
/ 19 апреля 2020

Давайте начнем с этого:

вы видите этот метод:

setAdapter();

переместите его из этого метода:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
      ..........
      ..........

      setAdapter();

поместите его в get запрос к базе данных:

        groups = new ArrayList<>();
        db.collection("users")
                .document(currentUser.getUid())
                .collection("groups")
                .get()
                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        if (task.isSuccessful()) {
                            for (QueryDocumentSnapshot document : task.getResult()) {
                                groups.add(document.toObject(Group.class));


                            }
                            //here
                             setAdapter();

                            Toast.makeText(getActivity(), "Groups received successfully", Toast.LENGTH_SHORT).show();
                        } else {
                            Log.d(MainActivity.TAG, "Error getting document: ", task.getException());
                            Toast.makeText(getContext(), "Failed getting groups", Toast.LENGTH_SHORT).show();
                        }
                    }
                });

А затем переместите запрос get и все, что с ним, из onCreate в onCreateView именно там, где был setAdapter ().

0 голосов
/ 19 апреля 2020

На вашем GroupFragment. java class

пожалуйста, укажите макет для ориентации recylerview

измените это

RecyclerView.LayoutManager layoutManager =
                new LinearLayoutManager(getActivity());
        mGroupsRecyclerView.setLayoutManager(layoutManager);

на это

RecyclerView.LayoutManager layoutManager =
                new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL,false);
        mGroupsRecyclerView.setLayoutManager(layoutManager);

или вы измените это через XML

<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
...