ساخت و طراحی پروگرس بار progressBar پیشرفته در اندروید
1397-10-09
رابط کاربری اپلیکیشن موزیک پلیر برای ios با Adobe XD
رابط کاربری UI اپلیکیشن موزیک پلیر برای ios با Adobe XD
1397-10-13

آموزش گرفتن اسکرین شات با کاتلین در اندروید + سورس کد

آموزش گرفتن اسکرین شات با کاتلین در اندروید

آموزش گرفتن اسکرین شات با کاتلین در اندروید

یکی از کاربردی ترین عملکردها , اسکرین شات گرفتن از صفحه موبایل هست که کد نویسی چندان پیچیده ای هم نداره ! امروز ما گرفتن اسکرین شات با کاتلین در اندروید به همراه سورس کد گرفتن screenshot با زبان کاتلین در اندروید را به شما در قالب مثال آموزش خواهیم داد. در این مثال دو نوع اسکرین شات رو آوردیم که خیلی کاربردی تر میشه داستان ! چرا که آزادی عمل بیشتری بدست میاریم.

یک نوع اسکرین شات از لایه (تنها محتویات در لایه ای که شما تصمیم میگیرد چه لایه ای باشه !! فقط کافیه که از نوادگان کلاس View باشه :))  )

و نوع دیگه اسکرین شات از تمام صفحه (که قبلا هم زیاد دیدیم!)

آموزش گرفتن اسکرین شات با کاتلین

خب بریم سراغ پروژه

محتویات فایل string.xml بصورت زیر هست

<resources>
    <string name="app_name">Screenshot App</string>
    <string name="take_screen_shot_activity">شات از صفحه</string>
    <string name="take_screen_shot_view">شات از لایه</string>
    <string name="take_save_screen_shot">ذخیره</string>
    <string name="reset">پاک کردن</string>
    <string name="toast_message_screenshot">ابتدا یک اسکرین شات بگیرید</string>
    <string name="toast_message_screenshot_success">اسکرین شات با موفقیت ثبت شد</string>
    <string name="settings_message">لطفا مجوز دسترسی را در تنظیمات بدهید</string>
</resources>

 

محتویات فایل colors.xml نیز بصورت زیر هست

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#882D60</color>
    <color name="colorPrimary2">#ac3879</color>
    <color name="colorPrimaryDark">#440026</color>
    <color name="colorAccent">#CD88AF</color>
    <color name="white">#ffffff</color>
    <color name="gray">#c7c7c7</color>
</resources>

خب از حواشی بگذریم الان باید بریم سراغ لایه اصلی اپ یعنی activity_main.xml که بصورت زیر با کانسترینت لیوت (که یه تنه میتونه جای چندین لینر لیوت یا ریلتیو لیوت صفحه رو مدیریت کنه و پیشنهاد میدم حتما بهش مسلط شید) طراحی شده

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                             xmlns:app="http://schemas.android.com/apk/res-auto"
                                             xmlns:tools="http://schemas.android.com/tools"
                                             android:id="@+id/parentView"
                                             android:layout_width="match_parent"
                                             android:layout_height="match_parent"
                                             android:padding="16dp"
                                             tools:context=".MainActivity">

    <Button
            android:id="@+id/buttonScreenshotActivity"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/take_screen_shot_activity"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:background="@color/colorPrimary"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintHorizontal_bias="0.5" app:layout_constraintEnd_toStartOf="@+id/buttonScreenshotView"
            app:layout_constraintHorizontal_chainStyle="packed" android:layout_marginTop="16dp"
            app:layout_constraintTop_toTopOf="parent" android:layout_marginEnd="5dp" android:layout_marginRight="5dp"/>
    <Button
            android:id="@+id/buttonScreenshotView"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/take_screen_shot_view"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:background="@color/colorPrimary2"
            app:layout_constraintStart_toEndOf="@+id/buttonScreenshotActivity"
            app:layout_constraintHorizontal_bias="0.5" app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginTop="16dp" app:layout_constraintTop_toTopOf="parent"
    />
    <Button
            android:id="@+id/buttonSaveScreenshot"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/take_save_screen_shot"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:background="@color/colorAccent"
            app:layout_constraintStart_toStartOf="parent" app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintEnd_toStartOf="@+id/buttonReset"
            app:layout_constraintHorizontal_chainStyle="packed" android:layout_marginEnd="5dp"
            android:layout_marginRight="5dp" android:layout_marginTop="16dp"
            app:layout_constraintTop_toBottomOf="@+id/buttonScreenshotActivity"/>
    <Button
            android:id="@+id/buttonReset"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/reset"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:background="@color/gray"
            app:layout_constraintStart_toEndOf="@+id/buttonSaveScreenshot"
            app:layout_constraintHorizontal_bias="0.5" app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginTop="16dp" app:layout_constraintTop_toBottomOf="@+id/buttonScreenshotView"/>

    <ImageView
            android:id="@+id/imageViewShowScreenshot"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginEnd="8dp" android:layout_marginRight="8dp"
            app:layout_constraintStart_toStartOf="parent" android:layout_marginLeft="8dp"
            android:layout_marginStart="8dp" app:layout_constraintTop_toBottomOf="@+id/buttonReset"
            android:layout_marginBottom="16dp" app:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginTop="16dp"/>

</android.support.constraint.ConstraintLayout>

و حالا یکی از کلاس های اصلی مورد استفاده در این پروژه و (پروژه های دیگر) با عنوان FileUtil.kt که وظیفه مدیریت عکس ایجاد شده رو به عهده داره که در این پروژه فقط کافیه که اون رو ذخیره کنه روی حافظه

package dn.marjan.screenshotapp

import android.graphics.Bitmap
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException


class FileUtil {

    /**
     * Stores the given [Bitmap] to a path on the device.
     *
     * @param bitmap   The [Bitmap] that needs to be stored
     * @param filePath The path in which the bitmap is going to be stored.
     */
    fun storeBitmap(bitmap: Bitmap, filePath: String) {
        val imageFile = File(filePath)
        imageFile.parentFile.mkdirs()
        try {
            val fout = FileOutputStream(imageFile)
            bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout)
            fout.flush()
            fout.close()
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
        } catch (e: IOException) {
            e.printStackTrace()
        }

    }

    companion object {

        private var mInstance: FileUtil? = null

        fun getInstance():FileUtil{
           if (mInstance == null) {
               synchronized(FileUtil::class.java) {
                   if (mInstance == null) {
                       mInstance = FileUtil()
                   }
               }
           }
           return mInstance!!
       }
    }
}

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

package dn.marjan.screenshotapp

import android.app.Activity
import android.graphics.Bitmap
import android.view.View.MeasureSpec
import android.view.View


class ScreenshotUtil  {

    /**
     * Measures and takes a screenshot of the provided [View].
     *
     * @param view The view of which the screenshot is taken
     * @return A [Bitmap] for the taken screenshot.
     */
    fun takeScreenshotForView(view: View): Bitmap {
        view.measure(
            MeasureSpec.makeMeasureSpec(view.width, MeasureSpec.EXACTLY),
            MeasureSpec.makeMeasureSpec(view.height, MeasureSpec.EXACTLY)
        )
        view.layout(
            view.x.toInt(),
            view.y.toInt(),
            view.x.toInt() + view.measuredWidth,
            view.y.toInt() + view.measuredHeight
        )

        view.isDrawingCacheEnabled = true
        view.buildDrawingCache(true)
        val bitmap = Bitmap.createBitmap(view.drawingCache)
        view.isDrawingCacheEnabled = false

        return bitmap
    }

    fun takeScreenshotForScreen(activity: Activity): Bitmap {
        return takeScreenshotForView(activity.window.decorView.rootView)
    }

    companion object {
        private  var mInstance: ScreenshotUtil? = null

        public fun getInstance(): ScreenshotUtil? {
            if (mInstance == null) {
                synchronized(ScreenshotUtil::class.java) {
                    if (mInstance == null) {
                        mInstance = dn.marjan.screenshotapp.ScreenshotUtil()
                    }
                }
            }
            return mInstance
        }
    }
}

و در انتها هم کلاس اکتیویتی اصلی

package dn.marjan.screenshotapp

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import com.karumi.dexter.PermissionToken
import android.widget.Toast
import android.Manifest;
import android.graphics.Bitmap;
import android.os.Environment;
import android.view.View;

import com.karumi.dexter.Dexter;
import com.karumi.dexter.listener.PermissionDeniedResponse;
import com.karumi.dexter.listener.PermissionGrantedResponse;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.single.PermissionListener
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity(), View.OnClickListener {

    private val activity = this@MainActivity


    private var bitmap: Bitmap? = null


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


        // initializing the listeners
        initListeners()


    }

    /**
     * method to initialize the listeners
     */
    private fun initListeners() {

        buttonScreenshotActivity.setOnClickListener(this)
        buttonScreenshotView.setOnClickListener(this)
        buttonSaveScreenshot.setOnClickListener(this)
        buttonReset.setOnClickListener(this)

    }

    /**
     * method for click listener
     *
     * @param view
     */
    override fun onClick(view: View) {

        when (view.id) {
         // Take ScreenshotUtil for activity
            R.id.buttonScreenshotActivity -> {
                bitmap = ScreenshotUtil.getInstance()!!
                    .takeScreenshotForScreen(activity) 
                imageViewShowScreenshot!!.setImageBitmap(bitmap)
            }
            // Take ScreenshotUtil for any view
            R.id.buttonScreenshotView -> {
                bitmap = ScreenshotUtil.getInstance()!!
                    .takeScreenshotForView(buttonScreenshotView)
                imageViewShowScreenshot!!.setImageBitmap(bitmap)
            }

            R.id.buttonSaveScreenshot -> requestPermissionAndSave()

            R.id.buttonReset -> {
                bitmap = null
                imageViewShowScreenshot!!.setImageBitmap(bitmap)
            }
        }
    }


    /**
     * Requesting storage permission
     * Once the permission granted, screen shot captured
     * On permanent denial show toast
     */
    private fun requestPermissionAndSave() {

        Dexter.withActivity(this)
            .withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
            .withListener(object : PermissionListener {
                override fun onPermissionGranted(response: PermissionGrantedResponse) {

                    if (bitmap != null) {
                        val path = Environment.getExternalStorageDirectory().toString() 
                        + "/test.png"
                        FileUtil.getInstance().storeBitmap(bitmap!!, path)
                        Toast.makeText(
                            activity,
                            getString(R.string.toast_message_screenshot_success)
                                    + " " + path,
                            Toast.LENGTH_LONG
                        ).show()
                    } else {
                        Toast.makeText(activity, getString(R.string.toast_message_screenshot)
                            , Toast.LENGTH_LONG).show()
                    }

                }

                override fun onPermissionDenied(response: PermissionDeniedResponse) {
                    // check for permanent denial of permission
                    if (response.isPermanentlyDenied) {
                        Toast.makeText(activity, getString(R.string.settings_message)
                            , Toast.LENGTH_LONG).show()
                    }
                }

                override fun onPermissionRationaleShouldBeShown(permission: PermissionRequest
                                                                , token: PermissionToken) {
                    token.continuePermissionRequest()
                }
            }).check()
    }
}

 

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

implementation 'com.karumi:dexter:5.0.0'

 

در انتها کافیه پروژه رو ران کنید و خروجی بگیرید !

 

آموزش گرفتن اسکرین شات با کاتلین در اندروید

آموزش گرفتن اسکرین شات با کاتلین در اندروید

امیدوارم این آموزش براتون مفید بوده باشه و ازش استفاده کنید. از طریق راه های ارتباطی زیر میتونید با ما برای درخواست آموزش های اختصاصی و انواع پروژه ها در ارتباط باشید.

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *