В настоящее время я работаю над 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, чтобы выбрать имя. Пожалуйста помоги. Спасибо!