<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Ali Gadimi</title>
        <link>https://virgool.io/feed/@aligadimi</link>
        <description>یه برنامه نویس عاشق تکنولوژی, فیزیک و یخورده فلسفه</description>
        <language>fa</language>
        <pubDate>2026-06-16 14:52:10</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/177124/avatar/tGsplS.png?height=120&amp;width=120</url>
            <title>Ali Gadimi</title>
            <link>https://virgool.io/@aligadimi</link>
        </image>

                    <item>
                <title>نکاتی در ساخت ویو انیمیشن دار اندروید با ValueAnimator</title>
                <link>https://virgool.io/@aligadimi/%D9%86%DA%A9%D8%A7%D8%AA%DB%8C-%D8%AF%D8%B1-%D8%B3%D8%A7%D8%AE%D8%AA-%D9%88%DB%8C%D9%88-%D8%A7%D9%86%DB%8C%D9%85%DB%8C%D8%B4%D9%86-%D8%AF%D8%A7%D8%B1-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-%D8%A8%D8%A7-valueanimator-eo4fb1ocmoat</link>
                <description>وقتی میخوایم یه ویو جدیدی بسازیم و قراره انیمیشن داشته باشه، کنترل تایمر یه موضوع خیلی مهمه که میتونه ایرادات زیادی وارد کنه و دردسر ساز باشه. باید کارایی که در هر فریم انجام میشه رو کاهش بدیم که بتونیم انیمیشن روان تری داشته باشیم.برای انیمیشن و تایمر از ValueAnimator استفاده می‌کنیم. حالا ValueAnimation چیه؟!انیمیشن‌ها معمولا دو قسمت دارن. یکی آپدیت مقادیری که دارن انیمیت می‌کنن و یکی آپدیت UI طبق اون مقادیری که آپدیت شده‌ان. ValueAnimator موتور اصلی زمان بندی انیمیشن‌ها هست که فقط قسمت اول رو انجام می‌ده و برای استفاده‌اش باید از listenerهاش استفاده کنین و تغییرات ui رو خودتون انجام بدین. برای این پست از ریپو زیر به عنوان مثال استفاده می‌کنم. https://github.com/itsaligadimi/LoadingDotBar سه تابع مهمی که داریم init, onMeasure, onDraw هست که تابع onDraw در هر دور انیمیشن اجرا خواهد شد پس باید کارای داخل اون رو به حداقل برسونیم تا عملکرد بهتری داشته باشیم. پس برای انجام محاسبات و مقداردهی‌های اولیه از توابع init و onMeasure استفاده می‌کنیم.private void init()
{
    movementRange = barHeight - (2 * dotRadius);

    dotbarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    dotbarPaint.setColor(dotColor);

    animator = ValueAnimator.ofInt(0, 7 * (movementRange / 2));
    animator.setDuration(duration);
    animator.addUpdateListener(this);
    animator.addListener(this);
}ابتدا یه محاسبه کوچیک برای تعیین مقادیری که انیمیت خواهند شد انجام می‌دیم.بعد شی paint رو می‌سازیم که تو onDraw در هر فریم استفاده خواهد شد پس یک بار برای همیشه تولیدش می‌کنیم تا از تکرار جلوگیری بشه.در آخر animator رو می‌سازیم که قراره مقداری از نوع int رو از 0 تا یک عددی که برحسب ارتفاع ویو مون محاسبه میشه، انیمیت کنه در زمان تعیین شده. در هربار آپدیت مقدار، توسط یه listener از اون مقدار با خبر می‌شیم و ویو مون رو آپدیت می‌کنیم. برای listener از ValueAnimator.AnimatorUpdateListener استفاده می‌کنیم که در هر آپدیت تابع onAnimationUpdate صدا زده میشه و می‌تونیم مقداری که آپدیت شده رو مثل خط زیر استفاده‌اش کنیم.int value = (int) animation.getAnimatedValue();من از Animator.AnimatorListener هم استفاده کرده‌ام که از شروع، پایان و تکرار انیمیشن با خبر می‌شیم که من در مثال LoadingDotBar فقط به پایانش احتیاج داشتم.protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    int padLeft = getPaddingLeft();
    int padTop = getPaddingTop();
    int padRight = getPaddingRight();
    int padBottom = getPaddingBottom();

    //calculate the view size
    int width = (3 * 2 * dotRadius) + // 3 dots * 2 radius
            (2 * gapSize) + // 2 gaps
            padLeft +
            padRight;
    int height = barHeight + padTop + padBottom;

    //calculate positions and helper sizes
    halfHeight = height / 2;
    dotOneX = padLeft + dotRadius;
    dotTwoX = padLeft + (3 * dotRadius) + gapSize;
    dotThreeX = padLeft + (5 * dotRadius) + (2 * gapSize);

    setMeasuredDimension(width, height);
}تابع onMeasure هدفش اینه که تصمیم بگیریم اندازه ویو چقدر خواهد بود. دو ورودی widthMeasureSpec و heightMeasureSpec هرکدام شامل دو نوع اطلاعات هستند که بصورت زیر می‌توان اطلاعات رو استخراج کردint mode = MeasureSpec.getMode(widthMeasureSpec);
int size = MeasureSpec.getSize(widthMeasureSpec);اینجا mode می‌تونه سه تا مقدار داشته باشه:UNSPECIFIEDیعنی پدر هیچ محدودیتی برای سایز تعیین نکرده و ویو می‌تونه هر سایزی داشته باشه.EXACTLYیعنی پدر اندازه دقیقی برای فرزند انتخاب کرده و در هر شرایطی فرزند در اون محدوده خواهد بود.AT_MOSTفرزند می‌تونه هر سایزی که خواست بگیره در محدوده ای که پرد تعیین کرده باشه. پدر یه اندازه حداکثیر تعیین کرده.با دونستن اینا و اندازه ای که ما برای ویو نیاز داریم، محاسبات لازم رو انجام میدیم و اندازه نهایی رو تصمیم میگیریم و با تابع setMeasuredDimension تصمیمون رو اعلام می‌کنیم.private void drawBar(Canvas canvas, int barXCenter, int barHeight)
{
    if (barHeight == 0)
    {
        canvas.drawCircle(barXCenter, halfHeight, dotRadius, dotbarPaint);
    } 
    else if (barHeight == 1)
    {
        canvas.drawCircle(barXCenter, halfHeight, dotRadius, dotbarPaint);
        canvas.drawCircle(barXCenter, halfHeight + 1, dotRadius, dotbarPaint);
    } 
    else
    {
        int halfBarHeight = barHeight / 2;
        canvas.drawCircle(barXCenter, halfHeight + halfBarHeight, dotRadius, dotbarPaint);
        canvas.drawCircle(barXCenter, halfHeight - halfBarHeight, dotRadius, dotbarPaint);
        canvas.drawRect(barXCenter - dotRadius,
                halfHeight + halfBarHeight,
                barXCenter + dotRadius,
                halfHeight - halfBarHeight,
                dotbarPaint);
    }
}اینجا هم که کار نهایی و کشیدن ویو روی canvas رو انجام می‌دیم که خیلی وارد جزئیات این قسمت نمی‌شم. شرط‌ها برای اینه که اگر دو تا دایره‌ها دقیقا روی هم بیافتن، یکی رو نکشیم که کار رو کمتر کرده باشیم.و در آخر برای اینکه هربار بعد از آپدیت شدن مقادیر توسط animator ویو رو دوباره بکشیم و از invalidate در آخر تابع onAnimationUpdate استفاده می‌کنیم.خببب همیننن. اگر جزئیات بیشتری درمورد هر بخشی از این پست یا کلا بحث‌های دیگه خواستین، می‌تونین تو نظرات بهم بگین. یادتون نره به کاراتون انیمیشن اضافه کنید و فعلا تا یه پست دیگه.   ??</description>
                <category>Ali Gadimi</category>
                <author>Ali Gadimi</author>
                <pubDate>Sun, 23 Aug 2020 18:27:34 +0430</pubDate>
            </item>
                    <item>
                <title>کنترل ورژن apk اندروید با گردل</title>
                <link>https://virgool.io/MobileLab/%DA%A9%D9%86%D8%AA%D8%B1%D9%84-%D9%88%D8%B1%DA%98%D9%86-apk-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-%D8%A8%D8%A7-%DA%AF%D8%B1%D8%AF%D9%84-zx8pfg0sur4k</link>
                <description>میشه گفت یکی از اون دردسرهاییه که همیشه داریم و هممون مجبور شدیم یجوری دستی کنترلش کنیم. ولی خب مثلا برنامه نویسیم هااا چرا دستی؟!؟! میتونیم با یه تیکه کد گردل حلش کنیم و دیگه از بقیه نشنویم &quot;برنامه ات نصب نمیشه!!&quot; :| what da ffffffffffوقتی نسخه جدیدی تولید میکنیم، versionCode رو افزایش میدیم و apk رو تولید میکنیم ولی همه فایلهایی که تولید میشن اسمشون app-release.apk و گاها اشتباهی رخ میده و نسخه قدیمی میره برای تست و نتیجه این میشه که یا نصب نمیشه یا هیچی تغییر نکرده. واس همین بهتره از این تیکه کد استفاده کنیم و فایلهای خروجی با اسمهای مناسب تولید بکنیم.اینم تیکه کدی که گفتمچند تا متغیر اولی که برای مشخص کردن ورژن اپلیکیشن هستن و از این به بعد فقط قراره این متغیرها رو ست کنین و فایل خروجی با نام و ورژن مناسب تولید خواهد شد. این که چجوری این عددها رو تغییر بدین بسته به شرایط و تصمیم خودتونه ولی خب پایین یه مثاله که حسابش دستتون بیاد.ext.versionMajor: مشخص میکنه که تغییرات بزرگی انجام شده و فیچر جدید اضافه شدهext.versionMinor: مشخص میکنه که تغییرات کوچیکی انجام شدهext.versionPatch: اینم برای رفع باگ و تغییرات خیلی کوچیکext.versionClassifier: از این برای مشخص کردن وضعیت اپلیکیشن استفاده میشهمقادیرش میتونه alpha, beta, snapshot, release و یه همچین چیزایی باشه.ext.isSnapshot: اینم اگه ترو باشه یعنی وضعیت مناسب برای انتشار نیست و همچین چیزیapplicationVariants.all { variant -&gt;
   variant.outputs.all {
      outputFileName = &amp;quot${fileName}-${variant.versionName}.apk&amp;quot
   }    
}این تیکه مشخص میکنه نام فایل رو چجوری ایجاد کنهversionCode generateVersionCode()
versionName generateVersionName()اینم از توابعی که پایین می بینیم استفاده میکنه تا versionCode و versionName رو برای اپلیکیشن مشخص کنه و اینطوری اروری هنگام نصب پیش نمیاد.private Integer generateVersionCode() {
    return ext.versionMajor + ext.versionMinor + ext.versionPatch
}private String generateVersionName() {
    String versionName = &amp;quot${ext.versionMajor}.${ext.versionMinor}.${ext.versionPatch}&amp;quot
    if (ext.versionClassifier == null &amp;&amp; ext.isSnapshot) {
        ext.versionClassifier = &amp;quotSNAPSHOT&amp;quot
    }
    if (ext.versionClassifier != null) {
        versionName += &amp;quot.&amp;quot + ext.versionClassifier
    }
    return versionName;
}اینم که توضیح خاصی نمی خواد چیز ساده ایه.میشه کارای تولید فایل apk رو هم با گردل یه buildscript بنویسیم با یوزر پس و آدرس فایل کلیدمون و یه تسکش کنیم که با اجرای یه تسک همه این کارا انجام بشه. ولی حالا شاید تو یه پست دیگه. فعلا ;)</description>
                <category>Ali Gadimi</category>
                <author>Ali Gadimi</author>
                <pubDate>Thu, 04 Jun 2020 12:54:01 +0430</pubDate>
            </item>
            </channel>
</rss>