簡體   English   中英

片段內的 RecyclerView 未正確顯示

[英]RecyclerView inside Fragment not showing properly

我目前正在開發一個類似 WhatsApp 的 Android 應用程序,最近遇到了一個讓我頭疼的問題。 我正在嘗試在屬於 TabLayout 的 Fragment 內創建一個 RecyclerView。 基本上,我有 3 個選項卡,每個選項卡都包含一個片段。 第一個選項卡用於用戶的對話,第二個用於組,第三個用於聯系人。 每個選項卡都應包含一個 RecyclerView,它根據 Firebase 身份驗證提供的當前用戶 ID 顯示來自 Firebase Firestore 的數據。 我認為的問題在於,除了 RecyclerView 之外的 Fragment 內部還有一個 FloatingActionButton。 此按鈕在每個 Fragment 中用於執行發送新消息或創建新組或添加新聯系人等操作。 單擊時,假設在組選項卡中,FAB 顯示一個 AlertDialog 要求用戶填寫組名稱,然后 select “創建”,組被創建並添加到數據庫中。 現在,問題是當用戶登錄應用程序並訪問組選項卡時,他的組不會顯示,但是如果用戶單擊 FAB,則會出現 AlertDialog 並且如果用戶單擊 EditText 以選擇名稱對於一個新組,突然用戶的組顯示在 Fragment 內。 我需要一些幫助,我對 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();
        }
    }

標簽AccessorAdapter.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
        }
    }

組.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;
        }
    }

組適配器.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();
        }
    }

組ViewHolder.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 以選擇名稱后,才會顯示該列表。 請幫忙。 謝謝!

在您的 GroupFragment.java class

請布局提供recyclerview的方向

改變這個

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" />

讓我們從這樣做開始:

你看到這個方法了嗎:

setAdapter();

從這個方法中移動它:

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

      setAdapter();

把它放在對數據庫的獲取請求中:

        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() 所在的位置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM