برنامه نویسی اندروید

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

برنامه نویسی اندروید

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

۵ مطلب در دی ۱۴۰۰ ثبت شده است

قبلا شیوه نمایش یک عکس در یک ImageView توسط کد را آموزش دادیم. گاهی نیاز داریم که بررسی کنیم که آیا یک عکس وجود دارد یا خیر و در صورت وجود داشتن در پوشه drawable ، آنگاه عکس در ImageView نمایش داده شود. برای این منظور می توانیم از ترکیب try و catch استفاده کنیم. این ترکیب، زمانی به کار می رود که یک سری دستور داریم و می خواهیم در صورتی که در هنگام اجرای آنها، خطایی رخ داد، آنگاه یک سری دستور دیگر نمایش داده شود.

با فرض اینکه ImageView دارای id با نام imageView1 باشد و نام عکس مورد نظرمان که در پوشه drawable قرار گرفته است، برابر image_1 باشد (با پسوند دلخواه، مثلا png)، آنگاه کدهای زیر را می نویسیم :

 
ImageView img = (ImageView) findViewById(R.id.imageView1);
String imageName = "image_1";  
try {
    int resID = getResources().getIdentifier(imageName,"drawable",getPackageName());
    img.setImageResource(resID);
} catch (Exception e) {
}
  • vahid hasani

در این مبحث، عنصر ImageView را توسعه (extend) می دهیم و یک عنصر جدید با نام TouchImageView می سازیم که ویزگی های ImageView را دارد و در عین حال، دارای قابلیت بزرگنمایی (zoom) دو انگشتی نیز می باشد.

در این پروژه اندروید، کدهای کلاس TouchImageView.java را بنده قبلا از یک سایت انگلیسی زبان گرفته بودم، اما متاسفانه آدرس آن را به خاطر ندارم که لینک منبع را ذکر کنم.

به عنوان یک مثال، پس از ساخت عنصر TouchImageView ، عکس زیر را در آن قرار می دهیم :

ایجاد امکان بزرگنمایی (zoom) دو انگشتی برای عکس نمایش داده شده در ImageView ، با توسعه عنصر ImageView ، در برنامه نویسی اندروید

گوشی را می چرخانیم تا عکس، بهتر نمایش داده شود (بخش بیشتری از عنصر را بپوشاند) :

ایجاد امکان بزرگنمایی (zoom) دو انگشتی برای عکس نمایش داده شده در ImageView ، با توسعه عنصر ImageView ، در برنامه نویسی اندروید

سپس با استفاده از قابلیت بزرگنمایی (zoom) دو انگشتی، بخشی از عکس را بزرگتر نمایش می دهیم :

ایجاد امکان بزرگنمایی (zoom) دو انگشتی برای عکس نمایش داده شده در ImageView ، با توسعه عنصر ImageView ، در برنامه نویسی اندروید

 

در ادامه، بخش های مهم پروژه اندروید را شرح می دهیم.

در برنامه eclipse ، ابتدا یک پروژه اندروید با نام ImageViewZoom می سازیم (نام package را برابر com.kelidestan.imageviewzoom انتخاب می کنیم. نام Activity اصلی را برابر MainActivity انتخاب می کنیم و فایل xml متناظر آن را هم برابر activity_main قرار می دهیم).

یک عکس با نام image.jpg را در پوشه drawable-hdpi قرار می دهیم (همان عکسی که می خواهیم نمایش داده شود) :

ایجاد امکان بزرگنمایی (zoom) دو انگشتی برای عکس نمایش داده شده در ImageView ، با توسعه عنصر ImageView ، در برنامه نویسی اندروید

همان طور که گفتیم، باید عنصر ImageView را توسعه (extend) بدهیم و یک عنصر جدید با نام دلخواه TouchImageView بسازیم. برای این منظور، یک کلاس (class) با نام TouchImageView بسازیم :

ایجاد امکان بزرگنمایی (zoom) دو انگشتی برای عکس نمایش داده شده در ImageView ، با توسعه عنصر ImageView ، در برنامه نویسی اندروید

کدهای فایل TouchImageView.java را به صورت زیر می نویسیم :

 



import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ImageView;

public class TouchImageView extends ImageView {

    Matrix matrix;

    // We can be in one of these 3 states
    static final int NONE = 0;
    static final int DRAG = 1;
    static final int ZOOM = 2;
    int mode = NONE;

    // Remember some things for zooming
    PointF last = new PointF();
    PointF start = new PointF();
    float minScale = 1f;
    float maxScale = 3f;
    float[] m;


    int viewWidth, viewHeight;
    static final int CLICK = 3;
    float saveScale = 1f;
    protected float origWidth, origHeight;
    int oldMeasuredWidth, oldMeasuredHeight;


    ScaleGestureDetector mScaleDetector;

    Context context;

    public TouchImageView(Context context) {
        super(context);
        sharedConstructing(context);
    }

    public TouchImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        sharedConstructing(context);
    }
   
    private void sharedConstructing(Context context) {
        super.setClickable(true);
        this.context = context;
        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
        matrix = new Matrix();
        m = new float[9];
        setImageMatrix(matrix);
        setScaleType(ScaleType.MATRIX);

        setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mScaleDetector.onTouchEvent(event);
                PointF curr = new PointF(event.getX(), event.getY());

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        last.set(curr);
                        start.set(last);
                        mode = DRAG;
                        break;
                       
                    case MotionEvent.ACTION_MOVE:
                        if (mode == DRAG) {
                            float deltaX = curr.x - last.x;
                            float deltaY = curr.y - last.y;
                            float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale);
                            float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale);
                            matrix.postTranslate(fixTransX, fixTransY);
                            fixTrans();
                            last.set(curr.x, curr.y);
                        }
                        break;

                    case MotionEvent.ACTION_UP:
                        mode = NONE;
                        int xDiff = (int) Math.abs(curr.x - start.x);
                        int yDiff = (int) Math.abs(curr.y - start.y);
                        if (xDiff < CLICK && yDiff < CLICK)
                            performClick();
                        break;

                    case MotionEvent.ACTION_POINTER_UP:
                        mode = NONE;
                        break;
                }
               
                setImageMatrix(matrix);
                invalidate();
                return true; // indicate event was handled
            }

        });
    }

    public void setMaxZoom(float x) {
        maxScale = x;
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            mode = ZOOM;
            return true;
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float mScaleFactor = detector.getScaleFactor();
            float origScale = saveScale;
            saveScale *= mScaleFactor;
            if (saveScale > maxScale) {
                saveScale = maxScale;
                mScaleFactor = maxScale / origScale;
            } else if (saveScale < minScale) {
                saveScale = minScale;
                mScaleFactor = minScale / origScale;
            }

            if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight)
                matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2);
            else
                matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());

            fixTrans();
            return true;
        }
    }

    void fixTrans() {
        matrix.getValues(m);
        float transX = m[Matrix.MTRANS_X];
        float transY = m[Matrix.MTRANS_Y];
       
        float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);
        float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale);

        if (fixTransX != 0 || fixTransY != 0)
            matrix.postTranslate(fixTransX, fixTransY);
    }

    float getFixTrans(float trans, float viewSize, float contentSize) {
        float minTrans, maxTrans;

        if (contentSize <= viewSize) {
            minTrans = 0;
            maxTrans = viewSize - contentSize;
        } else {
            minTrans = viewSize - contentSize;
            maxTrans = 0;
        }

        if (trans < minTrans)
            return -trans + minTrans;
        if (trans > maxTrans)
            return -trans + maxTrans;
        return 0;
    }
   
    float getFixDragTrans(float delta, float viewSize, float contentSize) {
        if (contentSize <= viewSize) {
            return 0;
        }
        return delta;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        viewWidth = MeasureSpec.getSize(widthMeasureSpec);
        viewHeight = MeasureSpec.getSize(heightMeasureSpec);
       
        //
        // Rescales image on rotation
        //
        if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight
                || viewWidth == 0 || viewHeight == 0)
            return;
        oldMeasuredHeight = viewHeight;
        oldMeasuredWidth = viewWidth;

        if (saveScale == 1) {
            //Fit to screen.
            float scale;

            Drawable drawable = getDrawable();
            if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0)
                return;
            int bmWidth = drawable.getIntrinsicWidth();
            int bmHeight = drawable.getIntrinsicHeight();
           
            Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);

            float scaleX = (float) viewWidth / (float) bmWidth;
            float scaleY = (float) viewHeight / (float) bmHeight;
            scale = Math.min(scaleX, scaleY);
            matrix.setScale(scale, scale);

            // Center the image
            float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight);
            float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth);
            redundantYSpace /= (float) 2;
            redundantXSpace /= (float) 2;

            matrix.postTranslate(redundantXSpace, redundantYSpace);

            origWidth = viewWidth - 2 * redundantXSpace;
            origHeight = viewHeight - 2 * redundantYSpace;
            setImageMatrix(matrix);
        }
        fixTrans();
    }
}

به این خط از کدها توجه کنید :

 

public class TouchImageView extends ImageView {

این خط از کدها بیان می کند که کلاس TouchImageView بر اساس توسعه (extend) کلاس ImageView (عنصر ImageView) ساخته شود.

چون یک عنصر جدید ساخته ایم، باید در فایل xml مربوط به Activity (یعنی فایل activity_main.xml)، عنصر TouchImageView را به جای عنصر ImageView به کار ببریم (در واقع، برای هر عکسی که می خواهیم قابلیت بزرگنمایی دو انگشتی داشته باشد) :

ایجاد امکان بزرگنمایی (zoom) دو انگشتی برای عکس نمایش داده شده در ImageView ، با توسعه عنصر ImageView ، در برنامه نویسی اندروید

بنابراین، کدهای فایل activity_main.xml را به صورت زیر می نویسیم :

 

<LinearLayout 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"
    tools:context=".MainActivity" >

    <com.too.imageviewzoom.TouchImageView
            android:id="@+id/touchImageView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

</LinearLayout>

نکته مهم در کد بالا این است که ما به جای نام TouchImageView ، نام زیر را برای عنصر نوشته ایم :

 

com.too.imageviewzoom.TouchImageView

که در آن، com.kelidestan.imageviewzoom برابر همان نام package برنامه اندروید ما می باشد، بنابراین دقت داشته باشید که در برنامه اندروید خود، ابتدا نام package برنامه خود را بنویسید و سپس نام TouchImageView را در انتهای آن قرار بدهید (اگر نام package را اشتباه بنویسید، یک خطا به وجود می آید و برنامه اندروید با Force Close روبرو می شود).

و در آخر، به سراغ فایل مربوط به Activity برنامه می رویم (یعنی فایل MainActivity.java) :

ایجاد امکان بزرگنمایی (zoom) دو انگشتی برای عکس نمایش داده شده در ImageView ، با توسعه عنصر ImageView ، در برنامه نویسی اندروید

کدهای فایل MainActivity.java را به صورت زیر می نویسیم :

 



import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
               
                TouchImageView img = (TouchImageView) findViewById(R.id.touchImageView);
                img.setImageResource(R.drawable.image);
                img.setMaxZoom(4f);
        }


}

مشاهده می کنید که در هنگام تعریف عنصر TouchImageView در فایل java ، به صورت زیر عمل شده است :

 

TouchImageView img = (TouchImageView) findViewById(R.id.touchImageView);
  • vahid hasani

فرض کنید که یک متغیر int با نام num داریم و می خواهیم که آن را به متغیر String تبدیل کنیم، برای این منظور، کدهای زیر را می نویسیم :

 
int num = 1234;  
String str = String.valueOf(num);

بنابراین یک رشته (String) با نام str خواهیم داشت که مقدار 1234 در آن ذخیره شده است.

  • vahid hasani

فرض کنید که در فایل strings.xml ، یک آرایه رشته ای با نام string_array_1 ، به صورت زیر تعریف کرده ایم :

 

<string name="number_1">string number 1</string>
<string name="number_2">string number 2</string>
<string name="number_3">string number 3</string>

<string-array name="string_array_1">
     <item>@string/number_1</item>
     <item>@string/number_2</item>
     <item>@string/number_3</item>      
</string-array>

اکنون برای دریافت آرایه رشته ای string_array_1 و ذخیره آن در یک متغیر، کدهای زیر را می نویسیم :

 

String[] my_string = getResources().getStringArray(R.array.string_array_1);

بنابراین اکنون یک متغیر با نام my_string داریم که به صورت آرایه ای از رشته ها (string array) است و می توانیم رشته های (strings) مورد نظرمان را از آن فراخوانی کنیم.

  • vahid hasani

با استفاده از کد زیر می توانیم نام تمامی رشته های (Strings) تعریف شده در فایل strings.xml در پروژه اندروید را به صورت یک آرایه (Array) از جنس رشته (String)، به دست آوریم :

 

Field[] fields = R.string.class.getFields();
String[] allStringsNames = new String[fields.length];
for (int  i =0; i < fields.length; i++) {          
    allStringsNames[i] = fields[i].getName();
}

بنابراین نام تمامی رشته های (Strings) تعریف شده در فایل strings.xml در پروژه اندروید را در آرایه ای با نام allStringsNames خواهیم داشت.

دقت شود که برای استفاده از کد بالا، package زیر را وارد (import) می کنیم (دستور کامل import را نوشته ایم) :

 
import java.lang.reflect.Field;
 

کپ

  • vahid hasani