আমি কীভাবে চিত্রগুলির জন্য জুম কার্যকারিতা পেতে পারি?


204

কোনও বড় চিত্র দেখানোর এবং ব্যবহারকারীকে জুম ইন এবং আউট এবং চিত্রটি প্যান করার জন্য কি সাধারণ উপায় আছে?

এখন পর্যন্ত আমি দুটি উপায় খুঁজে পেয়েছি:

  1. ওভাররাইটিং ইমেজভিউ, এমন একটি সাধারণ সমস্যার জন্য কিছুটা বেশি মনে হচ্ছে।
  2. ওয়েবভিউ ব্যবহার করা তবে সামগ্রিক বিন্যাসের উপর কম নিয়ন্ত্রণ সহ etc.

এখানে একটি জুম কন্ট্রোল (উইজেট) রয়েছে এবং প্যানিং পরিচালনা করতে আপনি অনটচ ইভেন্টটি শুনতে পারেন।
tobrien

1
অনুরূপ একটি প্রশ্ন stackoverflow.com/questions/2537396/... এই টিউটোরিয়ালের কোনো লিঙ্ক থাকে anddev.org/... । আপনি আপনার আইমজ প্যান করতে দরকারী হতে পারে। আমি এটিকে বিস্তারিতভাবে পড়িনি, তবে এটি আপনাকে জুম ফাংশনটি কীভাবে করবেন সে সম্পর্কেও কিছু ধারণা দিতে পারে।
স্টিভ হ্যালি

জুম করার সময় কেউ কি ছবিটি সংরক্ষণ করার চেষ্টা করেছেন? আমি জুমযুক্ত রাজ্যের পরিবর্তে একটি ডিফল্ট রাজ্যে সংরক্ষিত চিত্রটি চাই। দয়া করে আমার প্রশ্নটি দেখুন: স্ট্যাকওভারফ্লো.com/ জিজ্ঞাসা / 24730793/… ধন্যবাদ
ব্লেজ তামা

উত্তর:


208

হালনাগাদ

আমি সবেমাত্র টাচেমেজভিউকে একটি নতুন আপডেট দিয়েছি। এটিতে এখন প্যানিং এবং পিঞ্চ জুম ছাড়াও ডাবল ট্যাপ জুম এবং ফ্লিং অন্তর্ভুক্ত রয়েছে। নীচের কোডটি খুব তারিখের। আপনি সর্বশেষ কোড পেতে গিথুব প্রকল্পটি দেখতে পারেন।

, USAGE

আপনার প্রকল্পে টাচমিজভিউ.জভা রাখুন। এটি তখন ইমেজভিউয়ের মতোই ব্যবহার করা যেতে পারে। উদাহরণ:

TouchImageView img = (TouchImageView) findViewById(R.id.img);

আপনি যদি এক্সএমএলে টাচআইমেজভিউ ব্যবহার করছেন তবে আপনাকে অবশ্যই পুরো প্যাকেজের নাম সরবরাহ করতে হবে, কারণ এটি একটি কাস্টম ভিউ। উদাহরণ:

<com.example.touch.TouchImageView
    android:id="@+id/img”
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

দ্রষ্টব্য: আমি আমার পূর্ববর্তী উত্তরটি সরিয়েছি, যার মধ্যে বেশ কয়েকটি পুরানো কোড অন্তর্ভুক্ত ছিল এবং এখন গিথুবের সবচেয়ে আপডেট হওয়া কোডের সাথে সরাসরি লিঙ্ক করে।

ViewPager

আপনি যদি ভিউপ্যাজারে টাচআইমেজভিউ লাগাতে আগ্রহী হন তবে এই উত্তরটি দেখুন।


4
পাওলো, আমি পারফরম্যান্সের বিষয়গুলিতে অংশ নিই না, তবে আমি কোনও ট্যাবলেটে পরীক্ষা করতে পেলাম না। ধীর গতিতে, আপনি কি পিছিয়ে যাচ্ছেন? আমি অনস্কেলের শুরুতে একটি সর্বোচ্চ জুম ফ্যাক্টর সেট করলাম set এই আপনি কি কথা বলছেন? যদি তা না হয় তবে নিম্নলিখিতগুলি চেষ্টা করে দেখুন: 1. আপনি কি ডিবাগ মোডে আছেন? এটি এটি উল্লেখযোগ্যভাবে ধীর করবে। ২. আপনি কোন আকারের চিত্রগুলি সেট করছেন। আমি খুব বড় (8 মিমি) চিত্রের সাথে পরীক্ষা করিনি, তবে এটি এটিকে কমিয়ে দিতে পারে। ৩. আপনার কাছে এমন কোনও ফোন রয়েছে যা আপনি পরীক্ষা করতে পারেন? ৪. যদি সমস্ত কিছু ব্যর্থ হয়, দেখুন এমস্কেলফ্যাক্টরটিকে 2 (যদি> 1) বা 0.5 (যদি <1) দ্বারা গুণ করা হয় তবে আপনার পরিস্থিতি সাহায্য করে।
মাইক অরটিজ

3
@ আহসান ভিউ কনস্ট্রাক্টরকে এতে পরিবর্তন করুন: TouchImageView(Context context, AttributeSet attrs)এবং super(context, attrs);এটি কারণ কারণ আপনি যখন কাস্টম ভিউকে স্ফীত করেন, এটি কেবল একটি না হয়ে দুটি পরামিতি দিয়ে তৈরি করা হয়। যখন আমি এটির কাছাকাছি পৌঁছে যাব, তখন আমি তিনটি ভিউ কনস্ট্রাক্টর এবং ড্রয়যোগ্যদের সমর্থন করার জন্য টাচআইমেজভিউটি ঠিক করব।
মাইক অর্টিজ

2
@ আহসান যেহেতু এটি একটি কাস্টম ভিউ, তাই আপনাকে পুরো নামটি এক্সএমএল ফাইলে লিখতে হবে, অর্থাৎ <com.example.TouchImageView android:id="@+id/img" />। তুমি কি ওটা করেছ?
মাইক অর্টিজ

1
যুগ যুগ ধরে এটি সন্ধান করা এটি দুর্দান্ত জিনিস। গিথুব থেকে কোডটি ব্যবহার করুন কারণ এটি আরও সাম্প্রতিক এবং কেবল আরও ভাল কাজ করে
অ্যালেক্স

2
@ মাইকে আমি এই কোডটি চেষ্টা করেছি তবে কাস্টম গ্যালারী কাজ করে না। এই সমস্যাটি ঘিরে কি কোনও কৌশল রয়েছে?
উমেশ 4'12

80

আমি টাচআইমেজভিউ তৈরি করতে কিছু কোড মানিয়ে নিয়েছি যা মাল্টিটুচ (> ২.১) সমর্থন করে। এটি হ্যালো, অ্যান্ড্রয়েড বইটি দ্বারা অনুপ্রাণিত ! (তৃতীয় সংস্করণ)

এটি নীচের 3 টি ফাইলের মধ্যে রয়েছে টাচআইমেজভিউ.জ্যাভা র‌্যাপমোশনএভেন্ট.জাভা ইক্লেয়ারমোশনএভেন্ট.জভা

TouchImageView.java

import se.robertfoss.ChanImageBrowser.Viewer;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

public class TouchImageView extends ImageView {

    private static final String TAG = "Touch";
    // These matrices will be used to move and zoom image
    Matrix matrix = new Matrix();
    Matrix savedMatrix = new 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 start = new PointF();
    PointF mid = new PointF();
    float oldDist = 1f;

    Context context;


    public TouchImageView(Context context) {
        super(context);
        super.setClickable(true);
        this.context = context;

        matrix.setTranslate(1f, 1f);
        setImageMatrix(matrix);
        setScaleType(ScaleType.MATRIX);

        setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent rawEvent) {
                WrapMotionEvent event = WrapMotionEvent.wrap(rawEvent);

                // Dump touch event to log
                if (Viewer.isDebug == true){
                    dumpEvent(event);
                }

                // Handle touch events here...
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    savedMatrix.set(matrix);
                    start.set(event.getX(), event.getY());
                    Log.d(TAG, "mode=DRAG");
                    mode = DRAG;
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    oldDist = spacing(event);
                    Log.d(TAG, "oldDist=" + oldDist);
                    if (oldDist > 10f) {
                        savedMatrix.set(matrix);
                        midPoint(mid, event);
                        mode = ZOOM;
                        Log.d(TAG, "mode=ZOOM");
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    int xDiff = (int) Math.abs(event.getX() - start.x);
                    int yDiff = (int) Math.abs(event.getY() - start.y);
                    if (xDiff < 8 && yDiff < 8){
                        performClick();
                    }
                case MotionEvent.ACTION_POINTER_UP:
                    mode = NONE;
                    Log.d(TAG, "mode=NONE");
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mode == DRAG) {
                        // ...
                        matrix.set(savedMatrix);
                        matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
                    } else if (mode == ZOOM) {
                        float newDist = spacing(event);
                        Log.d(TAG, "newDist=" + newDist);
                        if (newDist > 10f) {
                            matrix.set(savedMatrix);
                            float scale = newDist / oldDist;
                            matrix.postScale(scale, scale, mid.x, mid.y);
                        }
                    }
                    break;
                }

                setImageMatrix(matrix);
                return true; // indicate event was handled
            }

        });
    }


    public void setImage(Bitmap bm, int displayWidth, int displayHeight) { 
        super.setImageBitmap(bm);

        //Fit to screen.
        float scale;
        if ((displayHeight / bm.getHeight()) >= (displayWidth / bm.getWidth())){
            scale =  (float)displayWidth / (float)bm.getWidth();
        } else {
            scale = (float)displayHeight / (float)bm.getHeight();
        }

        savedMatrix.set(matrix);
        matrix.set(savedMatrix);
        matrix.postScale(scale, scale, mid.x, mid.y);
        setImageMatrix(matrix);


        // Center the image
        float redundantYSpace = (float)displayHeight - (scale * (float)bm.getHeight()) ;
        float redundantXSpace = (float)displayWidth - (scale * (float)bm.getWidth());

        redundantYSpace /= (float)2;
        redundantXSpace /= (float)2;


        savedMatrix.set(matrix);
        matrix.set(savedMatrix);
        matrix.postTranslate(redundantXSpace, redundantYSpace);
        setImageMatrix(matrix);
    }


    /** Show an event in the LogCat view, for debugging */
    private void dumpEvent(WrapMotionEvent event) {
        // ...
        String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",
            "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
        StringBuilder sb = new StringBuilder();
        int action = event.getAction();
        int actionCode = action & MotionEvent.ACTION_MASK;
        sb.append("event ACTION_").append(names[actionCode]);
        if (actionCode == MotionEvent.ACTION_POINTER_DOWN
                || actionCode == MotionEvent.ACTION_POINTER_UP) {
            sb.append("(pid ").append(
                    action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
            sb.append(")");
        }
        sb.append("[");
        for (int i = 0; i < event.getPointerCount(); i++) {
            sb.append("#").append(i);
            sb.append("(pid ").append(event.getPointerId(i));
            sb.append(")=").append((int) event.getX(i));
            sb.append(",").append((int) event.getY(i));
            if (i + 1 < event.getPointerCount())
            sb.append(";");
        }
        sb.append("]");
        Log.d(TAG, sb.toString());
    }

    /** Determine the space between the first two fingers */
    private float spacing(WrapMotionEvent event) {
        // ...
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }

    /** Calculate the mid point of the first two fingers */
    private void midPoint(PointF point, WrapMotionEvent event) {
        // ...
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }
}

WrapMotionEvent.java

import android.view.MotionEvent;

public class WrapMotionEvent {
protected MotionEvent event;




    protected WrapMotionEvent(MotionEvent event) {
        this.event = event;
    }

    static public WrapMotionEvent wrap(MotionEvent event) {
            try {
                return new EclairMotionEvent(event);
            } catch (VerifyError e) {
                return new WrapMotionEvent(event);
            }
    }



    public int getAction() {
            return event.getAction();
    }

    public float getX() {
            return event.getX();
    }

    public float getX(int pointerIndex) {
            verifyPointerIndex(pointerIndex);
            return getX();
    }

    public float getY() {
            return event.getY();
    }

    public float getY(int pointerIndex) {
            verifyPointerIndex(pointerIndex);
            return getY();
    }

    public int getPointerCount() {
            return 1;
    }

    public int getPointerId(int pointerIndex) {
            verifyPointerIndex(pointerIndex);
            return 0;
    }

    private void verifyPointerIndex(int pointerIndex) {
            if (pointerIndex > 0) {
                throw new IllegalArgumentException(
                    "Invalid pointer index for Donut/Cupcake");
            }
    }

}

EclairMotionEvent.java

import android.view.MotionEvent;

public class EclairMotionEvent extends WrapMotionEvent {

    protected EclairMotionEvent(MotionEvent event) {
            super(event);
    }

    public float getX(int pointerIndex) {
            return event.getX(pointerIndex);
    }

    public float getY(int pointerIndex) {
            return event.getY(pointerIndex);
    }

    public int getPointerCount() {
            return event.getPointerCount();
    }

    public int getPointerId(int pointerIndex) {
            return event.getPointerId(pointerIndex);
    }
}

রবার্ট ফস, যদি এটি সীমানা বিচারক যুক্ত করে, তবে এটি আরও ভালভাবে পড়ে যেতে পারে your আপনাকে আপনার কোডটি খুব ভালভাবে ধন্যবাদ
Pengwang

3
এটি কাজ করে, কিন্তু আমি বিন্দু দেখতে পাচ্ছ না WrapMotionEventএবং EclairMotionEvent... যাহাই হউক না কেন +1।
সিপি

2
এটি সমর্থন করে এমন ফোনের জন্য মাল্টিটাইচ। অ্যান্ড্রয়েড <2.0 এর জন্য নিয়মিত স্পর্শ
রবার্ট ফস

দুর্দান্ত উদাহরণটি এটি দুর্দান্ত কাজ করে তবে ভিউয়ারের মধ্যে যা হয় তা আমি পাইনি (ভিউয়ার.আইসডিবগ == সত্য) {ডাম্পভেন্ট (ইভেন্ট); }
তোফিক আহমেদ

2
এটা কি? >> se.robertfoss.ChanI
छवि

60

আমি একটি ওয়েবভিউ ব্যবহার করেছি এবং মেমরির মাধ্যমে চিত্রটি লোড করেছি

webview.loadUrl("file://...")

ওয়েবভিউ সমস্ত প্যানিং জুমিং এবং স্ক্রোলিং পরিচালনা করে। যদি আপনি মোড়ানো_ কনটেন্ট ব্যবহার করেন তবে ওয়েবভিউটি বড় হবে না তবে চিত্র এবং কোনও সাদা অঞ্চল দেখানো হবে না। ওয়েবভিউ হ'ল আরও ভাল ইমেজভিউ;)


5
আমি একই পদ্ধতি ব্যবহার করছি। আমার কাছে একটি বৃহত্তর পাতাল রেল মানচিত্র রয়েছে যা আমি চাই যে ব্যবহারকারী জুম করতে এবং চারপাশে স্ক্রোল করতে সক্ষম হবে। আমি লক্ষ্য করেছি যে আপনার যদি বেশ বড় আকারের চিত্র থাকে (যেমন 1000 বা 3000 পিক্সেল প্রশস্ত), আপনি একবার জুম ইন করলে ছবিটি ঝাপসা হয়ে যায় It মনে হয় কলিরিস খুব জোরযুক্ত চিত্রটি খুব তীক্ষ্ণ প্রদর্শন করতে পারে না। যদিও মূল চিত্রটি সঙ্কুচিত এবং খুব তীক্ষ্ণ। অতএব আমি একটি বড় চিত্রকে ছোট ছোট টুকরো টুকরো করে কাটা এবং এইচটিএমএল এর মাধ্যমে আবার একত্রিত করেছি। এইভাবে জুম ইন করার সময় চিত্রটি তীক্ষ্ণ থাকে ((আমি নেক্সাস ওনে আছি, ২.১ আপ আগে এবং এখন ২.২ এ)
ম্যাথিয়াস কনরাডেট

@ ম্যাথিয়াস লিন: যদি একটি বড় চিত্র তারের উপরে প্রেরণ করা হয় তবে আমি শুনেছি ক্যারিয়াররা বড় চিত্রগুলি সংকোচিত করে। এই ব্যবহার-কেস আপনার জন্য উপযুক্ত হবে বা আপনি স্থানীয়ভাবে চিত্রটি লোড করেছেন?
স্যামুয়েল

@ সাম কোয়েস্ট: এটি স্থানীয়ভাবে লোড হচ্ছে
ম্যাথিয়াস কনরাডেট

4
জুম বোতামে নির্মিত ওয়েবভিউর ব্যবহার এবং চিম্পের জন্য জুম বাড়ানোর / আউট করার পক্ষে সমর্থন করা সম্পূর্ণ নতুন অ্যালগো যা বিভিন্ন ফোন এবং ভবিষ্যতের অ্যান্ড্রয়েড প্ল্যাটফর্ম রিলিজ জুড়ে কাজ করতে পারে না তার চেয়ে বেশি লেখার পক্ষে
সামি

2
এই সমাধানটি কেবল তখনই প্রয়োগ করা যেতে পারে যখন আপনি ডিস্কে ইমেজটি প্রায় বসে আছেন বা চিত্রটি যথেষ্ট ছোট যেমন আপনি 64 এনকোডের ভিত্তি করতে পারেন এবং স্ট্রিংয়ের মানটি লোডরউইলডথ ডেটা () এ পাস করতে পারেন।
জেফ্রি ব্লাটম্যান

7

জানুস্জ মূল প্রশ্নের জবাবে, এগুলি অর্জনের বিভিন্ন উপায় রয়েছে যার সবগুলিই তাদের সমস্যার স্তরে পরিবর্তিত হয় এবং নীচে বর্ণিত হয়েছে। ওয়েব ভিউ ব্যবহার করা ভাল, তবে এটি চেহারা এবং অনুভূতি এবং নিয়ন্ত্রণযোগ্যতার ক্ষেত্রে খুব সীমাবদ্ধ। যদি আপনি কোনও ক্যানভাস থেকে বিটম্যাপ আঁকেন, তবে সর্বাধিক বহুমুখী সমাধানগুলি প্রস্তাব করা হয়েছে বলে মনে হচ্ছে মাইকঅর্টিজ, রবার্ট ফস এবং / অথবা জ্যাকব নর্ডফালকের পরামর্শ অনুসারে। পলবোরকে অ্যান্ড্রয়েড- মাল্টিটচ -কন্ট্রোলার অন্তর্ভুক্ত করার জন্য একটি দুর্দান্ত উদাহরণ রয়েছে এবং মাল্টি-টাচ সমর্থন এবং কাস্টম ভিউগুলির সমস্ত প্রকারের জন্য দুর্দান্ত।

ব্যক্তিগতভাবে, আপনি যদি কোনও বিটম্যাপে কেবল একটি ক্যানভাস আঁকেন এবং তারপরে এটি ভিতরে এবং ইমেজভিউতে প্রদর্শিত হয় এবং একচেটিয়াভাবে মাল্টি টাচ ব্যবহার করে জুম করতে এবং ঘোরাতে সক্ষম হতে চান তবে আমি মাইকঅর্টিজের সমাধানটিকে সবচেয়ে সহজ হিসাবে খুঁজে পাই। তবে, আমার উদ্দেশ্যে গিটের যে কোডটি তিনি সরবরাহ করেছেন তা কেবল তখনই কাজ করবে যখন তার টাচ-ইমেজভিউ কাস্টম চিত্র ভিউ ক্লাসটি একমাত্র শিশু বা লেআউট প্যারাম সরবরাহ করবে:

android:layout_height="match_parent"
android:layout_height="match_parent"

দুর্ভাগ্যক্রমে আমার লেআউট ডিজাইনের কারণে, আমার "লেআউট_উইট" এর জন্য "মোড়ানো_কন্টেন্ট" প্রয়োজন। আমি যখন এটিকে পরিবর্তন করেছি তখন চিত্রটি নীচে কাটা হয়েছিল এবং আমি ক্রপ করা অঞ্চলটিতে স্ক্রোল বা জুম করতে পারি না। তাই আমি নিয়ে গবেষণা শুরু করেন উত্স ImageView মাত্র দেখতে কিভাবে Android এ "onMeasure" বাস্তবায়িত মামলা করার MikeOrtiz এর পরিবর্তন করেছেন।

   @Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

  //**** ADDED THIS ********/////
      int  w = (int) bmWidth;
      int  h = (int) bmHeight;
     width = resolveSize(w, widthMeasureSpec);  
     height = resolveSize(h, heightMeasureSpec);
  //**** END ********///   

   // width = MeasureSpec.getSize(widthMeasureSpec);   // REMOVED
   // height = MeasureSpec.getSize(heightMeasureSpec); // REMOVED

    //Fit to screen.
    float scale;
    float scaleX =  (float)width / (float)bmWidth;
    float scaleY = (float)height / (float)bmHeight;

    scale = Math.min(scaleX, scaleY);
    matrix.setScale(scale, scale);
    setImageMatrix(matrix);
    saveScale = 1f;

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

    matrix.postTranslate(redundantXSpace, redundantYSpace);

    origWidth = width - 2 * redundantXSpace;
    origHeight = height - 2 * redundantYSpace;
   // origHeight = bmHeight;
    right = width * saveScale - width - (2 * redundantXSpace * saveScale);
    bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);

    setImageMatrix(matrix);
}

এখানে রেজালাইজ সাইজ (ইনট, ইনট) হ'ল একটি "মেজারস্পেক দ্বারা আরোপিত প্রতিবন্ধকতাগুলির সাথে একটি পছন্দসই আকারের পুনর্মিলন করার ইউটিলিটি, যেখানে:

পরামিতি:

 - size How big the view wants to be
 - MeasureSpec Constraints imposed by the parent

রিটার্নস:

 - The size this view should be."

সুতরাং চিত্রটি লোড হয়ে যাওয়ার পরে মূল চিত্রটি মূল চিত্রের শ্রেণীর সাথে কিছুটা অনুরূপ আচরণ সরবরাহ করা হয়। বৃহত্তর বিভিন্ন স্ক্রিনকে সমর্থন করার জন্য আরও কিছু পরিবর্তন করা যেতে পারে যা অনুপাতের অনুপাতটিকে পরিবর্তন করে। তবে আপাতত আমি আশা করি এটি সাহায্য করবে। মাইকেআরটিজকে তার মূল কোড, দুর্দান্ত কাজের জন্য ধন্যবাদ।


এই ফিক্সটি মাইকের গিথুব রেপোতে অন্তর্ভুক্ত করা হয়েছে?
লার্শ


6

আমি কেবল রবার্ট ফসের টাচআইমেজভিউকে সংহত করেছি: এটি বাক্সের বাইরে পুরোপুরি কাজ করেছে! ধন্যবাদ!

আমি মাত্র কিছুটা কোড পরিবর্তন করেছি যাতে আমি এটি আমার লেআউট.এক্সএমএল থেকে ইনস্ট্যান্ট করতে সক্ষম হতে পারি could

মাত্র দুটি কনস্ট্রাক্টর যুক্ত করুন

public TouchImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

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

এবং পুরানো নির্মাণকারীকে একটি ডিআইডি পদ্ধতিতে রূপান্তর করুন:

private void init(Context context){
    //...old code ofconstructor of Robert Moss's code
}

3

@ রবার্ট ফস, @ মাইক অর্টিজ, আপনার কাজের জন্য আপনাকে অনেক ধন্যবাদ আমি আপনার কাজটি একীভূত করেছি এবং মাইকের অতিরিক্ত কাজের সাথে অ্যান্ড্রয়েড> 2.0 এর রবার্ট ক্লাস সম্পূর্ণ করেছি completed

আমার কাজের ফলস্বরূপ আমি ভিউপ্যাজারের ভিত্তিতে অ্যান্ড্রয়েড টাচ গ্যালারী উপস্থাপন করি এবং পরিবর্তিত টাচআইমেজভিউ ব্যবহার করি। চিত্রগুলি ইউআরএল দ্বারা লোড হচ্ছে এবং আপনি সেগুলি জুম করে টেনে আনতে পারেন। আপনি এখানে পেতে পারেন https://github.com/Dreddik/AndroidTouchGallery



2

@ মাইকের উত্তরে যুক্ত করা হচ্ছে। আমার প্রথমবার যখন চিত্রটি আসল আকারে পুনরুদ্ধার করতে ডাবল ট্যাপের প্রয়োজনও ছিল। সুতরাং আমি "অরিজ ..." ইনস্ট্যান্স ভেরিয়েবলগুলির পুরো গাদা যুক্ত করেছি এবং সিম্পলঅনজেস্টচারলিস্টনার যুক্ত করেছি যা কৌশলটি করেছে।

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ImageView;

public class TouchImageView extends ImageView {

    Matrix matrix = new 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;

    float redundantXSpace, redundantYSpace, origRedundantXSpace, origRedundantYSpace;;

    float width, height;
    static final int CLICK = 3;
    static final float SAVE_SCALE = 1f;
    float saveScale = SAVE_SCALE;

    float right, bottom, origWidth, origHeight, bmWidth, bmHeight, origScale, origBottom,origRight;

    ScaleGestureDetector mScaleDetector;
    GestureDetector mGestureDetector;

    Context context;

    public TouchImageView(Context context) {
        super(context);
        super.setClickable(true);
        this.context = context;
        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());

        matrix.setTranslate(1f, 1f);
        m = new float[9];
        setImageMatrix(matrix);
        setScaleType(ScaleType.MATRIX);

        setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {

                boolean onDoubleTapEvent = mGestureDetector.onTouchEvent(event);
                if (onDoubleTapEvent) {
                    // Reset Image to original scale values
                    mode = NONE;
                    bottom = origBottom;
                    right = origRight;
                    last = new PointF();
                    start = new PointF();
                    m = new float[9];
                    saveScale = SAVE_SCALE;
                    matrix = new Matrix();
                    matrix.setScale(origScale, origScale);
                    matrix.postTranslate(origRedundantXSpace, origRedundantYSpace);
                    setImageMatrix(matrix);
                    invalidate();
                    return true;
                } 


                mScaleDetector.onTouchEvent(event);

                matrix.getValues(m);
                float x = m[Matrix.MTRANS_X];
                float y = m[Matrix.MTRANS_Y];
                PointF curr = new PointF(event.getX(), event.getY());

                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    last.set(event.getX(), event.getY());
                    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 scaleWidth = Math.round(origWidth * saveScale);
                        float scaleHeight = Math.round(origHeight * saveScale);
                        if (scaleWidth < width) {
                            deltaX = 0;
                            if (y + deltaY > 0)
                                deltaY = -y;
                            else if (y + deltaY < -bottom)
                                deltaY = -(y + bottom);
                        } else if (scaleHeight < height) {
                            deltaY = 0;
                            if (x + deltaX > 0)
                                deltaX = -x;
                            else if (x + deltaX < -right)
                                deltaX = -(x + right);
                        } else {
                            if (x + deltaX > 0)
                                deltaX = -x;
                            else if (x + deltaX < -right)
                                deltaX = -(x + right);

                            if (y + deltaY > 0)
                                deltaY = -y;
                            else if (y + deltaY < -bottom)
                                deltaY = -(y + bottom);
                        }
                        matrix.postTranslate(deltaX, deltaY);
                        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
            }

        });

        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onDoubleTapEvent(MotionEvent e) {
                return true;
            }
        });
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        super.setImageBitmap(bm);
        bmWidth = bm.getWidth();
        bmHeight = bm.getHeight();
    }

    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 = (float) Math.min(
                    Math.max(.95f, detector.getScaleFactor()), 1.05);
            float origScale = saveScale;
            saveScale *= mScaleFactor;
            if (saveScale > maxScale) {
                saveScale = maxScale;
                mScaleFactor = maxScale / origScale;
            } else if (saveScale < minScale) {
                saveScale = minScale;
                mScaleFactor = minScale / origScale;
            }
            right = width * saveScale - width
                    - (2 * redundantXSpace * saveScale);
            bottom = height * saveScale - height
                    - (2 * redundantYSpace * saveScale);
            if (origWidth * saveScale <= width
                    || origHeight * saveScale <= height) {
                matrix.postScale(mScaleFactor, mScaleFactor, width / 2,
                        height / 2);
                if (mScaleFactor < 1) {
                    matrix.getValues(m);
                    float x = m[Matrix.MTRANS_X];
                    float y = m[Matrix.MTRANS_Y];
                    if (mScaleFactor < 1) {
                        if (Math.round(origWidth * saveScale) < width) {
                            if (y < -bottom)
                                matrix.postTranslate(0, -(y + bottom));
                            else if (y > 0)
                                matrix.postTranslate(0, -y);
                        } else {
                            if (x < -right)
                                matrix.postTranslate(-(x + right), 0);
                            else if (x > 0)
                                matrix.postTranslate(-x, 0);
                        }
                    }
                }
            } else {
                matrix.postScale(mScaleFactor, mScaleFactor,
                        detector.getFocusX(), detector.getFocusY());
                matrix.getValues(m);
                float x = m[Matrix.MTRANS_X];
                float y = m[Matrix.MTRANS_Y];
                if (mScaleFactor < 1) {
                    if (x < -right)
                        matrix.postTranslate(-(x + right), 0);
                    else if (x > 0)
                        matrix.postTranslate(-x, 0);
                    if (y < -bottom)
                        matrix.postTranslate(0, -(y + bottom));
                    else if (y > 0)
                        matrix.postTranslate(0, -y);
                }
            }
            return true;

        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = MeasureSpec.getSize(widthMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
        // Fit to screen.
        float scale;
        float scaleX = (float) width / (float) bmWidth;
        float scaleY = (float) height / (float) bmHeight;
        scale = Math.min(scaleX, scaleY);
        matrix.setScale(scale, scale);
        setImageMatrix(matrix);
        saveScale = SAVE_SCALE;
        origScale = scale;

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

        origRedundantXSpace = redundantXSpace;
        origRedundantYSpace = redundantYSpace;

        matrix.postTranslate(redundantXSpace, redundantYSpace);

        origWidth = width - 2 * redundantXSpace;
        origHeight = height - 2 * redundantYSpace;
        right = width * saveScale - width - (2 * redundantXSpace * saveScale);
        bottom = height * saveScale - height
                - (2 * redundantYSpace * saveScale);
        origRight = right;
        origBottom = bottom;
        setImageMatrix(matrix);
    }

}

2

এটি এই থ্রেডটিতে খুব দেরী সংযোজন, তবে আমি একটি চিত্রের দৃশ্যে কাজ করছি যা জুম এবং প্যানকে সমর্থন করে এবং বেশ কয়েকটি বৈশিষ্ট্য আমি অন্য কোথাও খুঁজে পাইনি। এটি OutOfMemoryErrorজুম বাড়ানোর সময় চিত্রটি সাব্পল করে এবং জুম বাড়ানোর সময় উচ্চতর রেজোলিউশন টাইলগুলি লোড করে খুব বড় চিত্র প্রদর্শন করার উপায় হিসাবে এটি শুরু হয়েছিল It এটি এখন একটি ViewPager, রোটোলে ম্যানুয়ালি বা এক্সআইএফ তথ্য (90 ° স্টপস) ব্যবহার করে সমর্থন করে, নির্বাচিত স্পর্শ ইভেন্টগুলি ব্যবহার করে OnClickListenerবা আপনার নিজস্ব GestureDetectorবা এর ওভাররাইডOnTouchListener , ওভারলেগুলি জুড়তে সাবক্লাসিং, জুম করার সময় প্যান করা এবং গতিবেগকে করুন।

এটি সাধারণ ব্যবহার প্রতিস্থাপন হিসাবে নয় ImageView তাই এটি প্রসারিত হয় না এবং সংস্থানগুলি, কেবল সম্পদ এবং বাহ্যিক ফাইলগুলি থেকে চিত্র প্রদর্শনের পক্ষে সমর্থন করে না। এর জন্য এসডিকে 10 দরকার।

উত্সটি গিটহাবে রয়েছে এবং একটি নমুনা রয়েছে যা এ-এর ব্যবহারের চিত্রিত করে ViewPager

https://github.com/davemorrissey/subsampling-scale-image-view


1

আপনি এর জন্য লেআউটপ্যারামগুলি ব্যবহার করে দেখতে পারেন

public void zoom(boolean flag){
    if(flag){
        int width=40;
        int height=40;
    }
    else{
        int width=20;
        int height=20;
    }
    RelativeLayout.LayoutParams param=new RelativeLayout.LayoutParams(width,height); //use the parent layout of the ImageView;
    imageView.setLayoutParams(param); //imageView is the view which needs zooming.
}

জুমআইন = জুম (সত্য); জুমআউট = জুম (মিথ্যা);


0
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    imageDetail = (ImageView) findViewById(R.id.imageView1);
    imageDetail.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            ImageView view = (ImageView) v;
            System.out.println("matrix=" + savedMatrix.toString());
            switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    savedMatrix.set(matrix);
                    startPoint.set(event.getX(), event.getY());
                    mode = DRAG;
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    oldDist = spacing(event);
                    if (oldDist > 10f) {
                        savedMatrix.set(matrix);
                        midPoint(midPoint, event);
                        mode = ZOOM;
                    }
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_POINTER_UP:
                    mode = NONE;
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mode == DRAG) {
                        matrix.set(savedMatrix);
                        matrix.postTranslate(event.getX() - startPoint.x, event.getY() - startPoint.y);
                    } else if (mode == ZOOM) {
                        float newDist = spacing(event);
                        if (newDist > 10f) {
                            matrix.set(savedMatrix);
                            float scale = newDist / oldDist;
                            matrix.postScale(scale, scale, midPoint.x, midPoint.y);
                        }
                    }
                    break;
            }
            view.setImageMatrix(matrix);
            return true;

        }

        @SuppressLint("FloatMath")
        private float spacing(MotionEvent event) {
            float x = event.getX(0) - event.getX(1);
            float y = event.getY(0) - event.getY(1);
            return FloatMath.sqrt(x * x + y * y);
        }

        private void midPoint(PointF point, MotionEvent event) {
            float x = event.getX(0) + event.getX(1);
            float y = event.getY(0) + event.getY(1);
            point.set(x / 2, y / 2);
        }
    });
}

এবং অঙ্কনযোগ্য ফোল্ডারে বিটিকান চিত্র ফাইল থাকা উচিত। পুরোপুরি কাজ করে :)


0

নীচের মতো কিছু এটি করবে।

@Override public boolean onTouch(View v,MotionEvent e)
{

    tap=tap2=drag=pinch=none;
    int mask=e.getActionMasked();
    posx=e.getX();posy=e.getY();

    float midx= img.getWidth()/2f;
    float midy=img.getHeight()/2f;
    int fingers=e.getPointerCount();

    switch(mask)
    {
        case MotionEvent.ACTION_POINTER_UP:
            tap2=1;break;

        case MotionEvent.ACTION_UP:
            tap=1;break;

        case MotionEvent.ACTION_MOVE:
            drag=1;
    }
    if(fingers==2){nowsp=Math.abs(e.getX(0)-e.getX(1));}
    if((fingers==2)&&(drag==0)){ tap2=1;tap=0;drag=0;}
    if((fingers==2)&&(drag==1)){ tap2=0;tap=0;drag=0;pinch=1;}

    if(pinch==1)

    {
        if(nowsp>oldsp)scale+=0.1;
        if(nowsp<oldsp)scale-=0.1;
        tap2=tap=drag=0;    
    }
    if(tap2==1)
        {
            scale-=0.1;
            tap=0;drag=0;
        }
    if(tap==1)
        {
            tap2=0;drag=0;
            scale+=0.1;
        }
    if(drag==1)
        {
            movx=posx-oldx;
            movy=posy-oldy;
            x+=movx;
            y+=movy;
            tap=0;tap2=0;
        }
    m.setTranslate(x,y);
    m.postScale(scale,scale,midx,midy);
    img.setImageMatrix(m);img.invalidate();
    tap=tap2=drag=none;
    oldx=posx;oldy=posy;
    oldsp=nowsp;
    return true;
}


public void onCreate(Bundle b)
{
        super.onCreate(b);

    img=new ImageView(this);
    img.setScaleType(ImageView.ScaleType.MATRIX);
    img.setOnTouchListener(this);

    path=Environment.getExternalStorageDirectory().getPath();   
    path=path+"/DCIM"+"/behala.jpg";
    byte[] bytes;
    bytes=null;
    try{
        FileInputStream fis;
        fis=new FileInputStream(path);
        BufferedInputStream bis;
        bis=new BufferedInputStream(fis);
        bytes=new byte[bis.available()];
        bis.read(bytes);
        if(bis!=null)bis.close();
        if(fis!=null)fis.close();

     }
    catch(Exception e)
        {
        ret="Nothing";
        }
    Bitmap bmp=BitmapFactory.decodeByteArray(bytes,0,bytes.length);

    img.setImageBitmap(bmp);

    setContentView(img);
}

সম্পূর্ণ প্রোগ্রাম দেখার জন্য এখানে দেখুন: অ্যান্ড্রয়েডে চিত্র জুম করার প্রোগ্রাম

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.