تحديث جميع البيانات لمستخدمي التطبيق وتصميم صفحة للمستخدمين
في هذا الدرس سوف نقوم بتصميم صفحة تحتوي على قائمة بها جميع مستخدمي التطبيق لكي تتمكن من اضافتهم والتحدث معهم , وايضا سوف نتعرف على كيفية عرض جميع مستخدمي التطبيق للجميع لكي تتمكن من اضافتهم وبدء محادثة جديدة معهم اذا كنت ترغب بذلك .
أصبح الاقبال على ظيفة android developer كبير جدا في هذه الايام وذلك لان مجال ال developing اصبح مطور بكثره في مختلف الدول سواء العربيه او الاجنبيه وليس فقط android developer بل هناك ios developer وهو الشخص المتخصص في تطوير تطبيقات نظام ios الخاص بشركة apple وفي الغالب يكون راتب الios developer اكبر في بعض الاحيان وذلك بسبب قلة المبرمجين في نظام ios واصبحت الكثير من القنوات والمواقع على منصة YouTube تختص بشروحات ios وايضا android ويعد موقعنا واحد من اكبر المواقع المختصه في هذا المجال ومساعدة المبرمجين في التعلم .
اثناء تعلمك للdevelopment يفضل ان يكون لديك ورقه وقلم لتدوين كل ما تحتاجه وتتعلمه ولكن نحن في موقعنا نقوم بتوفير لك كل ما تريد دون الحاجه الى الورقه والقلم فقط كل ما تحتاجه هو التطبيق على الدروس التي نضعها وحسب لكي تفهم كيف يعمل الكود وايضا تكتسب خبره من كثرة كتابة الcode, ودائما حاول ان تعتمد بشكل كبير على انماط التصميم في البرجخ مثل mvvm وهو اشهر نمط حاليا والكثير من الشركات تطلبه ولك لاهميته التنظميه في كتابة الكود مما يجعل من اي شخص اخر قادر على التعديل على الكود الخاص بك ويعرف كل شخص عمله ui , back , developer يكون كل شخص قادر على معرفة وظيفته بالتحديد
تصميم recyclerview تحتوي على بيانات المستخدمين للتطبيق
سوف نقوم اولا بتصميم شكل recyclerview لبيانات المستخدمين وبكل بساطة نريد ان نعرض الاسم الخاص بالمستخدم وايضا الاميل الخاص به والصورة الخاصه به ولذلك سوف نقوم بعمل تصميم يحتوي على هذة المواصفات فقط داخل recyclerview كما يظهر .
item_container_user.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/_8sdp">
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/imageProfile"
android:layout_width="@dimen/_35sdp"
android:layout_height="@dimen/_35sdp"
android:background="@drawable/background_image"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:riv_corner_radius="@dimen/_15sdp"
app:riv_oval="true" />
<TextView
android:id="@+id/text_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/_8sdp"
android:layout_marginEnd="@dimen/_8sdp"
android:ellipsize="end"
android:maxLines="1"
android:text="Chat app"
android:textColor="@color/primary_text"
android:textSize="@dimen/_13ssp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/imageProfile"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textEmail"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/_8sdp"
android:layout_marginTop="@dimen/_5sdp"
android:layout_marginEnd="@dimen/_8sdp"
android:ellipsize="end"
android:maxLines="1"
android:text="email@gmail.com"
android:textColor="@color/secondary_text"
android:textSize="@dimen/_10ssp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/imageProfile"
app:layout_constraintTop_toBottomOf="@id/text_name" />
</androidx.constraintlayout.widget.ConstraintLayout>
تصميم صفحة البحث عن مستخدمي التطبيق
سوف نقوم هنا بعمل صفحة جديدة تحتوي على مكان لتحديد مستخدمي التطبيق مثال على ذلك , يظهر هنا كل مستخدمي التطبيق بنفس الشكل الذي قمنا به بالاعلى ويمكنك النقر على اي مستخدم منهم وسوف ينقلك الى صفحة المحادثة معه لكي تتمكن من بدء محادثة مع المستخدم .
activity_user
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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:background="@color/primary"
android:animateLayoutChanges="true"
tools:context=".activities.UserActivity">
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/imageBack"
android:background="@drawable/background_icon"
android:src="@drawable/ic_back"
android:padding="@dimen/_6sdp"
android:layout_margin="@dimen/_14sdp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_width="@dimen/_30sdp"
android:layout_height="@dimen/_30sdp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/select_image"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="@id/imageBack"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/imageBack"
android:textStyle="bold" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="@dimen/_12sdp"
android:background="@drawable/background_content_bottom"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/imageBack" >
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/_20sdp"
android:overScrollMode="never"
android:visibility="gone"
android:orientation="vertical"
android:clipToPadding="false"
/>
<ProgressBar
android:id="@+id/progress"
android:layout_gravity="center"
android:layout_width="@dimen/_25sdp"
android:layout_height="@dimen/_25sdp"/>
<TextView
android:id="@+id/textErrorMessage"
android:layout_gravity="center"
android:layout_marginStart="@dimen/_24sdp"
android:layout_marginEnd="@dimen/_24sdp"
android:gravity="center"
android:textColor="@color/error"
android:textSize="@dimen/_12ssp"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
تصميم background_content_bottom
سوف نقوم بعمل الشكل الابيض وهو عبارة عن التصميم الذي قمنا به بالاعلى وسوف يحتوي على المحتويات الخاصه بالمستخدمين .
background
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/white" />
<corners
android:topRightRadius="@dimen/_32sdp"
android:topLeftRadius="@dimen/_32sdp" />
</shape>
عمل كلاس لتمرير البيانات
في طبيعة الحال نريد تمرير اسم المستخدم والبريد الصورة والتوكن اذا اردت وسوف نقوم بعمل هذة الخطوات كما يظهر بالصورة لكي نتمكن من تمريرهم .
User.class
public class User implements Serializable {
public String name , image , email , token ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
عمل Adapter لل recyclerView باستخدام ViewBinding
في هذة المرحلة سوف نقوم بعمل الخاص بالrecyclerView لكي نستطيع تكرار الrecyclerView اكثر من مره على حسب عدد المستخدمين ولقد شرحنا الrecyclerView في كثير من الدروس .
AdapterUser.class
public class AdapterUser extends RecyclerView.Adapter<AdapterUser.Holder> {
private List<User> users;
public AdapterUser(List<User> users) {
this.users = users;
}
private Bitmap getUserImage(String encodeImage) {
byte[] bytes = Base64.decode(encodeImage , Base64.DEFAULT);
return BitmapFactory.decodeByteArray(bytes,0,bytes.length);
}
@NonNull
@Override
public Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new Holder(ItemContainerUserBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
@Override
public void onBindViewHolder(@NonNull Holder holder, int position) {
holder.setData(users.get(position));
}
@Override
public int getItemCount() {
return users.size();
}
class Holder extends RecyclerView.ViewHolder {
ItemContainerUserBinding binding;
public Holder(@NonNull ItemContainerUserBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
// define all id in ItemContainerUser .
void setData(User user) {
binding.textEmail.setText(user.email);
binding.textName.setText(user.name);
binding.imageProfile.setImageBitmap(getUserImage(user.image));
}
}
}
استخدام UserActivity لعرض بيانات جميع مستخدمي عند الدخول اليها
في هذة الصفحة سوف نقوم بكتابة methode للحصول على جميع المستخدمين الذين قاموا بالتسجل في هذا التطبيق عن طريق خدمة firebase وايضا سوف نقوم بفلتره البيانات التي نريد الحصول عليها ونريد فقط الحصول على الاسم والبريد والصورة والتوكن وهذا سوف نحتاجه بشكل اكبر عندما نريد ارسال رسائل له تظهر في الnotification
UserActivity.class
public class UserActivity extends AppCompatActivity {
private ActivityUserBinding binding;
private PreferenceManager preferenceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityUserBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
preferenceManager = new PreferenceManager(getApplicationContext());
getUsers();
setListeners();
}
private void setListeners(){
binding.imageBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
}
// عرض كل الاشخاص الذين قامو بالتسجيل في التطبيق داخل recyclerView
private void getUsers() {
loading(true);
FirebaseFirestore firestore = FirebaseFirestore.getInstance();
firestore.collection(Constants.KEY_COLLECTION_USERS).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
loading(false);
String currentUserId = preferenceManager.getString(Constants.KEY_USER_ID);
if (task.isSuccessful() && task.getResult() != null) {
List<User> users = new ArrayList<>();
for (QueryDocumentSnapshot queryDocumentSnapshot : task.getResult()) {
if (currentUserId.equals(queryDocumentSnapshot.getId())) {
continue;
}
User user = new User();
user.name = queryDocumentSnapshot.getString(Constants.KEY_NAME);
user.email = queryDocumentSnapshot.getString(Constants.KEY_EMAIL);
user.image = queryDocumentSnapshot.getString(Constants.KEY_IMAGE);
user.token = queryDocumentSnapshot.getString(Constants.KEY_FCM_TOKEN);
users.add(user);
}
if (users.size() > 0) {
AdapterUser adapterUser = new AdapterUser(users);
binding.recyclerview.setAdapter(adapterUser);
binding.recyclerview.setLayoutManager(new LinearLayoutManager(UserActivity.this));
binding.recyclerview.setVisibility(View.VISIBLE);
} else {
showErrorMessage();
}
} else {
showErrorMessage();
}
}
});
}
private void showErrorMessage() {
binding.textErrorMessage.setText(String.format("%s" , getString(R.string.No_User_available)));
binding.textErrorMessage.setVisibility(View.VISIBLE);
}
protected void loading (Boolean isLoading) {
if (isLoading) {
binding.progress.setVisibility(View.VISIBLE);
} else {
binding.progress.setVisibility(View.INVISIBLE);
}
}
}
التعديل على صفحة activity_main واضافة FloatingActionButton لاضافة مستخدمين
سوف نقوم بالتعديل على activity_main ونضيف بداخلها فقط FloatingActionButton وهو عباره عن زر دائري يظهر في زاوية التطبيق لكي يتمكن المستخدم من النقر عليه والتحويل الى صفحة جديدة بها مستخدمي التطبيق .
activity_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:animateLayoutChanges="true"
android:background="@color/primary"
tools:context=".activities.MainActivity">
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/imageProfile"
android:layout_width="@dimen/_30sdp"
android:layout_height="@dimen/_30sdp"
android:layout_margin="@dimen/_16sdp"
android:scaleType="centerCrop"
app:riv_corner_radius="@dimen/_16sdp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image_signOut"
android:layout_width="@dimen/_30sdp"
android:layout_height="@dimen/_30sdp"
android:layout_margin="@dimen/_16sdp"
android:padding="@dimen/_6sdp"
android:src="@drawable/ic_logout"
android:background="@drawable/background_icon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/white"
android:textStyle="bold"
android:textSize="@dimen/_14ssp"
android:layout_marginEnd="@dimen/_8sdp"
android:layout_marginStart="@dimen/_8sdp"
app:layout_constraintBottom_toBottomOf="@id/imageProfile"
app:layout_constraintEnd_toStartOf="@id/image_signOut"
app:layout_constraintStart_toEndOf="@id/imageProfile"
app:layout_constraintTop_toTopOf="@id/imageProfile" />
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="@dimen/_25sdp"
android:layout_height="@dimen/_25sdp"
android:layout_gravity="center"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:background="@drawable/background_content_bottom"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/imageProfile"
android:layout_marginTop="@dimen/_16sdp"
android:layout_width="match_parent"
android:layout_height="0dp" >
</FrameLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fa_new_chat"
android:layout_width="wrap_content"
android:layout_margin="@dimen/_18sdp"
app:layout_constraintEnd_toEndOf="parent"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_add"
android:backgroundTint="@color/primary"
app:layout_constraintBottom_toBottomOf="parent"
android:tint="@color/white"
android:layout_height="wrap_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
عمل انتقال من MainActivity الى UserActivity
في النهاية سوف نقوم بعمل الكود الخاص بالFloatingActionButton وهو بكل بساطة ينقل المستخدم من الموقع الحالي الى الصفحة الخاصه بمستخدمي التطبيق لكي يتمكن من اضافة الاشخاص الذي يستخدمون التطبيق .
MainActivity
private void listener() {
binding.imageSignOut.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loading(true);
sign_out();
}
});
binding.faNewChat.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext() , UserActivity.class));
finish();
}
});
}