কীভাবে কোনও দৃশ্যের পরম স্থানাঙ্ক পাবেন


390

আমি দর্শনের উপরের বাম কোণে পরম স্ক্রিন পিক্সেল স্থানাঙ্কগুলি পাওয়ার চেষ্টা করছি। যাইহোক, সমস্ত পদ্ধতি যেমন আমি খুঁজে পেতে পারি getLeft()এবং getRight()সেগুলি কাজ করে না কারণ সেগুলি সমস্ত মতামতের পিতামাতার সাথে সম্পর্কিত বলে মনে হয়, এইভাবে আমাকে দেয় 0। এটি করার উপযুক্ত উপায় কী?

যদি এটি সহায়তা করে তবে এটি গেমটির জন্য 'চিত্রটিকে পিছনে রাখুন'। আমি চাই যে ব্যবহারকারী একাধিক টুকরা নির্বাচন করতে একটি বাক্স আঁকতে সক্ষম হবে। আমার ধারণাটি হ'ল এটি করার সবচেয়ে সহজ উপায় হ'ল getRawX()এবং এর getRawY()থেকে MotionEventএবং তারপরে সেই মানগুলি টুকরা ধারণ করে উপরের বাম কোণার সাথে তুলনা করুন। টুকরাগুলির আকার জেনে আমি কতগুলি টুকরো নির্বাচন করা হয়েছে তা নির্ধারণ করতে পারি। আমি বুঝতে পারছি আমি ব্যবহার করতে পারেন getX()এবং getY()উপর MotionEvent, কিন্তু যে আয় একটি আপেক্ষিক অবস্থান নির্ণয় করা হয় যা টুকরা আরো কঠিন নির্বাচিত হয় যে হিসাবে। (অসম্ভব নয়, আমি জানি, তবে এটি অযথা জটিল বলে মনে হচ্ছে)।

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

TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
Log.d(LOG_TAG, "Values " + tableLayout.getTop() + tableLayout.getLeft());

সম্পাদনা 2: প্রস্তাবিত উত্তরগুলির আরও অনুসরণ করে এখানে আমি চেষ্টা করেছি কোড code

public int[] tableLayoutCorners = new int[2];
(...)

TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
tableLayout.requestLayout();
Rect corners = new Rect();
tableLayout.getLocalVisibleRect(corners);
Log.d(LOG_TAG, "Top left " + corners.top + ", " + corners.left + ", " + corners.right
            + ", " + corners.bottom);

cells[4].getLocationOnScreen(tableLayoutCorners);
Log.d(LOG_TAG, "Values " + tableLayoutCorners[0] + ", " + tableLayoutCorners[1]);

সমস্ত সূচনা সম্পন্ন হওয়ার পরে এই কোডটি যুক্ত করা হয়েছিল। চিত্রটি ক এর মধ্যে থাকা ইমেজভিউজের একটি কক্ষে (ঘর [] অ্যারে) বিভক্ত হয়েছে TableLayout। সেলগুলি [0] শীর্ষে বাম ImageView, এবং আমি কোষগুলি বেছে নিয়েছি [4] কারণ এটি মাঝখানে কোথাও রয়েছে এবং খুব অবশ্যই (0,0) এর স্থানাঙ্ক থাকা উচিত নয়।

উপরে প্রদর্শিত কোডটি এখনও আমাকে লগগুলিতে সমস্ত 0s দেয় যা আমি সত্যিই বুঝতে পারি না কারণ বিভিন্ন ধাঁধার টুকরা সঠিকভাবে প্রদর্শিত হয়েছে। (আমি টেবিল লেআউটকর্ণার্স এবং ডিফল্ট দৃশ্যমানতার জন্য সর্বজনীন চেষ্টা করেছি, উভয়ই একই ফল দিচ্ছি))

আমি জানি না এটি তাত্পর্যপূর্ণ কিনা, তবে ImageViewগুলি মূলত একটি আকার দেওয়া হয় না। এর আকার আকার ImageViewনির্ধারণ করা হয় স্বয়ংক্রিয়ভাবে প্রদর্শনের মাধ্যমে যখন আমি এটিকে প্রদর্শন করার জন্য একটি চিত্র দেই। লগিং কোডটি তাদের একটি চিত্র দেওয়ার পরে এবং স্বয়ংক্রিয়ভাবে নিজেকে পুনরায় আকার দেওয়ার পরেও এটি কি তাদের মান 0 হওয়ার ক্ষেত্রে অবদান রাখতে পারে? সম্ভাব্যরূপে এর মোকাবিলা করতে, আমি tableLayout.requestLayout()উপরে বর্ণিত কোডটি যুক্ত করেছি , তবে তাতে কোনও লাভ হয়নি।

উত্তর:


632

ব্যবহার করুন View.getLocationOnScreen()এবং / অথবা getLocationInWindow()


3
এখন এটিই আমি খুঁজে পাওয়ার প্রত্যাশা করছিলাম function দুর্ভাগ্যক্রমে, আমি অবশ্যই এটি সঠিকভাবে ব্যবহার করব না। আমি বুঝতে পেরেছিলাম যে এটি একটি পরিচিত বাগ ছিল যা getLocationOnScreen অ্যানড্রয়েড v1.5 (যে প্ল্যাটফর্মটির জন্য আমি কোড করছি) একটি নাল পয়েন্টার ব্যতিক্রম দেয়, তবে ভি 2.1-এ পরীক্ষা করা এর চেয়ে ভাল কাজ করে না। উভয় পদ্ধতিই আমাকে সমস্ত কিছুর জন্য 0s দিয়েছে। আমি উপরে একটি কোড স্নিপেট অন্তর্ভুক্ত।
স্টিভ হ্যালি

76
লেআউটটি হওয়ার পরে আপনি কেবল এটির আবেদন করতে পারবেন । মতামতগুলি স্ক্রিনে অবস্থানের আগে আপনি পদ্ধতিটি কল করছেন।
রোমেন গাই

5
আহা, আপনি ঠিক বলেছেন যদিও আমি এটি করছি তা স্পষ্ট ছিল না। ধন্যবাদ! আরও তথ্যের জন্য কৌতূহলী কারও জন্য, আমি একটি উত্তর যুক্ত করেছি যা আমার অর্থটি বোঝায়।
স্টিভ হ্যালি

9
আপনি ভিউটি ট্রিউবার্সার এবং এর অনব্লোবললয়আউটলিস্টারের মতো? শুরু করতে View.getViewTreeObserver () দেখুন।
রোমেন গাই

8
@ রোমেনগুই হ্যাঁ, এ জাতীয় ধরণের, তবে নিবন্ধন করার চেয়ে কম বিভ্রান্তি (এবং তারপরে নিবন্ধন করুন ...)। এটি এমন একটি অঞ্চল যেখানে আইওডিস এটি এসডির ক্ষেত্রে অ্যান্ড্রয়েডের চেয়ে ভাল করে। উভয়ই দৈনিক ভিত্তিতে ব্যবহার করে আমি বলতে পারি আইওএসে প্রচুর বিরক্তিকর জিনিস রয়েছে তবে ইউআইভিউ হ্যান্ডলিং এর মধ্যে একটি নয়। :)
মার্টিন মার্কনকিনি

127

গৃহীত উত্তরটি আসলে কীভাবে অবস্থান পাবেন তা জানায়নি, সুতরাং এখানে আরও কিছু বিশদ দেওয়া হল। আপনি intদৈর্ঘ্যের 2 টি অ্যারে পেরিয়ে যান এবং মানগুলি (x, y) স্থানাঙ্ক (উপরে, বাম কোণে) দিয়ে প্রতিস্থাপন করা হয়।

int[] location = new int[2];
myView.getLocationOnScreen(location);
int x = location[0];
int y = location[1];

মন্তব্য

  • getLocationOnScreenসঙ্গে প্রতিস্থাপনgetLocationInWindow অধিকাংশ ক্ষেত্রে একই ফলাফল দিতে হবে (দেখুন এই উত্তর )। তবে, আপনি যদি কোনও ডায়ালগ বা কাস্টম কীবোর্ডের মতো একটি ছোট উইন্ডোতে থাকেন তবে আপনার ব্যবহারের জন্য কোনটি আপনার প্রয়োজন অনুসারে ভাল তা বেছে নিতে হবে।
  • আপনি (0,0)যদি এই পদ্ধতিটি কল করেন তবে আপনি পাবেন onCreateকারণ দৃশ্যটি এখনও নির্ধারণ করা হয়নি। ViewTreeObserverলেআউটটি হয়ে গেলে আপনি শোনার জন্য একটি ব্যবহার করতে পারেন এবং পরিমাপ করা স্থানাঙ্কগুলি পেতে পারেন। ( এই উত্তর দেখুন ।)

85

প্রথমে আপনাকে ভিউটির স্থানীয় দৃশ্যমান আয়তক্ষেত্রটি পেতে হবে

যেমন:

Rect rectf = new Rect();

//For coordinates location relative to the parent
anyView.getLocalVisibleRect(rectf);

//For coordinates location relative to the screen/display
anyView.getGlobalVisibleRect(rectf);

Log.d("WIDTH        :", String.valueOf(rectf.width()));
Log.d("HEIGHT       :", String.valueOf(rectf.height()));
Log.d("left         :", String.valueOf(rectf.left));
Log.d("right        :", String.valueOf(rectf.right));
Log.d("top          :", String.valueOf(rectf.top));
Log.d("bottom       :", String.valueOf(rectf.bottom));

আশা করি এটি সাহায্য করবে


3
এটিও কাজ করা উচিত ছিল ... তবে এটি আমাকে 0 এর মানও দিচ্ছে। আমি উপরে একটি কোড স্নিপেট অন্তর্ভুক্ত করেছি যদি এটি আপনাকে কী ভুল করেছে তা নির্ধারণ করতে সহায়তা করে। আবার ধন্যবাদ.
স্টিভ হ্যালি

1
আমার অন্যান্য মন্তব্য দেখুন; দৃশ্যগুলি নিজেরাই প্রকাশ করা শেষ হওয়ার আগেই আমি দুর্ঘটনাক্রমে এটিকে ডাকছিলাম। ধন্যবাদ এখন ধন্যবাদ।
স্টিভ হ্যালি

@ নবীনমূর্তি এটি নির্দিষ্ট দৃশ্যের স্থানাঙ্ক দেয়, আমার মূল বিন্যাসে ক্লিক করা দৃশ্যের স্থানাঙ্ক প্রয়োজন ..
অনিকেত

19
এটি পিতামাতার সাথে সম্পর্কিত অবস্থানটি প্রদান করে। getGlobalVisibleRect()পরম কর্ড জন্য ব্যবহার ।
জেফ্রি ব্লাটম্যান

3
@ স্টিভ হ্যালি, আপনার মত আমিও একই সমস্যার মুখোমুখি হয়েছি, কিছু কারণে এটি আমার চেষ্টা করা প্রতিটি পদ্ধতিতে আমাকে 0 দেয়। দেখে মনে হচ্ছে এটি শূন্য কেন দিচ্ছে তা আপনি নির্ধারণ করেছেন। লেআউটটি লোড হওয়ার পরেও আমি দর্শন স্থানাঙ্কগুলি পাওয়ার চেষ্টা করছি তবে আমি শূন্য কেন এটি কেন? আপনার সহায়তার জন্য ধন্যবাদ
পঙ্কজ নিমগাদে 20'15

46

একটি বিশ্বব্যাপী বিন্যাস শ্রোতা ব্যবহার সর্বদা আমার জন্য ভাল কাজ করেছে। লেআউট পরিবর্তন করা থাকলে জিনিসগুলি স্মরণে রাখতে সক্ষম হওয়ার সুবিধা রয়েছে, উদাহরণস্বরূপ যদি কিছুতে সেট করে সেট করা থাকে G GONE বা শিশু দর্শন যোগ করা / সরানো হয়।

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

     // inflate your main layout here (use RelativeLayout or whatever your root ViewGroup type is
     LinearLayout mainLayout = (LinearLayout ) this.getLayoutInflater().inflate(R.layout.main, null); 

     // set a global layout listener which will be called when the layout pass is completed and the view is drawn
     mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(
       new ViewTreeObserver.OnGlobalLayoutListener() {
          public void onGlobalLayout() {
               //Remove the listener before proceeding
               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    mainLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
               } else {
                    mainLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
               }

               // measure your views here
          }
       }
     );

     setContentView(mainLayout);
 }

OnGlobalLayoutListener (এর শেষে) onGlobalLayout () {...} এর ভিতরে সরাতে ভুলবেন না} এছাড়াও, কেবল নিশ্চিত হওয়ার জন্য, কি হয়েছে তা পরীক্ষা করুন! = 0; শ্রোতাকে দুবার ডাকা যেতে পারে, একবার ডাব্লু = 0 / এইচ = 0 এর মান দিয়ে, দ্বিতীয়বার আসল, সঠিক, মান সহ।
ম্যাকডি

মূল লেআউটটি স্ফীত করার উপায় এবং তারপরে আমার অ্যাপ্লিকেশনে বিশেষে setContentView()কোনও সমস্যা তৈরি করেছে Activity! এটি একটি সংলাপের ক্রিয়াকলাপ ছিল ( windowFrame:@null, windowActionBar:false, windowIsFloating:true, windowNoTitle:true)। এর প্রধান বিন্যাস (ক LinearLayout) নির্ধারিত কোনও প্রত্যক্ষ বাচ্চা নেই layout_width(এঁরা সকলেই ছিলেন match_parentবা ছিলেন wrap_content)।
মীর-ইসমাইলি

17

রোমেন গায়ের মন্তব্য অনুসরণ করে, আমি এটি কীভাবে ঠিক করেছি তা এখানে। আশা করি এটি অন্য যে কারও কাছে এই সমস্যাটি ছিল তাকে সহায়তা করবে।

আমি পর্দায় প্রদর্শিত হওয়ার আগে সত্যই পজিশনের অবস্থানগুলি পাওয়ার চেষ্টা করছিলাম কিন্তু এটি ঘটছিল তা মোটেই পরিষ্কার ছিল না। এই লাইনগুলি সূচনা কোডটি চলার পরে স্থাপন করা হয়েছিল, তাই আমি ধরেছিলাম যে সবকিছু প্রস্তুত আছে। তবে এই কোডটি এখনও অনক্রিট () এ ছিল; থ্রেড.স্লিপ () এর সাথে পরীক্ষার মাধ্যমে আমি আবিষ্কার করেছি যে অনকারিউট () অনারেসিউমের সমস্ত উপায় () সম্পাদন শেষ না হওয়া পর্যন্ত লেআউটটি আসলে চূড়ান্ত হয় না। সুতরাং প্রকৃতপক্ষে, কোডটি স্ক্রিনে বিন্যাসটি স্থির হওয়া শেষ হওয়ার আগে চালানোর চেষ্টা করা হয়েছিল। একটি অনক্লিকলিস্টনার (বা অন্য কোনও শ্রোতা) -তে কোড যুক্ত করে সঠিক মানগুলি প্রাপ্ত করা হয়েছিল কারণ লেআউটটি শেষ হওয়ার পরে এটি কেবল বরখাস্ত করা যেতে পারে।


নীচের লাইনটি সম্প্রদায়ের সম্পাদনা হিসাবে প্রস্তাব করা হয়েছিল:

ব্যবহার করুন onWindowfocuschanged(boolean hasFocus)


সুতরাং আপনি সেট কন্টেন্টভিউ (my_layout) বলতে চাইছেন; সমস্ত মতামত স্থাপন করবে না। সমস্ত দর্শনগুলি অনক্রিট () সমাপ্ত হওয়ার পরেই স্থাপন করা হবে?
আশ্বিন

5
বেশ না। সমস্ত দর্শন 'অস্তিত্ব' পরে রয়েছে setContentView(R.layout.something), তবে সেগুলি দৃষ্টিভત્રીভাবে লোড করা হয়নি। তাদের কোনও আকার বা অবস্থান নেই। প্রথম লেআউট পাস সমাপ্ত না হওয়া পর্যন্ত এটি ঘটে না, যা ভবিষ্যতে কোনও সময়ে ঘটে (সাধারণত অনারুম () পরে)।
স্টিভ হ্যালি

14

প্রথম উপায়:

ইন Kotlin আমরা দেখার জন্য একটি সহজ এক্সটেনশনটি তৈরি করতে পারেন:

fun View.getLocationOnScreen(): Point
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return Point(location[0],location[1])
}

এবং কেবল স্থানাঙ্ক পান:

val location = yourView.getLocationOnScreen()
val absX = location.x
val absY = location.y

দ্বিতীয় উপায়:

দ্বিতীয় উপায়টি আরও সহজ:

fun View.absX(): Int
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return location[0]
}

fun View.absY(): Int
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return location[1]
}

এবং সহজেই এক্স এক্স view.absX()এবং ওয়াইয়ের মাধ্যমে পানview.absY()


6
আপনার 1 ম নমুনার জন্য একটি সংক্ষিপ্ত সংস্করণ:val location = IntArray(2).apply(::getLocationOnScreen)
টুয়ান চাউ

5

আমার ব্যবহারের অবস্থানের অবস্থানের জন্য কাজ করে, এটি এবং এর Pointসাথে একটি বস্তু ফেরত দেবেx valuey value

public static Point getLocationOnScreen(View view){
    int[] location = new int[2];
    view.getLocationOnScreen(location);
    return new Point(location[0], location[1]);
}

ব্যবহার

Point viewALocation = getLocationOnScreen(viewA);

5

আপনি getLocationOnScreen()বা ব্যবহার করে একটি ভিউ এর স্থানাঙ্ক পেতে পারেনgetLocationInWindow()

এরপরে xএবং ভিউটির yউপরের বাম কোণে হওয়া উচিত। যদি আপনার মূল বিন্যাসটি স্ক্রিনের চেয়ে ছোট হয় (যেমন কোনও ডায়ালগের মতো), ব্যবহার করেgetLocationInWindow করা তার পাত্রে নয়, পুরো স্ক্রিনের সাথে সম্পর্কিত।

জাভা সলিউশন

int[] point = new int[2];
view.getLocationOnScreen(point); // or getLocationInWindow(point)
int x = point[0];
int y = point[1];

দ্রষ্টব্য: মানটি যদি সর্বদা 0 হয় তবে আপনি সম্ভবত অবস্থানটির অনুরোধ করার আগেই দৃশ্যটি পরিবর্তন করছেন।

ভিউটি আপডেট হওয়ার সুযোগ পেয়েছে তা নিশ্চিত করতে, ভিউর নতুন লেআউটটি ব্যবহার করে গণনা করার পরে আপনার অবস্থানের অনুরোধটি চালান view.post:

view.post(() -> {
    // Values should no longer be 0
    int[] point = new int[2];
    view.getLocationOnScreen(point); // or getLocationInWindow(point)
    int x = point[0];
    int y = point[1];
});

~~

কোটলিন সলিউশন

val point = IntArray(2)
view.getLocationOnScreen(point) // or getLocationInWindow(point)
val (x, y) = point

দ্রষ্টব্য: মানটি যদি সর্বদা 0 হয় তবে আপনি সম্ভবত অবস্থানটির অনুরোধ করার আগেই দৃশ্যটি পরিবর্তন করছেন।

ভিউটি আপডেট হওয়ার সুযোগ পেয়েছে তা নিশ্চিত করতে, ভিউর নতুন লেআউটটি ব্যবহার করে গণনা করার পরে আপনার অবস্থানের অনুরোধটি চালান view.post:

view.post {
    // Values should no longer be 0
    val point = IntArray(2)
    view.getLocationOnScreen(point) // or getLocationInWindow(point)
    val (x, y) = point
}

আমি এটি পরিচালনা করার জন্য একটি এক্সটেনশন ফাংশন তৈরি করার পরামর্শ দিচ্ছি:

// To use, call:
val (x, y) = view.screenLocation

val View.screenLocation get(): IntArray {
    val point = IntArray(2)
    getLocationOnScreen(point)
    return point
}

এবং যদি আপনার নির্ভরযোগ্যতার প্রয়োজন হয় তবে এগুলিও যুক্ত করুন:

view.screenLocationSafe { x, y -> Log.d("", "Use $x and $y here") }

fun View.screenLocationSafe(callback: (Int, Int) -> Unit) {
    post {
        val (x, y) = screenLocation
        callback(x, y)
    }
}

0

সঠিক X এবং Y কর্ডিনেটগুলি সন্ধান করতে এই কোডটি ব্যবহার করুন:

int[] array = new int[2];
ViewForWhichLocationIsToBeFound.getLocationOnScreen(array);
if (AppConstants.DEBUG)
    Log.d(AppConstants.TAG, "array  X = " + array[0] + ", Y = " + array[1]);
ViewWhichToBeMovedOnFoundLocation.setTranslationX(array[0] + 21);
ViewWhichToBeMovedOnFoundLocation.setTranslationY(array[1] - 165);

আমি আমার দৃষ্টিভঙ্গি সামঞ্জস্য করতে কিছু মান যুক্ত / বিয়োগ করেছি। সম্পূর্ণ দর্শন ফুলে উঠার পরে দয়া করে এই লাইনগুলি করুন।


"আমি আমার দৃষ্টিভঙ্গি সামঞ্জস্য করতে কিছু মান যুক্ত / বিয়োগ করেছি" " কেন ??
টুলমেকারস্টেভ

আমি আমার প্রয়োজন অনুসারে বলতে চাই (দৃশ্যধারণের স্থান), আমি আমার দৃষ্টিভঙ্গিটি সামঞ্জস্য করতে মান যুক্ত করেছি এবং বিয়োগ করেছি।
তরুণ

0

পর্দায় ভিউ অবস্থান এবং মাত্রা উভয়ই পান

val viewTreeObserver: ViewTreeObserver = videoView.viewTreeObserver;

    if (viewTreeObserver.isAlive) {
        viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                //Remove Listener
                videoView.viewTreeObserver.removeOnGlobalLayoutListener(this);

                //View Dimentions
                viewWidth = videoView.width;
                viewHeight = videoView.height;

                //View Location
                val point = IntArray(2)
                videoView.post {
                    videoView.getLocationOnScreen(point) // or getLocationInWindow(point)
                    viewPositionX = point[0]
                    viewPositionY = point[1]
                }

            }
        });
    }

0

উপরোক্ত উত্তরগুলি ছাড়াও, আপনাকে কোথায় এবং কখন ফোন করা উচিত এই প্রশ্নের জন্য getLocationOnScreen ?

আপনি যে কোনও দৃশ্যের সাথে সম্পর্কিত যে কোনও তথ্যে, দৃশ্যটি স্ক্রিনে রাখার পরে তা কেবলমাত্র উপলব্ধ হবে। আপনি সহজেই আপনার কোডটি লাগিয়ে এটি করতে পারেন যা এটির ভিতরে ভিউ তৈরির উপর নির্ভরশীল (ভিউ.পোস্ট (চলমান)):

view.post(new Runnable() {
            @Override
            public void run() {

               // This code will run view created and rendered on screen

               // So as the answer to this question, you can put
               int[] location = new int[2];
               myView.getLocationOnScreen(location);
               int x = location[0];
               int y = location[1];
            }
        });  
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.