یادداشت های یک توسعه دهنده از جهان برنامه نویسی

۴ مطلب با کلمه‌ی کلیدی «android» ثبت شده است

تغییر UI در زمان اجرا با استفاده از ViewStub

اصول برنامه نویسی و طراحی میگه تا حد امکان باید از کد های تکراری بپرهیزیم و اینکار برای طراحی رابط کاربری هم بسیار مورد نیازه . یه مثال ساده ای که در این مورد همیشه زده میشه جداسازی کد های یک قسمت طراحی بصورت یک فایل جدا layout و استفاده از اون در layout های دیگه است که میشه با تگ های include , merge اون قسمت رو اضافه کرد . البته اگر قسمت ضمیمه شونده منطق خودش رو داشته باشه باید بصورت fragment به اکتیویتی اضافه بشه تا بتونیم برای هر قسمت منطقش رو اجرا کنیم . اینکار هم با تگ fragment , framelayout قابل انجامه . در چنین مثالهایی ما یک بخش ثابت داریم که میتونه در فضاهای بزرگ دیگه مثل فرگمنت یا اکتیویتی تکرار بشه 


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

ViewStub 


طبق تعریف خود گوگل :
ViewStub is a zero-sized invisible View which is used to load "layout resource" at runtime.

یعنی ViewStub ویویی بدون سایز و مخفی است که در زمان اجرا به عنوان layout نمایش داده خواهد شد . این یعنی اینکه با اضافه کردن این ویو به layout هیچ جایی رو نخواهد گرفت و زمانی که متد ()inflate یا visible آن اجرا شود ، یه ویو دیگر را در خود نمایش خواهد داد . 

<ViewStub
    android:id="@+id/view_stub"
    android:inflatedId="@+id/replace_view"
    android:layout="@layout/replace_layout"
    android:layout_width="match_parent"
android:layout_height="match_parent"
/>

همانطور که در کد بالا می بینید attribute های ViewStub شامل موارد زیر می باشد :


android:id="@+id/view_stub"

 id مختص خود ViewStub که بتوان بعدا در برنامه به آن دسترسی داشت 


android:inflatedId="@+id/replace_view"

id ویویی که بعد از اجرای متد ()inflate یا visible به ویو جایگزین شده داده خواهد شد 


android:layout="@layout/replace_layout"

layout ای که باید جایگزین شود . البته اینکار را بصورت کد نویسی انجام می دهیم تا بتوانیم همانند مثال گفته شده layout های اختصاصی را برای هر فرگمنت جایگزین کنیم

viewStub.setLayoutResource(R.layout.my_checkbox);
View inflatedView = viewStub.inflate();

میتونید نحوه استفاده از ViewStub رو در اینجا و اینجا و اینجا و اینجا ببینید . با استفاده از ViewStub عملا ما میتونیم یک جایی اختصاصی جدا در layout در نظر بگیریم که برای هر فرگمنت یا اکتیویتی بتونه ویو مختص به خود رو در آن جایگزین کند . اما یکی از کاربرد های مهم دیگه ViewStub نیز لود کردن قسمت های مختلف layout در زمان های مختلفه . فرض کنید layout شلوغی داریم که اگر بخواهیم بصورت یکجا لود بشه زمان زیادی رو میگیره ، در این حالت با استفاده از ViewStub میشه زمان نمایش ویو رو تا زمان اجرای متد ()inflate یا visible به تاخیر بندازیم 


پی نوشت : یکی از ویژگی های ViewStub اینه که زمان inflate شدن ، خود ViewStub حذف خواهد شد و جای آن را ویو تعریف شده خواهد گرفت در نتیجه زمان استفاده از ViewStub در ConstraintLayout بعد از inflate شدن دیگه هیچ قید و بندی به ConstraintLayout نخواهد داشت ، برای حل این مشکل کافیه همانند راه حل ارائه شده در اینجا ، inflatedId رو با id یک مقدار قرار بدیم .

۰ نظر موافقین ۰ مخالفین ۰
مرتضی درزی

دیباگ مستقیم اپ روی گوشی

حتما برای دولاپر های عزیز اندروید پیش اومده که بعد از آماده سازی اولیه اپ و نصب روی گوشی ، در حالی که به نظر میاد همه چیز داره خوب کار میکنه اپ کرش می کنه و یه سوال بسیار بزرگ عین شاخ از سرشون بیرون میزنه  ! اگر مثل من دسترسی به محیط دیباگ android studio به سرعت در اختیارتون نیست و یا نمیدونید کجا خطا اتفاق افتاده تا سریع برید همون خط رو دیباگ دوباره کنید و میخواید که خطا روی خود گوشی بهتون نمایش داده بشه ، این روش کارایی خوبی خواهد داشت .

Android Global Exception Handler

اینکار به سادگی با java.lang.Thread.UncaughtExceptionHandler قابل انجامه ولی باید یکی از دو روش زیر رو انتخاب کنید :

1.خطایابی در سطح Application که در این صورت نمی توانید dialog باز کنید و یا اکتیویتی جدیدی اجرا کنید با این حال هر نوع خطایابی قابل اجرا خواهد شد 

2.خطایابی در سطح Activity که به راحتی میتوان dialog یا اکتیویتی دیگری باز کرد ولی باید در یک کلاس ارث بری شده توسط اکتیویتی ها نوشته شود ( مثلا BaseActivity )

خطایابی در سطح Application

در این روش log ایرور بصورت فایل روی دستگاه ذخیره خواهد شد تا در اجرای دوباره اپ بتوان از آن استفاده کرده و متن خطا را نمایش داد 


public class LoggingExceptionHandler implements Thread.UncaughtExceptionHandler {
    private final static String TAG = LoggingExceptionHandler.class.getSimpleName();
    private final static String ERROR_FILE = MyAuthException.class.getSimpleName() + ".error";
    private final Context context;
    private final Thread.UncaughtExceptionHandler rootHandler;
    public LoggingExceptionHandler(Context context) {
        this.context = context;
        // we should store the current exception handler -- to invoke it for all not handled exceptions ...
        rootHandler = Thread.getDefaultUncaughtExceptionHandler();
        // we replace the exception handler now with us -- we will properly dispatch the exceptions ...
        Thread.setDefaultUncaughtExceptionHandler(this);
    }
    @Override
    public void uncaughtException(final Thread thread, final Throwable ex) {
        try {
            Log.d(TAG, "called for " + ex.getClass());
            // assume we would write each error in one file ...
            File f = new File(context.getFilesDir(), ERROR_FILE);
            // log this exception ...
            FileUtils.writeStringToFile(f, ex.getClass().getSimpleName() + " " + System.currentTimeMillis() + "\n", true);
        } catch (Exception e) {
            Log.e(TAG, "Exception Logger failed!", e);
        }
    public static final List<String> readExceptions(Context context) {
        List<String> exceptions = new ArrayList<>();
        File f = new File(context.getFilesDir(), ERROR_FILE);
        if (f.exists()) {
            try {
                exceptions = FileUtils.readLines(f);
            } catch (IOException e) {
                Log.e(TAG, "readExceptions failed!", e);
            }
        }
        return exceptions;
    }
}

حالا باید ان را به سطح Application ضمیمه کنیم


public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        new LoggingExceptionHandler(this);
    }
}

یادتان نرود که در فایل AndroidManifest  نیز تغییرات زیر را انجام دهید 

<application
    android:name=".MyApp"

خطایابی در سطح Activity

در این روش با استفاده از ApplicationContext می توان log ایرور را بصورت مستقیم نشان داد و یا حتی اکتویتی جدیدی را اجرا کرد 

public class MyExceptionHandler implements Thread.UncaughtExceptionHandler {

    public static final String EXTRA_MY_EXCEPTION_HANDLER = "EXTRA_MY_EXCEPTION_HANDLER";
    private final Activity context;
    private final Thread.UncaughtExceptionHandler rootHandler;

    public MyExceptionHandler(Activity context) {
        this.context = context;
        // we should store the current exception handler -- to invoke it for all not handled exceptions ...
        rootHandler = Thread.getDefaultUncaughtExceptionHandler();
        // we replace the exception handler now with us -- we will properly dispatch the exceptions ...
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    @Override
    public void uncaughtException(final Thread thread, final Throwable ex) {
        if (ex instanceof MyAuthException) {
            // note we can't just open in Android an dialog etc. we have to use Intents here
            // http://stackoverflow.com/questions/13416879/show-a-dialog-in-thread-setdefaultuncaughtexceptionhandler

            Intent registerActivity = new Intent(context, AuthActivity.class);
            registerActivity.putExtra(EXTRA_MY_EXCEPTION_HANDLER, MyExceptionHandler.class.getName());
            registerActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            registerActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);

            context.startActivity(registerActivity);
            // make sure we die, otherwise the app will hang ...
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(0);
        } else {
            rootHandler.uncaughtException(thread, ex);
        }
    }
}

برای ضمیمه کردن این Handler باید یک کلاس ایجاد کرد تا اکتیویتی های دیگر از آن ارث بری کنند 


public abstract class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new MyExceptionHandler(BaseActivity.this);
    }
}
خودم از این روش در پروژه هام استفاده میکنم و معمولا وقتی ایرور جدید غیر قابل پیش بینی اتفاق می افته خیلی بدردم خورده ... البته چون از روش دوم استفاده میکنم بعضی از ایرور های که قبل از activity اتفاق می افتن رو نمیشه catch کرد که زیاد چنین اتفاقی نمی افته . من برای نمایش متن ایرور از اکتویتی جدید و یک TextView استفاده میکنم . البته نمی دونم بدلیل محدودیت String و یا TextView کل متن ایرور نمایش داده نمیشه که زیاد فرقی نمیکنه و معمولا از همون خطوط اول مشخص میشه خطا برای چیه 
۰ نظر موافقین ۰ مخالفین ۰
مرتضی درزی

تصاویر برداری ( Vector Drawable ) در اندروید

تصاویر برداری یا همان Vector Drawable نوعی از تصاویر هستند که با استفاده از محاسبات ریاضی و برداری ساخته میشوند و نسبت به تصاویر PNG  , JPG  کاربرد های بیشتری در طراحی رابط کاربری موبایل و وب دارند . از جمله مزیت بسیار خوب این تصاویر امکان تغییر سایز تصاویر در رزولوشن های متفاوت بدون از دست دادن جزئیات می باشد . 

 

تفاوت در چیست ؟

تصاویر برداری با محاسبات ریاضی ساخته می شوند ، مبنای این محاسبات نیز اندازه نمایی ( View ) است که در آن قرار گرفته اند .این یعنی اینکه اگر یک فایل برداری را در رزولوشن 320*240 قرار دهید ، تمام محاسبات از روی همین اندازه انجام گرفته و بردار ها بر اساس آن ساخته می شود و با قرار دادن همان فایل برداری در رزولوشن 1288*768 محاسبات دوباره بر اساس اندازه جدید انجام میگیرد . اما در تصاویر پیکسلی ، این پیکسل های تصاویر هستند که در هر رزولوشن جایگذاری میشوند و با تغییر اندازه تصاویر ، پیکسل ها تغییری نمی کنند و اطلاعات جدیدی برای افزایش کیفیت تصاویر به آن اضافه نمی شود . عملا تصاویر برداری با تبدیل تصاویر به یکسری بردار ریاضی و به تاخیر انداختن ساخته شدن تصویر تا زمان مشخص شدن اندازه نما در زمان اجرا تصاویر با کیفیت تری را تولید می کنند 

استفاده از تصاویر برداری در اندروید 

برای استفاده از تصاویر پیکسلی در اپلیکیشن ها باید از قبل فایل متفاوتی از یک تصویر برای روزلوشن های متفاوت صفحه نمایش در پوشه res پروژه گنجانده شود تا اندروید در زمان اجرا با توجه به روزلوشن دستگاه اجرا کننده تصویر درست را در صفحه نمایش دهد 

 


ولی پس از معرفی تصاویر برداری در اندروید lollipop و SDK 21 ، توسعه دهندگان می توانند تنها با یک فایل به فرمت xml ، تصاویر با کیفیت را برای روزلوشن های مختلف در اپلیکیشن های خود استفاده کنند . این فایل ها در پوشه drawable قرار میگیرند . 

 

تصاویر برداری را میتوان در android studio 3+  و SDK 23+ و Gradle 3+ به راحتی به کار برد .

تنظیمات مورد نیاز 

ابتدا باید در قسمت تنظیمات Gradle به بخش default config کد زیر را اضافه کنید . با این کار امکان استفاده از support library برای تصاویر برداری امکان پذیر میشود .

defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }

همچینی نیاز است تا کد های زیر نیز به قسمت dependencies اضافه شود تا برای ورژن های پایین تر ، از support library برای نمایش آن استفاده شود 

dependencies {
    implementation 'com.android.support:support-v4:27.1.1'
    implementation 'com.android.support:appcompat-v7:27.1.1'
}

بهتر است بجای کامپوننت های پیش فرض اندروید که قابلیت قرار گیری تصاویر در آن قرار دارد از کامپوننت های support library  بصورت زیر استفاده کنید . در این صورت نمایش تصاویر در ورژن های اندروید 21 به بالا بدون مشکل خواهد بود . 

  android.support.v7.widget.AppCompatButton
  android.support.v7.widget.AppCompatImageButton
  android.support.v7.widget.AppCompatImageView

جهت اختصاص تصاویر به این کامپوپنت های باید از app:srcCompat استفاده شود 

<android.support.v7.widget.AppCompatImageView
        android:id="@+id/img_demo"
        android:layout_width="120dp"
        android:layout_height="120dp"
 app:srcCompat="@drawable/ic_heart" />

در صورت نیاز میتوان بصورت کد نویسی نیز تصاویر برداری را به کامپوننت ها اختصاص داد که نمونه کد آن در زیر آمده است 

// set vector drawable by ID 
val drawable = AppCompatResources.getDrawable(mContext, R.drawable.ic_heart)
img_demo.setImageDrawable(drawable)

در صورت نیاز به استفاده از تصاویر برداری برای اندروید با ورژن های 21 به پایین تر نیز باید علاوه بر تنظیمات و روش های گفته شده بالا ، باید تنظیمات زیر را نیز انجام دهید 

ابتدا برای هریک از فایل های تصاویر خود یک wrapper به شکل زیر با فرمت xml ایجاد میکنید و تصاویر برداری را در آن آدرس دهی میکنید

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_heart"/>
</layer-list>

همچنین در اکتیویتی که این تصاویر را در آن نمایش میدهید نیز در بخش onCreate قطعه کد زیر را قرار دهید . 

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
}

ساخت تصاویر برداری در اندروید استدیو

میتونید در اندروید استودیو فایل های با فرمت svg و psd را به تصاویر برداری تبدیل کنید برای اینکار مثل تصویر به منوی Vector Asset رفته و فایل های مورد نظر را انتخاب کنید 

 

 

منابع جهت مطالعه 

تبدیل فایل های svg به vectordrawable 

http://inloop.github.io/svg2android/

ساخت فایل های svg

https://app.svgator.com

http://app.inker.co

https://vectr.com/

ساخت تصاویر برداری انیمیشن 

https://shapeshifter.design/

ساخت آیکون و تصاویر 

https://romannurik.github.io/AndroidAssetStudio/

کتابخانه برای استفاده از 2000 ایکون متریال بصورت تصاویر برداری 

https://github.com/code-mc/material-icon-lib


۰ نظر موافقین ۰ مخالفین ۰
مرتضی درزی

طراحی رابط کاربری موبایل

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

اما اگه آستین ها رو بالا زدید و میخواید طراحی رو شروع کنید ولی مسلما مثل هر برنامه نویس دیگه نرم افزار های طراحی مثل Photoshop , Sketch , Invision ندارید بهتره از بعضی از اپلیکیشن های انلاین استفاده کنید که اتفاقا خود طراحان هم تو کارهاشون ازش استفاده میکنن . 

یکی از این اپ های آنلاین که جالب و زیبا ساخته شده Fluid UI . اپی که برای طراحی رابط کاربری موبایل ، تبلت و وب ساخته شده و شما میتونید از تمام المان های استفاده شده در موبایل در طراحی اولیه تون استفاده کنید .

از جمله امکانات این اپ آنلاین 

نمونه سازی سریع 

به راحتی و با سرعت میتونید از المان های متریال دیزاین در اندروید و ios استفاده کنید .

اشتراک گذاری 

میتونید بصورت گروهی در ساخت طراحی شرکت کنید و هر کدام بصورت جدا یکی از کارها رو انجام داده و به اشتراک بگذارید 

دسترسی آسان 

بدلیل انلاین بودن اپ میتونید از هر کجا که اینترنت دارید کار طراحیتون رو ادامه بدید 

پیش نمایش روی موبایل 

میتونید با نصب اپلیکیشن اندروید این سایت و اسکن QR پروژه روی موبایلتون بصورت واقعی نتیجه رو ببینید 


از کارهای جالبی که میشه توی این اپ انجام داد ایجاد interaction یا همون واکنش رویدادی است که با کلیک روی یک منطقه یا المان خاص میشه به صفحه دیگه پیمایش کرد و حالتی شبیه نمایش واقعی رو درش دید . همچنین میشه تمام المان های متریال دیزاین رو هم به صفحه اضافه کرد و اگه دوست دارید فقط wireframe بسازید هم تمام المان ها به این صورت دردسترس هست . کافیه یه حساب کاربری ایجاد کنید و از طراحیتون لذت ببرید


شما هم اگه اپ یا سایت دیگه ای میشناسید معرفی کنید ...

۰ نظر موافقین ۱ مخالفین ۰
مرتضی درزی