کانال بله, جهت پشتیبانی و اطلاع رسانی کانال بله, جهت پشتیبانی و اطلاع رسانی
عضویت

‏ آموزش نحوه ی استفاده از ‏List‏ در اندروید-آداپتور اختصاصی در android

 

آموزش نحوه ی استفاده از ‏List‏ در اندروید قسمت دوم

 7. آموزش : پیاده سازی آداپتور اختصاصی

دراین تمرین آموزشی، طرح بندی (layout) خود را ویژه ی سطرها (rows) مشخص می کنیم و آن را در آداپتور پیاده می کنیم. فایل rowlayout.xml را در پوشه ی res/layout پروژه ی de.vogella.android.listactivity ایجاد کنید.

<?xml version="1.0" encoding="utf-8" ?>

‎‎<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"

               android:layout_width="wrap_content"

               android:layout_height="wrap_content">

        <imageview android:id="@+id/icon"

                     android:layout_width="22px"

                     android:layout_height="22px"

                     android:layout_marginleft="4px"

                     android:layout_marginright="10px"

                     android:layout_margintop="4px"

                     android:src="@drawable/ic_launcher">

            </ImageView>

            <textview android:id="@+id/label"

                        android:layout_width="wrap_content"

                        android:layout_height="wrap_content"

                        android:text="@+id/label"

                        android:textsize="20px">

                </TextView>

</linearlayout>

Activity خود را اصلاح کرده تا layout جدید در آن بکار گرفته شود.

package de.vogella.android.listactivity;
import android.app.ListActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.ArrayAdapter;

import android.widget.ListView;

import android.widget.Toast;

public class MyListActivity extends ListActivity {

 
public void onCreate(Bundle icicle) {
   
super.onCreate(icicle);
   
String[] values = new String[] { "Android"، "iPhone"، "WindowsMobile"،
       
"Blackberry"، "WebOS"، "Ubuntu"، "Windows7"، "Max OS X"،
       
"Linux"، "OS/2" };
   
// use your custom layout
    ArrayAdapter<
String> adapter = new ArrayAdapter<String>(this،
        R.layout.rowlayout، R.id.label، values);

    setListAdapter(adapter);

  }

  @Override
 
protected void onListItemClick(ListView l، View v، int position، long id) {
   
String item = (String) getListAdapter().getItem(position);
    Toast.makeText(
this، item + " selected"، Toast.LENGTH_LONG).show();
  }

}

 

نمایش listView با Layout خودش

 

8. ListView و ارتباط آن با افزایش کارایی

انگیزه افزایش کارایی و بهبود سرعت در دستگاه های اندروید

سرعت از آن جایی حائز اهمیت بسیار زیاد است که کاربر انتظار دارد دستگاه اندروید عملیات لازمه و کارهای محوله را سریع انجام دهد. در مقایسه با رایانه های رومیزی، طبیعتاً دستگاه های مبتنی بر سیستم عامل اندروید به خصوص از لحاظ سخت افزار به مراتب کندتر عمل می کنند. در این بخش به تشریح راه حلی در راستای افزایش سرعت عملیات این سیستم عامل جهت پیاده سازی بهینه ی list adapter اختصاصی، می پردازیم. گفتنی است آداپتورهای پیش فرض اندروید از جمله ArrayAdapter از پیش بهینه سازی شده بوده و از کارایی و سرعت لازم برخوردار می باشد.

عملیات سنگین و زمان بر

هر view ای که از فایل XML layout ظاهر می گردد (از فایل XML تغذیه و بارگذاری می شود) در نهایت به یک شی جاوا تبدیل می گردد. هر دو فرایند ظاهر کردن یا بارگذاری layout و ایجاد اشیا جاوا خیلی از لحاظ زمانی و مصرف حافظه عملیات سنگین و زمان بری محسوب می شوند.

به علاوه بکارگیری متد findViewById () خود بسیار سنگین بوده و زمان بر است، اما در مقایسه با بارگذاری layout به نسبت سبک تلقی می گردد.

اجتناب از بارگذاری مجدد شمای کلی (layout inflation و ایجاد اشیا جاوا)

در حقیقت ListView حاوی داده های بیشتری از تعداد سطر (row) هایی است که در لیست به نمایش گذاشته شده است. بنابراین اگر کاربر با بهره گیری از قابلیت اسکرول در لیست مورد نظر پیمایش کند، سطرها و view های مربوط به آن همگی از صفحه نمایش خارج می گردنند (برای کاربر دیگر قابل رویت نخواهند بود). در نتیجه آن دسته از اشیإ جاوا که این سطرها را نمایش می دهند، می توانند ویژه ی نمایش سطرهای جدید (که هم اکنون در صفحه نمایش قابل مشاهده می باشند) مورد استفاد قرار گیرند.

چنانچه سیستم اندروید به این نتیجه برسد که سطری دیگر برای کاربر قابل رویت نیست، به تابع getView () (از جمله متدهای آداپتور) دستور می دهد از view مربوطه با استفاده از پارامتر convertView دوباره استفاده کند.

آداپتور قادر است داده های جدید به view های گنجانده شده یا موجود در سلسله مراتب (hierarchy) convertView تخصیص دهد. این امر مانع از ایجاد اشیإ جدید جاوا و بارگذاری layout می شود و در نهایت در وقت و حافظه صرف جویی می کند.

در صورتی که اندروید نتواند سطری را دوباره بکارگیرد، سیستم اندروید null را به پارامتر convertview پاس می دهد.

اجتناب از بکارگیری متد findViewById () با پیاده سازی ViewHolder

با پیاده سازی کلاس ViewHolder می توان از فراخوانی مجدد تابع findViewById () در آداپتور اجتناب کرد.

ViewHolder در واقع یک کلاس ایستای داخلی (inner static class) درون آداپتور است که به view های مرتبط در layout ارجاع می دهد (حامل ارجاعاتی به view های مربوطه می باشد). ارجاع مزبور با استفاده از متد setTag () به row view به مثابه ی یک تگ اختصاص می یابد.

در صورت دریافت یک شی convertView، می توان به واسطه ی متد getTag () به نمونه ی کلاس ViewHolder دسترسی پیدا کرد سپس ویژگی (attribute) ها را به وسیله ی ارجاع / reference ViewHolder به view ها اختصاص داد.

اگرچه در نگاه اول عملیات فوق بسیار پیچیده بنظر می رسد، اما در حقیقت 15% از فراخوانی متد findViewById () سریع تر وظیفه ی محوله را انجام می دهد.

مثال

مثال زیر آداپتوری با کارایی بهینه سازی شده و بهبود یافته را نشان می دهد که view های موجود را دوباره بکار می برده و الگوی بالا را پیاده می کند.

package de.vogella.android.listactivity;
import android.app.Activity;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ArrayAdapter;

import android.widget.ImageView;

import android.widget.TextView;

public class MyPerformanceArrayAdapter extends ArrayAdapter<String> {

 
private final Activity context;
 
private final String[] names;
 
static class ViewHolder {
   
public TextView text;
   
public ImageView image;
  }

 
public MyPerformanceArrayAdapter(Activity context، String[] names) {
   
super(context، R.layout.rowlayout، names);
   
this.context = context;
   
this.names = names;
  }

  @Override
 
public View getView(int position، View convertView، ViewGroup parent) {
    View rowView = convertView;

   
// reuse views
   
if (rowView == null) {
      LayoutInflater inflater = context.getLayoutInflater();

      rowView = inflater.inflate(R.layout.rowlayout،
null);
     
// configure view holder
      ViewHolder viewHolder =
new ViewHolder();
      viewHolder.text = (TextView) rowView.findViewById(R.id.TextView01);

      viewHolder.image = (ImageView) rowView
         .findViewById(R.id.ImageView01);

      rowView.setTag(viewHolder);

    }

   
// fill data
    ViewHolder holder = (ViewHolder) rowView.getTag();

   
String s = names[position];
    holder.text.setText(s);

   
if (s.startsWith("Windows7") || s.startsWith("iPhone")
        || s.startsWith(
"Solaris")) {
      holder.image.setImageResource(R.drawable.no);

    }
else {
      holder.image.setImageResource(R.drawable.ok);

    }

   
return rowView;
  }

}

 9. فعال سازی  selection modeبرای ListView از طریق فراخوانی متد setChoiceMode ()

ListView به صورت پیش فرض selection mode را فعال نمی کند. در صورت لزوم باید خود با فراخوانی متد setChoiceMode () آن را فعال کنید.  ListView.CHOICE_MODE_MULTIPLEرا جهت فعال سازی چندین selection و  ListView.CHOICE_MODE_SINGLEرا برای فعال سازی تنها یک selection ارسال کنید.

برای دسترسی به آیتم های انتخابی ListView، از متد ()getCheckedItemPosition به منظور انتخاب تنها یک آیتم و از ()listView.getCheckedItemPositions جهت انتخاب چندین آیتم استفاده کنید. در صورت داشتن شناسه ای پایدار (stable ID)، می توانید با استفاده از متد getCheckedItemsId ()، شناسه ی آیتم های انتخابی را بدست آورید.

اندروید این layout پیش فرضی ارائه می دهد : طرح بندی android.R.layout.simple_list_item_multiple_choice که شامل view پیکربندی شده ی checkedTextView می باشد.

Activity های زیر نحوه ی بکارگیری selection mode ها را با مثال نمایش می دهد. اگر این مُدها را بکارببرید، ListView مقادیر انتخابی را ذخیره می کند.

package com.vogella.android.listview.selection.multi;
import android.app.ListActivity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.widget.ArrayAdapter;

import android.widget.ListView;

import android.widget.Toast;

import com.vogella.android.listview.selection.R;

public class MainActivity extends ListActivity {

  @Override
 
protected void onCreate(Bundle savedInstanceState) {
   
super.onCreate(savedInstanceState);
   
String[] values = new String[] { "a"، "b"، "c"، "d"، "e"، "f"، "g"،
       
"h"، "i"، "j"، "k"، "l"، "m"، "n"، "o"، "p"، "q"، "r"، "s"،
       
"t"، "u"، "w"، "x"، "y"، "z" };
    ‎‎    ArrayAdapter<
String> adapter = new ArrayAdapter<String>(this،
        android.R.layout.simple_list_item_multiple_choice، values);

    setListAdapter(adapter);

    getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

  }

@Override
 
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main، menu);

   
return true;
  }

  @Override
 
public boolean onOptionsItemSelected(MenuItem item) {
    Toast.makeText(
this،
       
String.valueOf(getListView().getCheckedItemCount())،
        Toast.LENGTH_LONG).show();

   
return true;
  }

}

package com.vogella.android.listview.selection.single;

import android.app.ListActivity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.widget.ArrayAdapter;

import android.widget.ListView;

import android.widget.Toast;

public class MainActivity extends ListActivity {


  @Override
 
protected void onCreate(Bundle savedInstanceState) {
   
super.onCreate(savedInstanceState);
   
String[] values = new String[] { "a"، "b"، "c"، "d"، "e"، "f"، "g"،
       
"h"، "i"، "j"، "k"، "l"، "m"، "n"، "o"، "p"، "q"، "r"، "s"،
       
"t"، "u"، "w"، "x"، "y"، "z" };
        ArrayAdapter<
String> adapter = new ArrayAdapter<String>(this،
        android.R.layout.simple_list_item_single_choice، values);

    setListAdapter(adapter);

    getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);

  }

  @Override
 
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main، menu);

   
return true;
  }

  @Override
 
public boolean onOptionsItemSelected(MenuItem item) {
    Toast.makeText(
this،
       
String.valueOf(getListView().getCheckedItemCount())،
        Toast.LENGTH_LONG).show();

   
return true;
  }

}

 10. آموزش نحوه ی استفاده از contextual action mode برای ListView

مطالعه ی این بخش ملزم آشنایی کلی شما با مفاهیم action bar و contextual action mode می باشد. این بخش چگونگی بکارگیری contextual action mode را جهت انتخاب ListView تشریح می کند.

به منظور تخصیص contextual action mode به قابلیت long click (کلیک یا همان لمس طولانی مدت روی المان یا آیتم مورد نظر که گزینه های دیگری را فعال می کند) روی یک آیتم، از متد setOnItemLongClickListener () در ListView استفاده کنید. متد بیان شده دارای اطلاعاتی درباره ی آیتم انتخابی می باشد. می توان در این متد ActionMode را راه اندازی کرد.

مثال زیر فرض می گیرد یک menu XML file به نام rowselection.xml  تعریف کرده اید و همچنین این منو دربردارنده ی درایه ای (entry) با شناسه ی@+id/menuitem1_show  می باشد.

حال اگر برنامه ی کاربردی را راه اندازی کرده و روی آیتمی در لیست long press کنید، Contextual action bar آماده ی بهره بری می باشد.

 

استفاده از contextual ActionBar در ListView

 

11. پیاده سازی عملیات undo

چه زمانی باید عملیات undo را پیاده کرد؟

توصیه می شود خنثی (undo) کردن عملیات اساسی را به خود کاربر محول کنید. از جمله ی این عملیات اساسی می توان به پاک کردن (deletion) اشاره کرد.

یک الگوی پرکاربرد و کارامد این است که در پایین صفحه یک (پنجره ی) انتخاب جهت مدیریت گزینه ی undo در اختیار کاربر قرار دهید. این انتخاب پس از گذشت زمان معینی و مجرد اینکه کاربر به همکاری با برنامه ادامه می دهد محو می گردد. به عنوان مثال می توان به اپلیکیشن Gmail اشاره کرد که الگوی نام برده را پیاده می کند.

دکمه Undo  

 مثال

در این بخش با ارائه ی مثال پیاده سازی عملیات undo را نمایش می دهیم که در آن با استفاده از animation دکمه ی undo به صورت خودکار پس از گذشت مدت زمان معینی محو می گردد.

برای این منظور پروژه ی جدیدی به نام com.vogella.android.userinterface.undo مبتنی بر قالب BlankTemplate ایجاد کنید.

Layout زیر را برای activity خود ایجاد کنید. این نوع طرح بندی از الگوی نمایشی FrameLayout برای نشان دادن دو بخش به طور کامل مجزای رابط کاربری (UI) استفاده می کند. نوار دکمه (button bar) در ابتدای امر پنهان است. دکمه ی ذکر شده از یک drawable استفاده می کند. یا یک drawable به پروژه ی خود اضافه کنید و یا به طور کلی ارجاع (reference) آن را حذف کنید.

<framelayout 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">

        <relativelayout android:layout_width="match_parent"

                          android:layout_height="match_parent"

                          tools:context=".MainActivity">

                <listview android:id="@+id/listview"

                            android:layout_width="match_parent"

                            android:layout_height="match_parent">

                    </ListView>

                </RelativeLayout>

                <linearlayout android:id="@+id/undobar"

                                android:visibility="gone"

                                android:layout_width="wrap_content"

                                android:layout_height="wrap_content"

                                android:layout_gravity="bottom|center_horizontal"

                                android:layout_margin="20dp"

                                android:alpha="100"

                                android:background="#808080"

                                android:dividerpadding="11dp"

                                android:padding="4dp">

                        <textview android:id="@+id/undobar_message"

                                    android:layout_width="wrap_content"

                                    android:layout_height="wrap_content"

                                    android:text="Deleted"

                                    android:textappearance="?android:attr/textAppearanceMedium"

                                    android:textcolor="#fff" />

                         <button android:id="@+id/undobar_button"

                                  android:layout_width="wrap_content"

                                  android:layout_height="wrap_content"

                                  android:layout_marginleft="30dp"

                                  android:onclick="onClick"

                                  android:background="#808080"

                                  android:drawableleft="@drawable/ic_undobar_undo"

                                  android:text="Undo"

                                  android:textappearance="?android:attr/textAppearanceMedium"

                                  android:textcolor="#fff" />

                    </LinearLayout>

</framelayout>

 اکنون کد activity خود را به ترتیب زیر بنویسید. برنامه ی راهنمای پروژه ی اندروید (Android Project Wizard) در محیط برنامه نویسی Eclipse از پیش درایه ی ActionBar را آماده ساخته و در صورت تمایل می توانید ActionBar entry خود را ایجاد کنید.

package com.vogella.android.userinterface.undo;
import android.app.Activity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.widget.ArrayAdapter;

import android.widget.ListView;

import android.widget.Toast;

import com.vogella.android.actionbar.undo.R;

public class MainActivity extends Activity {

 
private View viewContainer;
  @Override
 
protected void onCreate(Bundle savedInstanceState) {
   
super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ListView l = (ListView) findViewById(R.id.listview);

   
String[] values = new String[] { "Ubuntu"، "Android"، "iPhone"،
       
"Windows"، "Ubuntu"، "Android"، "iPhone"، "Windows" };
    ArrayAdapter<
String> adapter = new ArrayAdapter<String>(this،
        android.R.layout.simple_list_item_1، values);

    viewContainer = findViewById(R.id.undobar);

    l.setAdapter(adapter);

  }

  @Override
 
public boolean onCreateOptionsMenu(Menu menu) {
   
// Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_main، menu);

   
return true;
  }

  @Override
 
public boolean onOptionsItemSelected(MenuItem item) {
    showUndo(viewContainer);

   
return true;
  }

 
public void onClick(View view) {
    Toast.makeText(
this، "Deletion undone"، Toast.LENGTH_LONG).show();
    viewContainer.setVisibility(View.GONE);

  }

 
public static void showUndo(final View viewContainer) {
    viewContainer.setVisibility(View.VISIBLE);

    viewContainer.setAlpha(
1);
    viewContainer.animate().alpha(
0.4f).setDuration(5000)
       .withEndAction(
new Runnable() {
         @Override
         
public void run() {
            viewContainer.setVisibility(View.GONE);

          }

        });

  }

}

چنانچه المان مورد نظر را در ActionBar انتخاب کنید، نوار دکمه به مدت پنج ثانیه پدیدار می شود.

 

دکمه Undo

1394/07/27 7854 3548
رمز عبور : tahlildadeh.com یا www.tahlildadeh.com
نظرات شما

نظرات خود را ثبت کنید...