نمایش تعدادی عکس، با استفاده از GridView ، در برنامه نویسی اندروید
در این مبحث قصد داریم که چگونگی نمایش تعدادی عکس با استفاده از GridView را شرح بدهیم. نتیجه به صورت زیر می باشد :


و با چرخاندن گوشی، خروجی به صورت زیر است (در حالت افقی) :

همچنین با اشاره کاربر بر روی هر یک از item های موجود در GridView ، یک پیام بر اساس شماره item به کاربر نمایش داده می شود (یک پیام کوتاه چند ثانیه ای با استفاده از روش Toast). این مورد را برای این منظور به پروژه اندروید افزوده ایم که متوجه شوید چگونه یک سری کد را تعیین کنید که بعد از اشاره کاربر بر روی هر item از GridView ، اجرا شوند :

فایل پروژه اندروید و همچنین فایل apk ساخته شده از آن را می توانید از انتهای مبحث دانلود نمایید.
کدهای این مبحث را قبلا در برنامه اندرویدی با نام ((کاریکاتور)) به کار برده بودم. در آن زمان یادم است که برای نمایش عکس ها با استفاده از GridView مشکل داشتم زیرا در گوشی های با صفحه نمایش های با اندازه مختلف، عکس ها بر روی یکدیگر قرار می گرفتند و یا به صورتی بودند که مد نظر من نبود. البته در آن زمان، می دانستم که باید چندین فایل xml برای صفحه نمایش های با اندازه مختلف (4 دسته) بسازم ( آموزش شماره 239 )، اما این مورد نیز کمکی نکرد، بنابراین از این روش استفاده نکردم و ترجیح دادم کدها را به گونه ای بنویسم که تنها یک فایل xml کافی باشد و بر اساس تنظیم پارامترهای مربوط به اندازه عنصرها، آن را به صورت مناسب برای تمامی صفحه های نمایش با اندازه های مختلف، در بیاورم. بنابراین ممکن است که کدهای استفاده شده برای GridView ، کمی با کدهای سایر سایت ها متفاوت باشد. اما به هر حال از هر کدی که استفاده می کنید، به نکته مهم زیر توجه کنید :
((GridView یکی از عناصری است که اگر کدهای آن را به درستی تعیین نکنید، به شدت به اندازه صفحه نمایش حساس می باشد و ممکن است که طراحی شما، برای برخی صفحه های نمایش با اندازه های مختلف، خراب شود. پس حتما GridView را در صفحه نمایش های با اندازه مختلف آزمایش کنید و نتیجه را ببینید)).
نام پروژه اندروید را برابر GridViewImage انتخاب کرده ایم (نام package برابر com.kelidestan.gridviewimage انتخاب شده است. نام Activity اصلی را برابر MainActivity.java انتخاب کرده ایم و فایل xml متناظر آن را هم برابر activity_main.xml قرار داده ایم) :

قبل از هر چیز، در پروژه اندروید، به 30 عدد عکس نیاز داریم که آنها را در پوشه drawable-hdpi کپی کرده ایم :

فایل activity_main.xml ، فایل xml متناظر برای Activity اصلی برنامه است (البته تنها یک Activity داریم) که ظاهر گرافیکی آن را تعیین می کند :

کدهای فایل activity_main.xml را به صورت زیر می نویسیم :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<GridView
android:id="@+id/gridview"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:numColumns="3"
android:columnWidth="150dp"
android:horizontalSpacing="10dp"
android:verticalSpacing="10dp"
android:gravity="center"
>
</GridView>
</LinearLayout>
همان طور که مشاهده می کنید، یک عنصر GridView تعریف کرده ایم. با استفاده از مشخصه numColumns ، تعداد ستون های GridView را برابر 3 ستون قرار داده ایم.
ظاهر گرافیکی فایل activity_main.xml به صورت زیر می باشد (در برنامه eclipse) :

اکنون به سراغ Activity اصلی برنامه اندروید می رویم که کدهای آن در فایل MainActivity.java نوشته شده اند :

کدهای فایل MainActivity.java را به صورت زیر می نویسیم :
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
public Integer[] myImages = {
R.drawable.image_1,
R.drawable.image_2,
R.drawable.image_3,
R.drawable.image_4,
R.drawable.image_5,
R.drawable.image_6,
R.drawable.image_7,
R.drawable.image_8,
R.drawable.image_9,
R.drawable.image_10,
R.drawable.image_11,
R.drawable.image_12,
R.drawable.image_13,
R.drawable.image_14,
R.drawable.image_15,
R.drawable.image_16,
R.drawable.image_17,
R.drawable.image_18,
R.drawable.image_19,
R.drawable.image_20,
R.drawable.image_21,
R.drawable.image_22,
R.drawable.image_23,
R.drawable.image_24,
R.drawable.image_25,
R.drawable.image_26,
R.drawable.image_27,
R.drawable.image_28,
R.drawable.image_29,
R.drawable.image_30
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
String position_string = "you pressed the item number " + String.valueOf(position+1) + " in GridView";
Toast.makeText(getApplicationContext(), position_string, Toast.LENGTH_SHORT).show();
}
});
}
public static int convertDpToPixels(float dp, Context context){
Resources resources = context.getResources();
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp,
resources.getDisplayMetrics()
);
}
public class ImageAdapter extends BaseAdapter{
private Context mContext;
public int getCount() {
return myImages.length;
}
public Object getItem(int position) {
return myImages[position];
}
public long getItemId(int position) {
return 0;
}
public ImageAdapter(Context c) {
mContext = c;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null){
imageView = new ImageView(mContext);
float w = 100;
float h = 100;
int width_pixel = convertDpToPixels(w,MainActivity.this);
int height_pixel = convertDpToPixels(h,MainActivity.this);
imageView.setLayoutParams(new GridView.LayoutParams(width_pixel, height_pixel));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
imageView.setMaxHeight(60);
}else{
imageView = (ImageView) convertView;
}
imageView.setBackgroundResource(myImages[position]);
return imageView;
}
}
}
اکنون کدها را شرح می دهیم :
کدهای زیر را در نظر بگیرید :
R.drawable.image_1,
R.drawable.image_2,
R.drawable.image_3,
R.drawable.image_4,
R.drawable.image_5,
R.drawable.image_6,
R.drawable.image_7,
R.drawable.image_8,
R.drawable.image_9,
R.drawable.image_10,
R.drawable.image_11,
R.drawable.image_12,
R.drawable.image_13,
R.drawable.image_14,
R.drawable.image_15,
R.drawable.image_16,
R.drawable.image_17,
R.drawable.image_18,
R.drawable.image_19,
R.drawable.image_20,
R.drawable.image_21,
R.drawable.image_22,
R.drawable.image_23,
R.drawable.image_24,
R.drawable.image_25,
R.drawable.image_26,
R.drawable.image_27,
R.drawable.image_28,
R.drawable.image_29,
R.drawable.image_30
};
با کدهای بالا، یک آرایه (Array) از جنس Integer و با نام myImages تعریف کرده ایم که در آن، مشخصات (resource Id ، یا به اختصار : resId) مربوط به عکس هایی که می خواهیم در GridView نمایش داده شوند، نوشته شده است (برای ارجاع به عکس ها).
در روش onCreate ، کدهای زیر برای GridView نوشته شده است (کدهای روش onCreate ، به محض اجرای Activity ، اجرا خواهند شد) :
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
String position_string = "you pressed the item number " + String.valueOf(position+1) + " in GridView";
Toast.makeText(getApplicationContext(), position_string, Toast.LENGTH_SHORT).show();
}
});
ابتدا با کد زیر، GridView را بر اساس id آن شناسایی کرده ایم :
سپس یک Adapter را برای GridView تعیین کرده ایم :
دقت کنید که در کد بالا، یک شیء (object) از کلاس (class) با نام ImageAdapter ساخته ایم و آن را با استفاده از روش setAdapter ، به عنوان Adapter برای GridView تعیین کرده ایم. همان طور که می دانید، در ساخت یک شیء از یک کلاس، از کلمه new استفاده می شود و این مورد، نکته ای ساده برای تشخیص ساختن یک شیء از یک کلاس می باشد. کلاس ImageAdapter را هم در انتهای کدهای همین Activity تعریف کرده ایم (بعدا کدهای آن را شرح می دهیم).
با کدهای زیر تعیین کرده ایم که اگر کاربر بر روی یک از item های (خانه های) GridView اشاره کرد، چه کدهایی اجرا شوند (برای این منظور، روش setOnItemClickListener را به کار برده ایم) :
@Override
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
String position_string = "you pressed the item number " + String.valueOf(position+1) + " in GridView";
Toast.makeText(getApplicationContext(), position_string, Toast.LENGTH_SHORT).show();
}
});
پس بر اساس کدهای بالا، با اشاره کاربر بر روی یک item از GridView ، کدهای زیر اجرا خواهد شد (کدهایی برای نمایش یک پیام کوتاه به کاربر، که در آن، شماره item اشاره شده را اعلام می کنیم) :
Toast.makeText(getApplicationContext(), position_string, Toast.LENGTH_SHORT).show();
دقت کنید که در متغیر position ، شماره مربوط به item ای را که بر روی آن اشاره شده، ذخیره شده است. البته مقدار position از صفر شروع می شود (یعنی item اول را برابر 0 در نظر می گیرد) و بنابراین یک واحد به آن اضافه کرده ایم. برای نمایش پیام، از روش Toast استفاده کرده ایم که یک پیام را در چند ثانیه نمایش می دهد.
در کدهای Activity ، یک تابع با نام convertDpToPixels تعریف کرده ایم ( آموزش شماره 283 ) :
Resources resources = context.getResources();
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp,
resources.getDisplayMetrics()
);
}
این تابع، یک مقدار را بر اساس واحد dp دریافت می کند و سپس مقدار متناظر با آن را بر حسب تعداد پیکسل (pixels) بر می گرداند. اگر یادتان باشد، در ابتدای مبحث گفتم که کدها را به گونه ای نوشته ام که بر روی صفحه نمایش های با اندازه مختلف، مشکلی نداشته باشد و به طور صحیح نمایش داده شود و نیازی هم به ساخت چند فایل xml برای صفحه نمایش های با اندازه های مختلف نباشد. یکی از مواردی که برای رسیدن به این هدف نیاز داریم، استفاده از همین تابع است زیرا در بخشی از کدها، نیاز داریم که واحد را به صورت پیکسل (pixels) داشته باشیم.
و اما بخش آخر کدها که همان ImageAdapter است (Adapter تعیین شده برای GridView) :
private Context mContext;
public int getCount() {
return myImages.length;
}
public Object getItem(int position) {
return myImages[position];
}
public long getItemId(int position) {
return 0;
}
public ImageAdapter(Context c) {
mContext = c;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null){
imageView = new ImageView(mContext);
float w = 100;
float h = 100;
int width_pixel = convertDpToPixels(w,MainActivity.this);
int height_pixel = convertDpToPixels(h,MainActivity.this);
imageView.setLayoutParams(new GridView.LayoutParams(width_pixel, height_pixel));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
imageView.setMaxHeight(60);
}else{
imageView = (ImageView) convertView;
}
imageView.setBackgroundResource(myImages[position]);
return imageView;
}
}
همان طور که قبلا گفتیم، یک شئ (object) از این کلاس (class) ساختیم و آن را به عنوان Adapter برای GridView تعیین کردیم. Adapter برای ساخت GridView به کار خواهد رفت و item های آن را می سازد و ویژگی ها و منابع مربوط به item ها در میان کدهای Adapter (یعنی همین Adapter با نام ImageAdapter) نوشته شده است.
چون قصد داریم که در هر item ، یک عکس نمایش داده شود، بنابراین در هر item ، باید یک ImageView داشته باشیم که در آن، عکس نمایش داده شود. بنابراین کد زیر را می نویسیم تا در هر item ، یک ImageView ساخته شود (ساخت یک شیء از کلاس ImageView) :
در کدهای زیر، با استفاده از همان تابع convertDpToPixels ، دو مقدار ارتفاع و عرض (برای تعیین اندازه های ImageView) را بر حسب پیکسل به دست آورده ایم (یعنی یک مقدار را بر حسب dp تعیین کرده ایم و چون dp در گوشی های با صفحه نمایش مختلف، متفاوت است، می خواهیم مقادیر مورد نظرمان را بر حسب پیکسل به دست آوریم) :
float h = 100;
int width_pixel = convertDpToPixels(w,MainActivity.this);
int height_pixel = convertDpToPixels(h,MainActivity.this);
شاید کاری که انجام می دهیم، برایتان کمی مبهم باشد. در واقع، ما ابتدا واحد را بر حسب dp بیان کرده ایم و چون واحد dp یک واحد نسبی است و بر اساس اندازه صفحه نمایش گوشی تعیین می شود، بنابراین مقادیر w و h به طور مستقل از اندازه صفحه نمایش ذخیره شده اند. اکنون چون می خواهیم این دو مقدار را برای روشی به کار ببریم که واحد را بر حسب پیکسل (pixels) دریافت می کند، پس آن دو را به واحد پیکسل (pixels) تبدیل می کنیم.
سپس ویژگی های مربوط به اندازه و پارامترهای ظاهری ImageView را مشخص کرده ایم :
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
imageView.setMaxHeight(60);
در کل، می توانید این موارد (و همچنین مقادیر h و w و پارامترهای تعیین شده در فایل xml) را مطابق سلیقه خود تغییر بدهید، اما حتما نتیجه را بر روی گوشی های با صفحه نمایش های با اندازه مختلف، آزمایش کنید.
در آخر، تعیین کرده ایم که بر اساس مقدار ذخیره شده در متغیر position که متناظر با شماره مربوط به item است، یکی از عکس هایی که در آرایه myImages ، مقدار مربوط به resource ID آن را ذکر کرده ایم، در ImageView نمایش داده شود :
معمولا در برنامه های اندرویدی که ممکن است از نظر حافظه (memory)، مشکلی به وجود بیاید (مثلا یک force close ایجاد شده و برنامه به اجبار بسته شود)، در فایل AndroidManifest.xml ، یک مشخصه با نام largeHeap را باید برابر true قرار بدهیم تا این مشکل، تا حدودی رفع شود. من برای مواردی که احتمالا تعداد عکس ها زیاد است، توصیه می کنم که این مشخصه نیز در پروژه اندروید ذکر شود. برای این منظور، فایل AndroidManifest.xml از پروژه اندروید را باز می کنیم :

اکنون باید کد زیر را به تگ application اضافه کنیم :
برای اینکه موقعیت آن را به درستی متوجه شوید، کل کدهای فایل AndroidManifest.xml از پروژه اندروید را در زیر نمایش داده ام :
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.kelidestan.gridviewimage"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:largeHeap="true"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.kelidestan.gridviewimage.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
ساخت پروژه اندروید تمام شد و اکنون می توانیم آن را تست کنیم :


و با چرخاندن گوشی، خروجی به صورت زیر است (در حالت افقی) :

همچنین با اشاره کاربر بر روی هر یک از item های موجود در GridView ، یک پیام بر اساس شماره item به کاربر نمایش داده می شود :

فایل های پروژه اندروید را می توانید از لینک های زیر دریافت کنید :


سلام خسته نباشد
میخواستم ب\رسم چطور میشه وقتی رو یکی از عکسا که کیلک کردم به یه اکتویتی دیگه بره و عکس تمام صحفه بشه و یه متنی زیر اون عکس نوشت ممنون میشم راهنمایی بکنین


سلام.
در همین مبحث شرح دادیم که چگونه کدهایی بنویسیم که با اشاره بر روی هر item ، آن کدها اجرا شوند.
بنابراین اکنون تنها باید آن کدها را به این صورت تغییر بدهید که به Activity دیگری برویم و شماره متناظر با عکس نیز به آن Activity ارسال شود (). در Activity ، یک ImageView و یک TextView را تعریف می کنیم و بر اساس شماره مربوط به عکس که دریافت کرده ایم، عکس و متن مربوط را در آن دو عنصر نمایش می دهیم.


سلام. چطور متونیم گرید ویو رو به صورت افقی تغییر صفحه بدیم. مثل تقویمی که با همه اطلاعاتش از یک ماه به ماه دیگه بره؟
خاصیت viewpager را آشنا هستم ولی برای گرید ویو عمل نمیکند.


من یک سوال دارم.در این کد شما از یک ارایه integer ای استفاده کردین که میره و پوشه عکس ها ایدی عکس رو به عنوان ورودی میگیره.من میخوام این عکس ها از یک پوشه از حافظه اکسترنال اورده بشه و در این لیست ویو نمایش داده بشه..حالا چیکار کنم.همین یه تیکه کد رو میشه به من بگید و در کلاسی که ارایه رو استفاده کردید جایگزین کنید؟


سلام.
به جای آرایه مورد نظر، باید یک آرایه بسازید که از نوع String باشد و نام عکس ها را در آرایه می نویسید (یا مثلا با کدهایی، نام فایل های موجود در آن پوشه را به دست آورده و در یک آرایه قرار می دهید). نام آرایه را برابر همان نام قبلی انتخاب کنید (چون در بخش هایی از کد ذکر شده است). بر اساس نام فایل عکس و همچنین مسیر پوشه (که آن را هم باید به صورت String در یک متغیر داشته باشید)، مسیر کامل فایل هر عکس را می توانید بسازید.
در حالت عادی، کدهای نمایش عکس به صورت زیر می بودند :
بنابراین باید کدهای مورد نظرتان برای نمایش عکس را جایگزین کد بالا کنید. به عنوان یک مثال، کد موجود در کلید زیر را ببینید :
دقت شود که کد موجود در کلید بالا، برای نماش عکس در ImageView است (نه در پس زمینه ImageView - زیرا روش قبلی که setBackgroundResource می بود، برای نمایش عکس در پس زمینه ImageView به کار می رفت)، بنابراین اگر خواستید که در پس زمینه نمایش داده شود (زیرا احتمالا در اندازه عکس ها تاثیر خواهد داشت)، باید کدها را تغییر دهید.
در ضمن، اجازه های دسترسی به حافظه خارجی (External Storage) که در کلید بالا ذکر شده است را فراموش نکنید (در غیر این صورت، با خطا رورو می شوید).


با سلام
من درحال ساختن یک کتاب کمیک هستم(هر صفحه از یک عکس تشکیل شده)
و الان میخوام کاری کنم که وقتی کاربر انگشتش رو از راست به چپ بکشه، بره به صفحه بعدی(عکس image view عوض بشه) و برعکس
لطفا راهنمایی کنین