ভিউ'র গেটউইথ () এবং getHeight () 0 প্রদান করে


513

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

আমি কিছু গবেষণা করেছি এবং আমি দেখেছি এটি onCreate()পদ্ধতি ছাড়া অন্য কোথাও করা দরকার । কেউ যদি কীভাবে এটি করতে হয় তার একটি উদাহরণ দিতে পারেন, তা দুর্দান্ত।

আমার বর্তমান কোডটি এখানে:

package com.animation;

import android.app.Activity;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.Button;
import android.widget.LinearLayout;

public class AnimateScreen extends Activity {


//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    LinearLayout ll = new LinearLayout(this);

    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(30, 20, 30, 0);

    Button bt = new Button(this);
    bt.setText(String.valueOf(bt.getWidth()));

    RotateAnimation ra = new RotateAnimation(0,360,bt.getWidth() / 2,bt.getHeight() / 2);
    ra.setDuration(3000L);
    ra.setRepeatMode(Animation.RESTART);
    ra.setRepeatCount(Animation.INFINITE);
    ra.setInterpolator(new LinearInterpolator());

    bt.startAnimation(ra);

    ll.addView(bt,layoutParams);

    setContentView(ll);
}

কোন সাহায্য প্রশংসা করা হয়।

উত্তর:


197

আপনি getWidth()খুব তাড়াতাড়ি কল করছেন। ইউআই এখনও আকারের এবং পর্দায় আউট করা হয়নি।

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

বলা হচ্ছে, আপনি বোতামের আকার নির্ধারণ করতে একটি মাত্রা সংস্থান ব্যবহার করতে পারেন , তারপরে এই সমস্যাটি এড়াতে আপনার লেআউট ফাইল এবং আপনার উত্স কোড থেকে সেই মাত্রা সংস্থানটি উল্লেখ করুন।


82
এনগ্রিনউড 6, আপনার অন্যান্য সমাধান কী?
অ্যান্ড্রু

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

11
@ ওভাররাইড পাবলিক অকার্যকর অন উইন্ডো ফোকাস চ্যাঞ্জড (বুলিয়ান হ্যাশফোকাস) {// টোডো স্বয়ংক্রিয়ভাবে উত্পন্ন পদ্ধতি স্টাব সুপার.অনুইন্ডো ফোকাস চ্যাঞ্জড (হেসফোকাস); // এখানে আপনি আকার পেতে পারেন! }
সানা

5
@ এনগ্রিনউইড 6 তাহলে আপনার সমাধান কী ছিল?
নিমা ওয়াজিরি

5
আকারটি পেতে এই শ্রোতাটি ব্যবহার করুন, কখন আপনার স্ক্রিন প্রস্তুত। View.getViewTreeObserver ()। addOnGlobalLayoutListener (new ViewTreeObserver.OnGlobalLayoutListener () {}
সিনান

814

মূল সমস্যাটি হ'ল, আপনাকে প্রকৃত পরিমাপের জন্য অঙ্কন পর্বের জন্য অপেক্ষা করতে হবে (বিশেষত গতিশীল মানগুলি wrap_contentবা এর মতো match_parent), তবে সাধারণত এই পর্বটি শেষ হয় নি onResume()। সুতরাং এই পর্বের জন্য অপেক্ষা করার জন্য আপনার একদম প্রয়োজন। এর বিভিন্ন সম্ভাব্য সমাধান রয়েছে:


1. আঁকুন / লেআউট ইভেন্টগুলি শুনুন: ভিউTreeObserver

একটি ViewTreeObserver বিভিন্ন অঙ্কন ইভেন্টের জন্য বরখাস্ত হয়। সাধারণত OnGlobalLayoutListenerআপনি পরিমাপটি পাওয়ার জন্য যা চান তা তাই শ্রোতার মধ্যে কোডটি বিন্যাস পর্বের পরে কল করা হবে, সুতরাং পরিমাপগুলি প্রস্তুত:

view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                view.getHeight(); //height is ready
            }
        });

দ্রষ্টব্য: শ্রোতা তাত্ক্ষণিকভাবে সরানো হবে কারণ অন্যথায় এটি প্রতিটি লেআউট ইভেন্টে আগুন লাগবে। আপনার যদি অ্যাপ্লিকেশনগুলিকে সমর্থন করতে হয় SDK Lvl <16 শ্রোতার রেজিস্ট্রেশন করতে এটি ব্যবহার করুন:

public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)


২. লেআউট সারিতে একটি চলমানযোগ্য যুক্ত করুন: দেখুন.পোস্ট ()

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

UI ইভেন্টের সারি ক্রমযুক্ত ইভেন্টগুলি প্রক্রিয়া করবে। সেট কনটেন্টভিউ () আহ্বান করার পরে ইভেন্টের কাতারে রিলেআউট চেয়ে একটি বার্তা থাকবে, সুতরাং আপনার সারিটিতে পোস্ট করা যে কোনও কিছুই বিন্যাস পাসের পরে ঘটবে

উদাহরণ:

final View view=//smth;
...
view.post(new Runnable() {
            @Override
            public void run() {
                view.getHeight(); //height is ready
            }
        });

সুবিধা উপর ViewTreeObserver:

  • আপনার কোডটি কেবল একবার কার্যকর করা হয়েছে এবং কার্যকর করার পরে আপনাকে পর্যবেক্ষককে অক্ষম করতে হবে না যা ঝামেলা হতে পারে
  • কম ভার্বোজ সিনট্যাক্স

তথ্যসূত্র:


৩.উইউরাইট ভিউজের অন-লেআউট পদ্ধতি w

এটি কেবলমাত্র নির্দিষ্ট পরিস্থিতিতে ব্যবহারিক যখন যুক্তিটি নিজেই ভিউতে আবদ্ধ করা যায়, অন্যথায় এটি একটি সম্পূর্ণ ভার্জোজ এবং ভার্চুয়াল বাক্য গঠন।

view = new View(this) {
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        view.getHeight(); //height is ready
    }
};

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


৪. লেআউট পর্যায়ে গেছে কিনা তা পরীক্ষা করে দেখুন

ইউআই তৈরি করার সময় আপনার যদি এমন কোড রয়েছে যা একাধিকবার কার্যকর করছে আপনি নিম্নলিখিত সমর্থনটি v4 lib পদ্ধতিটি ব্যবহার করতে পারেন:

View viewYouNeedHeightFrom = ...
...
if(ViewCompat.isLaidOut(viewYouNeedHeightFrom)) {
   viewYouNeedHeightFrom.getHeight();
}

উইন্ডোতে সর্বশেষ সংযুক্ত বা বিচ্ছিন্ন হওয়ার পরে ভিউটি কমপক্ষে একটি বিন্যাসের মধ্য দিয়ে চলেছেলে সত্য প্রত্যাবর্তন করে।


অতিরিক্ত: স্থিরভাবে সংজ্ঞায়িত পরিমাপ পাওয়া

যদি কেবল স্থিতিশীলভাবে সংজ্ঞায়িত উচ্চতা / প্রস্থ পাওয়ার পক্ষে যথেষ্ট হয় তবে আপনি এটি দিয়ে এটি করতে পারেন:

তবে মনে রাখবেন, অঙ্কনের পরে এটি প্রকৃত প্রস্থ / উচ্চতার চেয়ে আলাদা হতে পারে। জাভাডোক পার্থক্যটি পুরোপুরি বর্ণনা করে:

একটি দৃশ্যের আকার প্রস্থ এবং উচ্চতা দিয়ে প্রকাশ করা হয়। একটি দৃশ্য আসলে প্রস্থ এবং উচ্চতার মানগুলির দুটি জোড়া রাখে।

প্রথম জুটি পরিমাপ করা প্রস্থ এবং পরিমাপ করা উচ্চতা হিসাবে পরিচিত। এই মাত্রাগুলি সংজ্ঞা দেয় যে ভিউটি তার পিতামাতার মধ্যে কতটা বড় হতে চায় (আরও তথ্যের জন্য লেআউট দেখুন)

দ্বিতীয় জোড়টি কেবল প্রস্থ এবং উচ্চতা বা কখনও কখনও অঙ্কন প্রস্থ এবং অঙ্কনের উচ্চতা হিসাবে পরিচিত। এই মাত্রাগুলি স্ক্রিনে অঙ্কনের সময় এবং বিন্যাসের পরে দৃশ্যটির আসল আকারকে সংজ্ঞায়িত করে। এই মানগুলি পরিমাপ করা প্রস্থ এবং উচ্চতা থেকে আলাদা হতে পারে না। গেটউইথ () এবং গেটহাইট () কল করে প্রস্থ এবং উচ্চতা পাওয়া যাবে।


1
আমি একটি খণ্ডে ভিউ.পোস্ট ব্যবহার করছি। যার পিতামাতার উচ্চতা 0 ডিপি এবং ওজন সেট রয়েছে তা আমাকে পরিমাপ করতে হবে। আমি যা কিছু চেষ্টা করি তা শূন্যের উচ্চতা ফেরায় (আমি বিশ্বব্যাপী বিন্যাস শ্রোতাদেরও চেষ্টা করেছি)। আমি যখন ভিউ.পোস্ট কোডটি 125 এর বিলম্বের সাথে অনভিউতে তৈরি করেছি তখন এটি কাজ করে তবে দেরি না করেই হয় না। ধারনা?
Psest328

6
খুব খারাপ আপনি কেবল একবার উত্তর উত্তোলন করতে পারেন, সত্যিই ভাল ব্যাখ্যা। আমি যদি আমার অ্যাপ্লিকেশনটি ছেড়ে দিয়ে সাম্প্রতিক অ্যাপ্লিকেশনগুলি থেকে এটি পুনরায় শুরু করি তবে ভিউ রোটেশনটিতে আমার সমস্যা ছিল। আমি যদি সেখান থেকে এটি সরিয়ে নিয়ে নতুন করে পুনঃসূচনা করি তবে সবকিছু ঠিক আছে। ভিউ.পোস্ট () আমার দিনটি বাঁচিয়েছে!
ম্যাথিয়াস

1
ধন্যবাদ। আমি সাধারণত View.post () (2 য় পদ্ধতি) ব্যবহার করি তবে এটি যদি কোনও পটভূমির থ্রেড থেকে ডাকা হয় তবে এটি কখনও কখনও কাজ করে না। সুতরাং, লিখতে ভুলবেন না runOnUiThread(new Runnable() {...}। বর্তমানে আমি 1 ম পদ্ধতির একটি প্রকরণ ব্যবহার করুন: addOnLayoutChangeListener। পরে এটি সরাতে ভুলবেন না: অপসারণ করুনআউটআউটচ্যাঞ্জলিস্টেনার। এটি ব্যাকগ্রাউন্ড থ্রেড থেকেও কাজ করে।
কুলমাইন্ড

2
দুর্ভাগ্যক্রমে আমার জন্য 'ভিউ.পস্ট ()' সারাক্ষণ কাজ করে না। আমার 2 টি প্রকল্প রয়েছে যা খুব মিল। একটি প্রকল্পে এটি কাজ করছে, অন্যদিকে কাজ করছে না। । :( উভয় অবস্থায় আমি 'onCreate ()' একটি ভ্রমণ থেকে পদ্ধতি থেকে পদ্ধতি কলে যেকোনো পরামর্শ কেন।?
আদ্রিয়ান Buciuman

1
আমি বিষয়টি খুঁজে। একটি প্রকল্পে দর্শন আছে android:visibility="gone", এবং অন্য প্রকল্পে দৃশ্যমান সম্পত্তি ছিল invisible। যদি দৃশ্যমানতা হয় goneতবে প্রস্থটি সর্বদা 0 থাকবে
অ্যাড্রিয়ান বুকিউমান

262

আমরা ব্যবহার করতে পারি

@Override
 public void onWindowFocusChanged(boolean hasFocus) {
  super.onWindowFocusChanged(hasFocus);
  //Here you can get the size!
 }

10
সুতরাং আমরা খণ্ডগুলিতে কীভাবে কাজ করতে পারি? এটি কেবল কার্যকলাপে কাজ করে?
ওলকুনমুস্তফা

8
এটি জিনিসটি করা উচিত তবে এর উত্তরটি হওয়া উচিত নয়। একজন ব্যবহারকারী উইন্ডোতে আঁকানোর পরিবর্তে যে কোনও সময়ে মাত্রা পেতে চান। এছাড়াও এই পদ্ধতিটি একাধিকবার বা প্রতিবার উইন্ডোতে পরিবর্তিত হওয়ার পরে (দেখুন লুকান, চলে যাওয়া, নতুন দর্শন যুক্ত করা ইত্যাদি called) নামে ডাকা হয়। সুতরাং এটি সাবধানে ব্যবহার করুন :)
ডাঃ এএনড্রো

1
এটি একটি হ্যাক এবং দেখে মনে হচ্ছে ভিউটি ট্রিউবার্সার ব্যবহার করা আরও ভাল।
i_am_jorf

অভদ্র শব্দটি বোঝানোর অর্থ নয়, তবে একটি স্বয়ংক্রিয় উত্পন্ন মন্তব্য (বিশেষত কোডের 2 লাইনে) রেখে দেওয়া খুব বেশি আত্মবিশ্বাস দেয় না যে আপনি আসলে কী করছেন তা আপনি জানেন।
নাটিক্স

দুর্ভাগ্যক্রমে, এটি আমার পক্ষে কার্যকর হয়নি। ভিউ ট্রিউবার্সার চেষ্টা করে আমার জন্য কাজ করেছে।
নরেন্দ্র সিং

109

আমি এই সমাধানটি ব্যবহার করেছি, যা আমি উইন্ডো ফোকাস চ্যাঞ্জড () এর চেয়ে ভাল think যদি আপনি কোনও ডায়ালগফ্র্যাগমেন্টটি খুলেন, তবে ফোনটি ঘোরান, যখন ব্যবহারকারী ডায়ালগটি বন্ধ করে তবেই উইন্ডোফোকাস চ্যাঞ্জড কল হবে):

    yourView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            // Ensure you call it only once :
            yourView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

            // Here you can get the size :)
        }
    });

সম্পাদনা করুন: সরানোর হিসাবে গ্লোবালঅনলআউটলাইস্টেনার অবচিত হ'ল, আপনার এখন করা উচিত:

@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {

    // Ensure you call it only once :
    if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
        yourView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }
    else {
        yourView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    }

    // Here you can get the size :)
}

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

2
এটির জন্য API 16 বা তার বেশি (জেলি বিন)
টমসভ

7
এটি এপিআই 16 প্রয়োজন হয় না! শুধুমাত্র ইস্যু পদ্ধতি removeGlobalOnLayoutListener এপিআই 16 থেকে নিন্দা করা হয়েছে, কিন্তু সব API লেভেলের সঙ্গে সহজ সমাধান সামঞ্জস্যপূর্ণ নেই - stackoverflow.com/questions/16189525/...
gingo

আপনার যদি শ্রোতা অপসারণের প্রয়োজন হয় যাতে এটি নিজেকে অনেকবার কল করে না এবং আপনার বিভিন্ন API এর সাথে সমস্যা হয় তবে আমি আপনাকে বর্গের শীর্ষে একটি মিথ্যা বুলিয়ান সেট করার পরামর্শ দিই এবং তারপরে মানগুলি ক্যাপচার করার পরে এটি সত্য করে দেয় যাতে এটি আবার মানগুলি ক্যাপচার করে না।
মনসুর ফাহাদ

আপনি যদি প্রথম রান করার পরে শ্রোতাকে সরিয়ে ফেলেন তবে আপনি ভুল মাত্রা পেতে পারেন: 02-14 10: 18: 53.786 15063-15063 / ধাঁধা ফ্রেম: উচ্চতা: 1647 প্রস্থ: 996 02-14 10: 18: 53.985 15063-15063 / ধাঁধা ফ্রেমমেন্ট: উচ্চতা : 1500 প্রস্থ: 996
লিওস লিটারাক

76

এই অ্যান্ড্রয়েড বিকাশকারীদের থ্রেডে ইয়ান যেমন বলেছে :

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

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

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


8
onSizeChanged আমার পক্ষে কাজ করেছিল। onWindowFocusedChanged আমার কাস্টম ভিউতে কল হয় না।
অ্যারোনমারিনো

এটি একটি ভাল সমাধান দেখায়, তবে onSizeChanged পদ্ধতিতে ওভাররাইড করতে আমার সর্বদা আমার কাস্টম ভিউটি কী তৈরি করা উচিত?
এম.এলসাকা

Bottom line, if you call getWidth() etc. in a constructor, it will return zero.এটি একটি বিঙ্গো আমার ইস্যুগুলির মূল।
মাইকনোরসন

আমি এই সমাধানটিকে টুকরো টুকরো করার পরামর্শ দিচ্ছি, কারণ কিছু অন্যান্য সমাধান আমার ক্ষেত্রে 0 ফিরে আসে।
উইন্ডারাইডার

66

স্ক্রিনে প্রদর্শিত হওয়ার আগে যদি আপনাকে কিছু উইজেটের প্রস্থ পেতে হয় তবে আপনি getMeasuredWidth () বা getMeasuredHeight () ব্যবহার করতে পারেন।

myImage.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
int width = myImage.getMeasuredWidth();
int height = myImage.getMeasuredHeight();

5
কোনও কারণে, এটি আমার পক্ষে কাজ করা একমাত্র উত্তর ছিল - ধন্যবাদ!
ফারবোদ সালামাত-জাদেহ

আমার কাছে একই, সবচেয়ে সহজ সমাধান, যা আমার পক্ষে কাজ করেছে
টিমা


1
@ কমন্সওয়্যার, বিশ্বব্যাপী বিন্যাস কলব্যাকে গাছের পর্যবেক্ষকগণের আগে এই সমাধানটি উচ্চতা এবং প্রস্থকে কীভাবে দেয়, তার একটি ব্যাখ্যা সহায়ক হবে।
মিগটিয়ান

21

OnPreDrawListener()পরিবর্তে আমি এটি ব্যবহার করব addOnGlobalLayoutListener(), যেহেতু এটি অন্যান্য শ্রোতার চেয়ে কিছুটা আগে বলা হয়।

    view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
    {
        @Override
        public boolean onPreDraw()
        {
            if (view.getViewTreeObserver().isAlive())
                view.getViewTreeObserver().removeOnPreDrawListener(this);

            // put your code here
            return true;
        }
    });

3
মনে রাখবেন যে, return falseমানে করতে বাতিল বর্তমান অঙ্কন পাসreturn trueপরিবর্তে , পরিবর্তে।
পাং

9

গ্লোবাল লেআউটে পর্যবেক্ষণ এবং প্রদত্ত কার্য সম্পাদন করার জন্য একটি কোটলিন এক্সটেনশন height

ব্যবহার:

view.height { Log.i("Info", "Here is your height:" + it) }

বাস্তবায়ন:

fun <T : View> T.height(function: (Int) -> Unit) {
    if (height == 0)
        viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                function(height)
            }
        })
    else function(height)
}

6

অ্যান্ড্রয়েডএক্সের একাধিক এক্সটেনশন ফাংশন রয়েছে যা আপনাকে এই ধরণের কাজের ভিতরে ভিতরে সহায়তা করে androidx.core.view

এর জন্য আপনার কোটলিন ব্যবহার করা দরকার।

এখানে সবচেয়ে ভাল ফিট করে এমনটি হ'ল doOnLayout:

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

ক্রিয়াটি কেবলমাত্র পরবর্তী লেআউটে একবার অনুরোধ করা হবে এবং তারপরে সরানো হবে।

আপনার উদাহরণে:

bt.doOnLayout {
    val ra = RotateAnimation(0,360,it.width / 2,it.height / 2)
    // more code
}

নির্ভরতা: androidx.core:core-ktx:1.0.0


এটিই একমাত্র সঠিক উত্তর। android.googlesource.com/platform/frameworks/support/+/…
hrules6872

1
এই এক্সটেনশনগুলি সত্যই গুরুত্বপূর্ণ এবং দরকারী
আহমদ না

5

আপনি যদি RxJava এবং RxBindings ব্যবহার করছেন তবে একটি লাইনার । বয়লারপ্লেট ছাড়াই অনুরূপ পন্থা। এটি টিম অটিনের উত্তরের মত সতর্কবাণী দমন করতে হ্যাককে সমাধান করে ।

RxView.layoutChanges(yourView).take(1)
      .subscribe(aVoid -> {
           // width and height have been calculated here
      });

এই হল. কখনও ফোন না করা সত্ত্বেও, সদস্যতা ছাড়ার প্রয়োজন নেই।


4

এটি ঘটে কারণ ভিউতে স্ফীত হতে আরও বেশি সময় প্রয়োজন। সুতরাং কল view.widthএবং view.heightমূল থ্রেডের পরিবর্তে, view.post { ... }আপনার viewইতিমধ্যে স্ফীত হয়েছে তা নিশ্চিত করার জন্য আপনার ব্যবহার করা উচিত । কোটলিনে:

view.post{width}
view.post{height}

জাভাতে আপনি কল করতে পারেন getWidth()এবং getHeight()পদ্ধতিগুলিতে একটিতে Runnableএবং পাস করতে পারেনRunnable পারেন view.post()

view.post(new Runnable() {
        @Override
        public void run() {
            view.getWidth(); 
            view.getHeight();
        }
    });

এটি সঠিক উত্তর নয় কারণ পোস্ট কোডটি কার্যকর করার সময় দৃশ্যটি পরিমাপ করা এবং ছাঁটাই করা হতে পারে। এটি একটি প্রান্তের কেস হবে .postতবে ভিউটি ছড়িয়ে দেওয়ার গ্যারান্টি দেয় না।
d.aemon

1
এই উত্তরটি দুর্দান্ত ছিল এবং আমার পক্ষে কাজ করেছিল। আপনাকে অনেক ধন্যবাদ এহসান
এমএমজি

3

উচ্চতা এবং প্রস্থটি শূন্য কারণ আপনার উচ্চতা এবং প্রস্থের জন্য অনুরোধ করার সময় দেখা দর্শন তৈরি করা হয়নি। এর একটি সহজ সমাধান

view.post(new Runnable() {
        @Override
        public void run() {
            view.getHeight(); //height is ready
            view.getWidth(); //width is ready
        }
    });

অন্যান্য পদ্ধতির তুলনায় এই পদ্ধতিটি সংক্ষিপ্ত এবং খাস্তা হিসাবে ভাল।


3

হতে পারে এটি কাউকে সহায়তা করে:

ভিউ ক্লাসের জন্য একটি এক্সটেনশন ফাংশন তৈরি করুন

ফাইলের নাম: ViewExt.kt

fun View.afterLayout(what: () -> Unit) {
    if(isLaidOut) {
        what.invoke()
    } else {
        viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                what.invoke()
            }
        })
    }
}

এটি এর পরে যে কোনও দৃষ্টিতে ব্যবহার করা যেতে পারে:

view.afterLayout {
    do something with view.height
}

2

উত্তরটি postভুল, কারণ আকারটি পুনরায় গণনা করা যায় না।
আর একটি গুরুত্বপূর্ণ বিষয় হ'ল ভিউ এবং এর পূর্বপুরুষদের অবশ্যই দৃশ্যমান হওয়া উচিত । তার জন্য আমি একটি সম্পত্তি ব্যবহার করি View.isShown

এখানে আমার কোটলিন ফাংশনটি, এটি ব্যবহারের কোথাও স্থাপন করা যেতে পারে:

fun View.onInitialized(onInit: () -> Unit) {
    viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            if (isShown) {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                onInit()
            }
        }
    })
}

এবং ব্যবহারটি হ'ল:

myView.onInitialized {
    Log.d(TAG, "width is: " + myView.width)
}

1

আপনি যদি কোটলিন ব্যবহার করেন

  leftPanel.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {

            override fun onGlobalLayout() {

                if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
                    leftPanel.viewTreeObserver.removeOnGlobalLayoutListener(this)
                }
                else {
                    leftPanel.viewTreeObserver.removeGlobalOnLayoutListener(this)
                }

                // Here you can get the size :)
                leftThreshold = leftPanel.width
            }
        })

0

গন দর্শনগুলি ব্যাকগ্রাউন্ডে অ্যাপ্লিকেশন হিসাবে 0 উচ্চতার হিসাবে ফিরে আসে। এটি আমার কোড (1oo% কাজ করে)

fun View.postWithTreeObserver(postJob: (View, Int, Int) -> Unit) {
    viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            val widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
            val heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
            measure(widthSpec, heightSpec)
            postJob(this@postWithTreeObserver, measuredWidth, measuredHeight)
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                @Suppress("DEPRECATION")
                viewTreeObserver.removeGlobalOnLayoutListener(this)
            } else {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
            }
        }
    })
}

0

আমাদের দেখার অপেক্ষা করা দরকার দেখার জন্য আঁকা হবে। এই উদ্দেশ্যে অনপ্রেড্রোল্লিস্টনার ব্যবহার করুন। কোটলিন উদাহরণ:

val preDrawListener = object : ViewTreeObserver.OnPreDrawListener {

                override fun onPreDraw(): Boolean {
                    view.viewTreeObserver.removeOnPreDrawListener(this)

                    // code which requires view size parameters

                    return true
                }
            }

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