السلام عليكم
اليوم سوف نقوم بعمل قائمة مثل الlistView ولكن بشكل شبكة و تسمى GridView وهي مفيدة جدا في التعامل مع الصور مثلا اذا كنت تريد عرض قائمة من الصور بشكل شبكة فالGridView هي الحل الأمثل .
تطبيق اليوم سوف يحتوي في الاكتيفيتي الرئيسية على Button و GridView والاكتيفيتي الأخرى سوف تحتوي على زر لفتح معرض الصور وبعد اختيار الصورة والعودة إلى الاكتيفيتي الرئيسية سوف تظهر الصورة في القائمة .
قم بإنشاء كلاس باسم Photos عن طريق New > JavaClass (سوف أشرح وظيفته لاحقا) :
public class Photos { Uri photo_uri; String Photo_name; public Uri getPhoto_uri() { return photo_uri; } public void setPhoto_uri(Uri photo_uri) { this.photo_uri = photo_uri; } public String getPhoto_name() { return Photo_name; } public void setPhoto_name(String photo_name) { Photo_name = photo_name; } }
xml custom_photo_gallery : وهذه سوف يتم عرضها في كل item في ال gridView مثل الليست فيو
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="1dp"> <ImageView android:layout_width="100dp" android:layout_height="100dp" android:id="@+id/mPhoto" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/mPhotoName" android:layout_marginTop="5dp" android:textSize="20sp" android:textColor="#5f0042" android:text="Image" /> </LinearLayout>
كود ال xml للاياوت الأكتيفيتي الرئيسية activity_grid_list_view :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="match_parent" tools:context="com.example.yaser.galleryexamples.GridListView"> <GridView android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="true" android:numColumns="auto_fit" android:id="@+id/photos_list" android:layout_below="@+id/add_photo" android:columnWidth="100dp" android:verticalSpacing="5dp" android:stretchMode="columnWidth"></GridView> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add photo" android:id="@+id/add_photo" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" /> </RelativeLayout>
الان في الاكتيفيتي الرئيسية سوف نضع كود فتح الأكتيفيتي الأخرى باستخدام دالة onActivityResult لكي نستقبل الصورة من الاكتفيتي الثانية ونضعها في القائمة ,ولقد قمنا بشرح onActivityResult في درس سابق ويمكنك مراجعته من هنا
قمت بتسمية الأكتيفيتي الرئيسية بGridListView :
public class GridListView extends AppCompatActivity { Button addPhoto; GridView photosGridList; ArrayList<Photos> photos = new ArrayList<>(); final int REQUEST_PHOTO = 1 ; PhotosAdapter photo_adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_grid_list_view); photosGridList = (GridView)findViewById(R.id.photos_list); photo_adapter = new PhotosAdapter(GridListView.this,photos); photosGridList.setAdapter(photo_adapter); addPhoto = (Button)findViewById(R.id.add_photo); addPhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivityForResult(new Intent(GridListView.this, SelectPhoto.class), REQUEST_PHOTO); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode == RESULT_OK ){ if(requestCode == REQUEST_PHOTO){ Photos photo = new Photos(); photo.setPhoto_uri(data.getData()); photo.setPhoto_name(data.getStringExtra("photo_name")); photos.add(photo); photo_adapter = new PhotosAdapter(GridListView.this,photos); photosGridList.setAdapter(photo_adapter); } }else{ Toast.makeText(GridListView.this,"error",Toast.LENGTH_SHORT).show(); } } class PhotosAdapter extends BaseAdapter{ List<Photos> mPhotos; Context mContext; public PhotosAdapter(Context context, ArrayList<Photos> photos){ this.mPhotos = photos; this.mContext = context; } @Override public int getCount() { return mPhotos.size(); } @Override public Object getItem(int position) { return mPhotos.get(position); } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView == null){ LayoutInflater inflater = LayoutInflater.from(GridListView.this); convertView = inflater.inflate(R.layout.custom_photo_gallery,null); holder = new ViewHolder(); holder.photo = (ImageView) convertView.findViewById(R.id.mPhoto); holder.photo_name = (TextView) convertView.findViewById(R.id.mPhotoName); convertView.setTag(holder); }else{ holder = (ViewHolder)convertView.getTag(); } Photos photo = mPhotos.get(position); Picasso.with(mContext).load(photo.getPhoto_uri()).resize(300,300).centerCrop().into(holder.photo); holder.photo_name.setText(photo.getPhoto_name()); return convertView; } class ViewHolder { ImageView photo; TextView photo_name; } }
في البداية عرفنا اوبجكت من gridView وقمنا باعطائه الاي دي الخاص به في الاون كريت بعدها قمنا بإنشاء اوبجكت من كلاس الأدابتر وأعطيناه في الباراميتر الأول Context والثاني ال ArrayList والتي تتكون من Objects من الكلاس Photos وكل اوبجكت واحد يمثل صورة واحدة ,بعدها نعين الادابتر لل GridView ,وفي حدث onClick للزر نقوم بفتح أكتيفيتي SelectPhoto ونستعمل startActivityForResult لكي نستقبل الصورة بعد اختيارها , في دالة onActivityResult نقوم بالبداية التأكد من الResultCode و requestCode كما تعلمنا سابقا ,, بعدها ننشئ اوبجكت من كلاس Photos ونعين ال photo_uri وال photo_name عن طريق دالة set وهي تقوم بتعيين المتغير كما وضعت في الباراميتر .. أي انه الآن أصبح لدينا اوبجكت يحتوي علىUri الصورة واسم الصورة وبعدها نقوم بإضافته إلى ال ArrayList .
قم بإنشاء اكتيفيتي باسم SelectPhoto (أو أي اسم اخر ولكن لا تنسى تغييره عند استدعاء الاكتيفيتي )
SelectPhoto :
public class SelectPhoto extends AppCompatActivity { Button upload,OK; ImageView uploadedPhoto; Uri photo_uri; EditText photoName; String name; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_select_photo); photoName = (EditText)findViewById(R.id.photoname); OK = (Button)findViewById(R.id.ok); OK.setVisibility(View.GONE); upload = (Button)findViewById(R.id.uploadPhoto); uploadedPhoto = (ImageView)findViewById(R.id.uploadedPhoto); upload.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent i = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(Intent.createChooser(i,"select your photo"),1); } }); OK.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent photo = new Intent(); photo.setData(photo_uri); if(!photoName.getText().toString().equals("")) { name = photoName.getText().toString(); }else{ name = ""; } photo.putExtra("photo_name", name); setResult(RESULT_OK, photo); finish(); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode == 1 && resultCode == RESULT_OK){ photo_uri = data.getData(); if(photo_uri.getPath() != null) { Picasso.with(Gallery_main.this).load(photo_uri).resize(300, 300).centerCrop().into(uploadedPhoto); OK.setVisibility(View.VISIBLE); } } }
كود xml :
<LinearLayout 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:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context=".Gallery_main" android:weightSum="1"> <TextView android:text="@string/help1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="upload " android:id="@+id/uploadPhoto" android:layout_below="@+id/textView" android:layout_centerHorizontal="true" android:layout_gravity="center_horizontal" /> <ImageView android:layout_width="150dp" android:layout_height="150dp" android:id="@+id/uploadedPhoto" android:layout_below="@+id/textView" android:layout_toStartOf="@+id/uploadPhoto" android:layout_toLeftOf="@+id/uploadPhoto" android:layout_alignBottom="@+id/uploadPhoto" android:layout_gravity="center_horizontal" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/photoname" android:layout_gravity="center_horizontal" android:hint="اكتب هنا أي اسم للصورة" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="OK" android:id="@+id/ok" android:layout_gravity="center_horizontal" /> </LinearLayout>
اللاياوت تحتوي على زرين وصورة و editText عند الضغط على الزر الأول يفتح معرض الصور وبعدها في دالة onActivityResult نقوم بأخذ ال Uri من ال data وباستخدام مكتبة بيكاسو نعين الصورة لل ImageView وعند الضغط على الزر الثاني ننشئ انتنت جديد ونعين الداتا الخاصة به عن طريق setData لنضع ال Uri الخاص بالصورة التي اختارها المستخدم ثم نأخذ ما كتب في ال EditText ونستخدم putExtra لتمرير قيمة ال Text إلى الأكتيفيتي الأولى
دالة setResult نضع فيها RESULT_OK و الانتنت الذي نريد تمريره بعدها بدالة finish ننهي هذه الاكتيفيتي للعودة للاكتفيتي السابقة .
نعود لonActivityResult في GridListView وكما ترى data.getData هي ال uri الذي وضعناه في دالة setData في اكتيفيتي SelectPhoto و photo_name هو الkey لقيمة ما كتب في ال EditText, بعد اضافة الأوبجكت للArrayList ننشئ اوبجكت للأدابتر وسوف يقوم الأدابتر بعرض ال objects الموجودة في ال ArrayList على شكل شبكة في ال GridView
ما يهم في كلاس الأدابتر هو دالة getView في البداية نقوم باستخدام ال inflater بتعيين اللاياوت التي تظهر في كل عنصر وهي custom_photo_gallery أي أن كل عنصر سوف يحتوي على صورة و textView بعدها ننشئ اوبجكت من كلاس ViewHolder وهو يحتوي على ال ImageView ,, TextView ثم نقوم بإعطائهما ال Id ,
دالة setTag تأخذ باراميتر واحد يمكن أن يكون أي اوبجكت وبما أننا أعطيناها ال holder فسيصبح convertView يحتوي على id الخاص بال views لذلك لن نحتاج إلى انشاء اوبجكت جديد من كلاس ViewHolder في كل مرة نضيف صورة , لأن if لن تنفذ إلا في المرة الأولى من استدعاء getView وفي داخل ال else نقوم بتعيين ال holder إلى getTag وسترجع هذه الدالة holder الذي يحتوي على id لذلك لن نحتاج إلى إعادة تعيين ال id للصورة والتيكست فيو في كل مرة تستدعى getView وذلك سيسرع عملية عرض الصور ,
(Photos photo = mPhotos.get(position
mPhotos هي ArrayList وتحتوي على objects من نوع Photos ولكي نحصل على الصورة الحالية ننشئ اوبجكت من Photos ونستدعي دالة get ثم نمرر ال position لل row (يعني موقع الصورة في القائمة ) ليصبح الآن photo يحتوي على معلومات الصورة
قم بتشغيل البرنامج الآن واختر أي صورة من الاستديو لتجدها في القائمة , طبعا اذا خرجت من البرنامج ستختفي كل الصور وذلك بسبب أننا لم نحفظ ال ArrayList , ولكن سنتعلم كيفية حفظها في درس اخر إن شاءالله
أتمنى أنكم استفدتم .. ترقبوا الدروس القادمة