13 Şubat 2018 Salı

Android Dersleri 13 - GridView


13 - GridView

https://www.tutorialspoint.com/android/android_grid_view.htm  bu ve aşağıdaki kaynağın örneği aynı.
https://developer.android.com/guide/topics/ui/layout/gridview.html
        GridView is a ViewGroup that displays items in a two-dimensional, scrollable grid(rows & columns). ( Item'ları 2 boyutlu ve scrollable bir alanda gösteren bir viewgroup'dur GridView.  )
        The grid items are not necessarily predetermined but they automatically inserted to the layout using a ListAdapter. (GridView'de gösterilecek olan item'lar, GridView'e ListAdapter kullanılarak insert edilir. )



GRID VIEW

       An adapter actually bridges between UI components and the data source that fill data into UI Component. Adapter can be used to supply the data to like spinner, list view, grid view etc. ( Adapter, view ve source'u birbirine bağlar. Spinner, list view, gridview gibi viewgroup'lara veri sağlamak için adapter kullanılır. )
       The ListView and GridView are subclasses of AdapterView and they can be populated by binding them to an Adapter, which retrieves data from an external source and creates a View that represents each data entry. ( ListView, Spinner ve GridView, birer AdapterView'dir, yani AdapterView'in subclass'ıdırlar ve ViewGroup'durlar. Bu viewgroup'a item insert etmek için Adapter kullanılmak zorundadır, Adapter class'ı bir array'den veya cursor'dan okuduğu verileri kullanarak View object'ler yaratır ve bu View object'leri bir ViewGroup'a ekler. )

GridView Attributes

       Following are the important attributes specific to GridView. ( Layout xml'da tanımladığımız GridView element aşağıdaki attribute'lere sahiptir. )
Sr.No
Attribute & Description
1
android:id
This is the ID which uniquely identifies the layout.
2
android:columnWidth
This specifies the fixed width for each column. This could be in px, dp, sp, in, or mm. ( GridView'deki herbir sütunun(hücrenin) genişliğini belirtir. )
3
android:gravity
Specifies the gravity within each cell. Possible values are top, bottom, left, right, center, center_vertical, center_horizontal etc. ( Herbir hücredenin içindeki item'ı sağa mı sola mı yukarı mı aşağı mı yaslayacağımızı vs. ayarlarız. )
4
android:horizontalSpacing
Defines the default horizontal spacing between columns. This could be in px, dp, sp, in, or mm. ( Sütunlar(hücreler) arasındaki yatay boşluğu belirtir. )
5
android:verticalSpacing
Defines the default vertical spacing between rows. This could be in px, dp, sp, in, or mm. (Satırlar(hücreler) arasındaki boşluğu, yani dikeydeki boşluğu belirtir. )
6
android:stretchMode
Defines how columns should stretch to fill the available empty space, if any. This must be either of the values. (Eğer boş alan varsa, sütunlar yani hücreleri genişletmek için bu attribute'ü kullanırız. Bu attribute'e aşağıdaki değerlerden birini assign ederiz.)
·        none − Stretching is disabled. ( Hücreler genişletilmez. )
·        spacingWidth − The spacing between each column is stretched. ( Herbir sütun arasındaki boşluk doldurulacak şekilde hücreler yatayda genişletilir. )
·        columnWidth − Each column is stretched equally. ( Herbir hücre eşit miktarda genişletilir veya uzatılır. )
·        spacingWidthUniform − The spacing between each column is uniformly stretched. ( Herbir sütun arasındaki boşluk doldurulacak şekilde hücreler eşit oranda yatayda genişletilir.)
7
android:numColumns
Defines how many columns to show. May be an integer value, such as "100" or auto_fit which means display as many columns as possible to fill the available space. ( Bir satırda kaç tane item gösterileceğini, yani gridview'de kaç tane column(sütun) olacağını belirtiriz. 100 dersek, gridview'de 100 tane sütun olmasını belirtmiş oluruz, auto_fit dersek ekrana sığabildiği kadar sütun gösteririz gridview'de. )
       MainActivity.java : To do something when an item in the grid is clicked, the setOnItemClickListener() method is passed a new AdapterView.OnItemClickListener. This anonymous instance defines the onItemClick() callback method to show a Toast that displays the index position (zero-based) of the selected item (in a real world scenario, the position could be used to get the full sized image for some other task) ( MainActivity.java dosyasının içeriği aşağıdadır. MainActivity class'Inın onCreate() method'Unda main layout'U set ederiz, findViewById() method'Unu çağırarak GridView view object'i elde ederiz sonra bu object'in setAdapter(new ImageAdapter(this)) method'unu çağırırız. setAdapter() method'una argument olarak ImageAdapter object'i veririz yani. ImageAdapter constructor'a argument olarak context object veririz, Activity class'ı bir context olduğu için, this bir context object'e refer eder.
public class MainActivity extends Activity {
   @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() {
       
public void onItemClick(AdapterView<?> parent, View v,
               
int position, long id) {
           
Toast.makeText(HelloGridView.this, "" + position,
                   
Toast.LENGTH_SHORT).show();
       
}
   
});
  }
} 
       Following will be the content of res/layout/activity_main.xml file. (main layout xml'de GridView element kullanırız. GridView element'in attribute'lerini inceleyelim. )
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/gridview"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:columnWidth="90dp"   // hücre genişliğini ayarlar.
   android:numColumns="auto_fit"    // bir satırdaki hücre sayısı ekrana sığabilecek kadardır.
   android:verticalSpacing="10dp"     // dikeyde 2 satır arasındaki boşluk
   android:horizontalSpacing="10dp"  // yatayda 2 satır arasındaki boşluk
   android:stretchMode="columnWidth" // Herbir hücre eşit miktarda genişletilsin veya uzatılsın.
   android:gravity="center"    // hücredeki içerik ortalansın.
/>
res/values/strings.xml :
<?xml version="1.0" encoding="utf-8"?>
<resources>
   <string name="app_name">HelloWorld</string>
   <string name="action_settings">Settings</string>
</resources>

     ImageAdapter.java : First, this class implements some required methods inherited from BaseAdapter. Normally, getItem(int) should return the actual object at the specified position in the adapter, but it's ignored for this example. Likewise, getItemId(int)should return the row id of the item, but it's not needed here.
 ( BaseAdapter class'ını extend eden bir adapter class'ı tanımladık. Bu class'ın aldığı constructor argument olarak Context object alıp bu object'i kendi scope'undaki reference variable'a assign eder. Sonra 8 tane image indirdim google'dan ve bunları kopyalayıp drawable klasörüne yapıştırdım, bu resimlerin isimlerini mThumbIds isimli bir integer array'de tutuyorum. BaseAdapter class'ını extend ettiğimiz için getView() method'unu ek olarak, getCount(), getItem(), getItemId() method'larını da implement etmek zorundayız. Şimdilik yeterli olduğu için getItem(), getItemId() method'larının null return etmesini sağlayalım, getCount() method'u ise mThumbsIds isimli integer array'imizin size'ını return etsin.)

     getView() method creates a new View for each image added to the ImageAdapter. When this is called, a View is passed in, which is normally a recycled object (at least after this has been called once), so there's a check to see if the object is null. If it is null, an ImageView is instantiated and configured with desired properties for the image presentation:
o    setLayoutParams(ViewGroup.LayoutParams) sets the height and width for the View—this ensures that, no matter the size of the drawable, each image is resized and cropped to fit in these dimensions, as appropriate. ( imageView object'in setLayoutParams() method'unu çağırarak imageView'in size'larını dinamik olarak set ederiz. )
o    setScaleType(ImageView.ScaleType) declares that images should be cropped toward the center (if necessary). ( imageView'İn içerisindeki image'ın nasıl resize edileceğini belirtir. )
o    setPadding(int, int, int, int) defines the padding for all sides. (Note that, if the images have different aspect-ratios, then less padding will cause more cropping of the image if it does not match the dimensions given to the ImageView.)
     If the View passed to getView() is not null, then the local ImageView is initialized with the recycled View object.
     At the end of the getView() method, the position integer passed into the method is used to select an image from the mThumbIds array, which is set as the image resource for the ImageView.
( Şimdi ise getView() method'unu inceleyelim.
       Gridview'deki bir hücre olarak kullanılacak bir view ekranda ilk kez yaratılıyorsa, convertView null'dır. Daha önce yaratılmışsa null değildir. Bu konuyu adapter'lerde daha önce anlatmıştık. Yani başlangıçta ekran dolana kadar yaratılan hücrelerin view'leri için getView() methdo'u çağırıldığında convertView null'dır. Ancak aşağı doğru scroll ettiğimizde ekranda zaten varolan hücreleri tekrar kullanırız dolayısıyla convertView null değildir bu durumda, recycling denir bu işleme yani hücrelerin içeriğini değiştiririz bu sayede. Hücre ilk kez yaratıldığında convertView null'dır, if block'a gireriz, imageView class'ından bir object yaratırız, imageView object'in setLayoutParams() method'unu çağırarak imageView'in size'larını dinamik olarak set ederiz.
       setScaleType() : Controls how the image should be resized or moved to match the size of this ImageView. ( imageView'İn içerisindeki image'ın nasıl resize edileceğini belirtir. )
       convertView null değilse, convertView'i imageView'e cast ve assign ederiz. Sonra imageView object'in setImageResource(mThumbIds[position]) method'unu çağırırız, böylece imageView object'e mThumbIds isimli array'in position'ıncı elemenındaki isme sahip resmi set ederiz. En son imageView object'i return ederiz.
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent)
{
   ImageView imageView;
  
   if (convertView == null) {
      imageView = new ImageView(mContext);
      imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
      imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
      imageView.setPadding(8, 8, 8, 8);
   }
   else
   {
      imageView = (ImageView) convertView;
   }
   imageView.setImageResource(mThumbIds[position]);
   return imageView;
}      )
public class ImageAdapter extends BaseAdapter {
   private Context mContext;

    // Keep all Images in array
   public Integer[] mThumbIds = {
      R.drawable.sample_2, R.drawable.sample_3,
      R.drawable.sample_4, R.drawable.sample_5,
      R.drawable.sample_6, R.drawable.sample_7,
      R.drawable.sample_0, R.drawable.sample_1,
      R.drawable.sample_2, R.drawable.sample_3,
      R.drawable.sample_4, R.drawable.sample_5,
      R.drawable.sample_6, R.drawable.sample_7,
      R.drawable.sample_0, R.drawable.sample_1,
      R.drawable.sample_2, R.drawable.sample_3,
      R.drawable.sample_4, R.drawable.sample_5,
      R.drawable.sample_6, R.drawable.sample_7
   };

   // Constructor
   public ImageAdapter(Context c) {
      mContext = c;
   }
  
   public int getCount() {
      return mThumbIds.length;
   }

   public Object getItem(int position) {
      return null;
   }

   public long getItemId(int position) {
      return 0;
   }
  
   // create a new ImageView for each item referenced by the Adapter
   public View getView(int position, View convertView, ViewGroup parent) {
      ImageView imageView;
     
      if (convertView == null) {
         imageView = new ImageView(mContext);
         imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
         imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
         imageView.setPadding(8, 8, 8, 8);
      }
      else
      {
         imageView = (ImageView) convertView;
      }
      imageView.setImageResource(mThumbIds[position]);
      return imageView;
   }
}
       Şimdiye kadar yazığımız kodları çalıştırdığımızda aşağıdaki uygulamayı elde ederiz. Sadece böyle bir gridview gösterilir uygulamadaki resimlere tıklayınca resimlerin pozisyonu ekranda toast mesajıyla gösterilir, başka hiçbir fonksiyonalite yoktur.
       GridView ve ImageView element'lerinin property'lerinin değiştirerek uygulamayı tekrar çalıştıralım. Böylece bu element'lerin davranışlarını inceleyelim. Örneğin, kodumuzdaki şu method'u silip:
bunun yerine şunu kullanalım:
output'u inceleyelim.

Sub-Activity Example

       Let's extend the functionality of above example where we will show selected grid image in full screen. To achieve this, we need to introduce a new activity. Just keep in mind for any activity we need perform all the steps like we have to implement an activity class, define that activity in AndroidManifest.xml file, define related layout and finally link that sub-activity with the main activity by it in the main activity class. (Yukarıdaki uygulamamıza fonksiyonellik ekleyelim. GridView'de gösterilen resimlere tıklayınca farklı bir activity açılsın ve bu activity'de tıkladığımız resim full ekranda gösterilir. Bunun için önce yeni bir activity class'ı(SingleViewActivity) tanımlayacağız, bu activity'yi manifest.xml dosyasında belirteceğiz, ve bu activity için yeni bir layout dosyası(single_view.xml) tanımlayıp activity için bu layout'u set edeceğiz. Son olarak, subactivity'yi Main activity class'ına bağlayacağız, yani main activity'de bir resime tıklayınca subactivty başlatılacak. )

       Following is the content of the modified main activity file  MainActivity.java. This file can include each of the fundamental life cycle methods. ( MainActivity class'ını yazalım.Yukarıdaki uygulamanın MainActivity'sinden farklı olarak sadece GridView view object'lere listener register ettik, bu view object'lere tıklayınca bir intent object yaratılır.
Intent i = new Intent(getApplicationContext(), SingleViewActivity.class);
SingleViewActivity, intent'in gönderileceğini activity class'ıdır, yani ekranda açılacak activity class'ıdır. Sonra bu intent'e veri koyulur:
            i.putExtra("id", position);
Sonra startActivity() method'u çağırılarak yeni activity başlatılır:
            startActivity(i);
)
public class MainActivity extends Activity {
   @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() {
         public void onItemClick(AdapterView<?> parent, View v, int position, long id){
            // Send intent to SingleViewActivity 
            Intent i = new Intent(getApplicationContext(), SingleViewActivity.class);
            // Pass image index
            i.putExtra("id", position);
            startActivity(i);
         }
      });
   }
}

       Following will be the content of new activity file  SingleViewActivity.java file.( Yeni bir activity class'ı tanımlarız. GridView'deki bir resime tıklanıldığında bu activty açılacaktır ekranda.
       onCreate() method'Unda
setContentView(R.layout.single_view);
diyerek activity'nin layout'u set edilir. Sonra bu activity başlatılırken, mainActivity'den gönderilen intent object elde edilir:
      Intent i = getIntent();
       Sonra intent object'de tutulan id isimli variable'ın değeri elde edilir.
      // Selected image id
      int position = i.getExtras().getInt("id");
       Sonra, ImageAdapter class'ından bir object yaratılır ImageAdapter constructor'ına context object argument olarak verilerek.
      ImageAdapter imageAdapter = new ImageAdapter(this);
       Sonra set edilen layout'daki SingleView id'li element, yani  ImageView element elde edilir:
      ImageView imageView = (ImageView) findViewById(R.id.SingleView);
       Sonra ImageView element'in setImageResource() method'u çağırılarak imageView'in içerisine bir resim koyulur.
      imageView.setImageResource(imageAdapter.mThumbIds[position]);
)
public class SingleViewActivity extends Activity {
   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.single_view);
      
      // Get intent data
      Intent i = getIntent();
      
      // Selected image id
      int position = i.getExtras().getInt("id");
      ImageAdapter imageAdapter = new ImageAdapter(this);
      
      ImageView imageView = (ImageView) findViewById(R.id.SingleView);
      imageView.setImageResource(imageAdapter.mThumbIds[position]);
   }
}
Following will be the content of res/layout/single_view.xml file. ( Yeni activity'mizin layout'u, yani full screen fotoğraf göstereceğimiz activity'nin layout'u aşağıda gösterilmiştir. Bu layout'un root view'i LinearLayout'dur,LinearLayout içerisinde bir ImageView vardır, ImageView'in size'ı LinearLayout'u kaplar. )
<?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="match_parent"
   android:orientation="vertical">
<ImageView android:id="@+id/SingleView"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"/>
</LinearLayout>
Following will be the content of AndroidManifest.xml to define two new constants. ( AndroidManifest dosyasında 2 tane activity belirtiriz, android:name attribute'ü ile activity class'ını belirtiriz. activity class'ının başındaki . nokta nedir peki? Uygulamanın default package'ıdır, yani manifest element'inin package attribute'ü ile belirtilen path'dir. activity element'inin içindeki intent-filter element'İnin içerisindeki action ve category element'leri, uygulama başlatıldığında bu activity'nin başlatılmasını sağlar. )
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.example.helloworld">
   <application
      android:allowBackup="true"
      android:icon="@drawable/ic_launcher"
      android:label="@string/app_name"
      android:theme="@style/AppTheme" >
      <activity
         android:name="com.example.helloworld.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>
      <activity android:name=".SingleViewActivity"></activity>
   </application>
</manifest>
Output :   ( Uygulamamızı çalıştıralım. GridView'de resimler gösterilir. )

       Now if you click on either of the images it will be displayed as a single image: ( Bu resimlerden birine tıkladığımızda tıkladığımız resim yeni bir activity'de full ekranda açılır aşağıdaki gibi:)


Soru?
onItemSelected()  nedir?

For further resource :
http://www.androidhive.info/2012/02/android-gridview-layout-tutorial/
https://www.raywenderlich.com/127544/android-gridview-getting-started


Hiç yorum yok:

Yorum Gönder