কীভাবে কোনও দৃশ্যের মাত্রা পুনরুদ্ধার করবেন?


209

আমি গঠিত একটি দৃশ্য আছে TableLayout, TableRow and TextView। আমি এটি গ্রিডের মতো দেখতে চাই। আমার এই গ্রিডের উচ্চতা এবং প্রস্থ পাওয়া দরকার। পদ্ধতিগুলি getHeight()এবং getWidth()সর্বদা 0. ফিরে আসে যখন আমি গ্রিডকে গতিশীলভাবে ফর্ম্যাট করি এবং যখন আমি এক্সএমএল সংস্করণ ব্যবহার করি তখন এটি ঘটে।

কীভাবে দেখার জন্য মাত্রা পুনরুদ্ধার করবেন?


ফলাফলগুলি পরীক্ষা করতে আমি এখানে আমার পরীক্ষার প্রোগ্রামটি ডিবাগ-এ ব্যবহার করেছি:

import android.app.Activity;
import android.os.Bundle;
import android.widget.TableLayout;
import android.widget.TextView;

public class appwig extends Activity {  
    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.maindemo);  //<- includes the grid called "board"
      int vh = 0;   
      int vw = 0;

      //Test-1 used the xml layout (which is displayed on the screen):
      TableLayout tl = (TableLayout) findViewById(R.id.board);  
      tl = (TableLayout) findViewById(R.id.board);
      vh = tl.getHeight();     //<- getHeight returned 0, Why?  
      vw = tl.getWidth();     //<- getWidth returned 0, Why?   

      //Test-2 used a simple dynamically generated view:        
      TextView tv = new TextView(this);
      tv.setHeight(20);
      tv.setWidth(20);
      vh = tv.getHeight();    //<- getHeight returned 0, Why?       
      vw = tv.getWidth();    //<- getWidth returned 0, Why?

    } //eof method
} //eof class

কার্যকলাপের ক্ষেত্রে লেআউট প্রয়োগ হওয়ার পরে getWidth / Height ব্যবহার না করে getMeasuredWidth / Height ব্যবহার করুন।
ভুপস

9
ছেলেরা, সবার জন্যই কল করতে হবে getHeight()এবং getWidth()ক্রিয়াকলাপের জীবনচক্রের নিজের মতামতগুলি মাপতে বলার পরে, অন্য কথায়, এই ধরণের স্টাফটি করুন onResume()এবং এটিই। আপনার কোনও প্রত্যাশা করা উচিত নয় যে এখনও অবিকৃত কোনও অবজেক্টের এর মাত্রাগুলি জানতে হবে, এটি সম্পূর্ণ কৌশল। নীচে প্রস্তাবিত যাদুটির প্রয়োজন নেই।
ক্লাস স্ট্যাকার

2
কলিং getHeight()/Width()মধ্যে onResume()উত্পাদ করা হয়নি> 0 মান আমার জন্য।
দর্পণ

@ ক্লাসস্ট্যাকার ফ্র্যাগমেন্টের কী হবে?
zdd

@zdd দয়া করে একটি সম্পূর্ণ নতুন প্রশ্ন জিজ্ঞাসা করুন এবং একটি মন্তব্যে এখানে একটি রেফারেন্স পোস্ট করুন।
ক্লাস স্ট্যাকার

উত্তর:


418

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

সম্পাদনা: 07/05/11 মন্তব্যগুলি থেকে কোড অন্তর্ভুক্ত:

final TextView tv = (TextView)findViewById(R.id.image_test);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

    @Override
    public void onGlobalLayout() {
        LayerDrawable ld = (LayerDrawable)tv.getBackground();
        ld.setLayerInset(1, 0, tv.getHeight() / 2, 0, 0);
        ViewTreeObserver obs = tv.getViewTreeObserver();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            obs.removeOnGlobalLayoutListener(this);
        } else {
            obs.removeGlobalOnLayoutListener(this);
        }
    }

});

প্রথমে আমি আমার TextView( onGlobalLayout()পদ্ধতিটিতে অ্যাক্সেসের জন্য ) একটি চূড়ান্ত রেফারেন্স পাই । এর পরে, আমি ViewTreeObserverআমার কাছ থেকে পেয়েছি TextViewএবং একটি OnGlobalLayoutListenerওভাররাইডিং যুক্ত করছি onGLobalLayout(এখানে অনুরোধ করার জন্য একটি সুপার ক্লাস পদ্ধতি বলে মনে হচ্ছে না ...) এবং আমার কোড যুক্ত করা যা এই শ্রোতার মধ্যে দৃশ্যের পরিমাপ জানার প্রয়োজন। সমস্ত আমার জন্য প্রত্যাশিত কাজ করে, তাই আমি আশা করি এটি সহায়তা করতে সক্ষম হবে।


23
@ জর্জি বেইলি: একাধিক কলকে জয় করার জন্য আমি সম্প্রতি অন্য কারও পোস্ট দেখেছি (আমি নিজে এটি পরীক্ষা করি নি, তাই ওয়াইএমএমভি) ছিল (অন্লোবাললয়আউট () এর মধ্যে): tv.getViewTreeObserver().removeGlobalOnLayoutListener(this);এইভাবে শ্রোতাকে প্রথমবারের পরে অপসারণ করা উচিত এটি ঘটে.
কেভিন কপক

3
আমিও আবার সাহায্য করতে চাই আপনার যেমন কিছু করার দরকার হতে পারে: mView.getViewTreeObserver ()। সরানগ্লোবালঅনলয়আউটলাইজনার (গ্লোবাল লেআউটলিস্টনার); আপনি যদি একবার নিজের ভিউটির আকার পরিবর্তন করতে চান। আশা করি এই সহায়তা
হেনরি সাউ

7
প্রশ্নটি খুব পুরানো, তবে addOnLayoutChangeListenerকাজগুলিও ব্যবহার করছে! :)
এফএক্স

7
এছাড়াও, নোট করুন যে এপিআই 16 এর পর থেকে আপনার প্রয়োজন: যদি (android.os.Build.VERSION.SDK_INT> = 16) {দেখুন.getViewTreeObserver ()। সরানঅনগ্লোবাললয়আউটলিস্টার (এটি); } অন্য {ভিউ.জেটভিউটিউরিসরবার ()। অপসারণ গ্লোবালঅনলয়আউটলাইস্টার (এটি); }
এডিসন

2
গ্লোবালঅনলয়আউটলিস্টনারকে অপসারণ করা হওয়ায় এটি Eclipse এ সতর্কতা দেয়। এটা কি স্বাভাবিক? সময়ের সাথে সাথে, অবহিত কোড সতর্কতাগুলি সমস্তদিকে প্লাবিত হবে ...
জনি

82

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

@Override
public void onWindowFocusChanged (boolean hasFocus) {
        // the height will be set at this point
        int height = myEverySoTallView.getMeasuredHeight(); 
}

4
ডকুমেন্টেশনের উদ্ধৃতি দিতে, "এই ক্রিয়াকলাপটি ব্যবহারকারীর কাছে দৃশ্যমান কিনা এটির সেরা সূচক এটি।"
ক্যামেরন লোয়েল পামার

6
আপনার যে টুকরোটি ব্যবহার করতে হবে তার ক্ষেত্রে এটি কাজ করে না ViewTreeObserver
মিহির

ওপি বিশেষভাবে এটি দেখার জন্য কীভাবে তা জানতে চেয়েছিল
জাস্টড্যানিউল

স্ক্রোলভিউ মোট উচ্চতা এবং সর্বোচ্চ স্ক্রোলভিউ.সেটস্ক্রোলি () একই হবে? অর্থাত্ আমার ক্ষেত্রে আমি উপরের পদ্ধতির সাথে উচ্চতা পেয়েছি 702 এবং আমি getScrolly () থেকে সর্বোচ্চ মূল্য পেয়েছি 523,
হিতেশ ধামশানিয়া

আপনার ভিউটিকে অন্য কোনও এক্সএমএল ফাইল থেকে অন্তর্ভুক্ত করার সময় এই পদ্ধতিটিও কাজ করে না।
জে ডোঙ্গা

19

আপনি এমন কোনও উপাদানগুলির প্রস্থ এবং উচ্চতা পাওয়ার চেষ্টা করছেন যা এখনও আঁকেনি।

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

এবং, আমি ভুল হতে পারি, তবে setWidth()সর্বদা সম্মানিত হয় না, Layoutএটি তার শিশুদের দেয় এবং তাদের কীভাবে মাপানো যায় (কল করা child.measure()) তা স্থির করে, তাই যদি আপনি সেট করেন setWidth()তবে উপাদানটি আঁকার পরে আপনার এই প্রস্থটি পাওয়ার নিশ্চয়তা নেই।

আপনার যা প্রয়োজন তা হল getMeasuredWidth()ভিউটি আসলে আঁকার পরে কোথাও ব্যবহার করা (আপনার দেখার সাম্প্রতিকতম পরিমাপ)।

দেখব Activityসেরা মুহূর্ত খোঁজার জন্য জীবনচক্র।

http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

আমি বিশ্বাস করি একটি ভাল অনুশীলন এটি ব্যবহার করা হয় OnGlobalLayoutListener:

yourView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (!mMeasured) {
                // Here your view is already layed out and measured for the first time
                mMeasured = true; // Some optional flag to mark, that we already got the sizes
            }
        }
    });

আপনি সরাসরি এই কোডটি স্থাপন করতে পারেন onCreate()এবং যখন দেখানো হবে তখন তা অনুরোধ করা হবে।


দুর্ভাগ্যক্রমে এটি অনআরএসিউমেও কাজ করছে না। কমপক্ষে এমুলেটরটিতে অনআরেসিউম কল করার পরে চূড়ান্ত মাত্রা সেট করা হয়েছে।
jki

এটি একটি ভয়াবহ অনুশীলন !!! এই শ্রোতাকে বারবার ডাকা হবে এবং আপনার অভিনয়টি মেরে ফেলবে। পতাকা ব্যবহারের পরিবর্তে শ্রোতাদের একবার হয়ে নিবন্ধভুক্ত করুন।
নীল

15

ভিউ'র পোস্ট পদ্ধতিটি এভাবে ব্যবহার করুন

post(new Runnable() {   
    @Override
    public void run() {
        Log.d(TAG, "width " + MyView.this.getMeasuredWidth());
        }
    });

1
যে কাজ করে, কিন্তু সত্যিই, কেন কোন আলোচনা? বিটিডব্লিউ, এটি কাজ করে কারণ লেআউটটি সংঘটিত না হওয়া পর্যন্ত রান্নেবল চালিত হয় না।
নরম্যান এইচ

7

আমি এটির onGlobalLayout()কিছু কাস্টম বিন্যাস করার চেষ্টা করেছি TextView, তবে @ জর্জ বেইলি যেমন লক্ষ্য করেছেন, onGlobalLayout()অবশ্যই দুটি বার বলা হয়েছে: একবার প্রাথমিক বিন্যাসের পথে এবং দ্বিতীয় বার পাঠ্য পরিবর্তন করার পরে।

View.onSizeChanged()আমার পক্ষে আরও ভাল কাজ করে কারণ আমি যদি সেখানে পাঠ্য সংশোধন করি তবে পদ্ধতিটি কেবল একবার (লেআউট পাসের সময়) বলা হয়। এটির প্রয়োজনীয় উপ-শ্রেণিবদ্ধকরণ TextView, তবে এপিআই স্তরে 11+ View. addOnLayoutChangeListener()উপ-শ্রেণিবদ্ধকরণ এড়াতে ব্যবহার করা যেতে পারে।

আরও একটি জিনিস, ভিউটির সঠিক প্রস্থের জন্য View.onSizeChanged(), layout_widthসেট করা উচিত match_parent, নয় wrap_content


2

আপনি প্রকৃত চিত্র পাওয়ার আগে আপনি কোনও নির্মাণকারীর আকার বা অন্য কোনও পদ্ধতিতে চালিত হওয়ার চেষ্টা করছেন?

সমস্ত উপাদানগুলি প্রকৃতপক্ষে পরিমাপ করার আগে আপনি কোনও মাত্রা পাচ্ছেন না (যেহেতু আপনার এক্সএমএল আপনার প্রদর্শন আকার, পিতামাতার অবস্থান এবং যা কিছু সম্পর্কে জানেন না)

OnSizeChanged () এর পরে মানগুলি পাওয়ার চেষ্টা করুন (যদিও এটি শূন্যের সাথে ডাকা যেতে পারে), অথবা কেবল আপনি যখন আসল চিত্র পাবেন তখন অপেক্ষা করুন।


আমি আমার আসল প্রশ্ন এবং কোডটি আরও পরিষ্কার করে আপডেট করেছি। ধন্যবাদ.

2

এফএক্স যেমন উল্লেখ করেছে, আপনি OnLayoutChangeListenerনিজের দৃষ্টিভঙ্গি দেখতে চান এমন একটি ব্যবহার করতে পারেন

view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
    @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
        // Make changes
    }
});

আপনি যদি কেবল প্রাথমিক বিন্যাস চান তবে আপনি কলব্যাকটিতে শ্রোতাদের সরাতে পারবেন।


2

আমার ধারণা আপনারা এটি দেখার দরকার: onSizeChanged()আপনার দৃষ্টিভঙ্গির ব্যবহার । এখানে কিভাবে ব্যবহার করবেন তার একটি বর্ধিত কোড স্নিপেট হয় onSizeChanged()আপনার লেআউট বা দৃশ্য উচ্চতা এবং প্রস্থ পরিবর্তনশীল পেতে http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.html


1

ViewTreeObserverএবং onWindowFocusChanged()এগুলি এতটা প্রয়োজনীয় নয়।

আপনি যদি TextViewলেআউট হিসাবে স্ফীত হন এবং / অথবা এতে কিছু সামগ্রী রেখে সেট করেন LayoutParamsতবে আপনি ব্যবহার করতে পারেন getMeasuredHeight()এবং getMeasuredWidth()

তবে আপনাকে সতর্কতা অবলম্বনLinearLayouts করতে হবে (সম্ভবত অন্য কোনও ক্ষেত্রে ViewGroups)। সমস্যাটি হ'ল, আপনি প্রস্থ এবং উচ্চতা এর পরে পেতে পারেন onWindowFocusChanged()তবে আপনি যদি এতে কিছু মতামত যুক্ত করার চেষ্টা করেন তবে সমস্ত কিছু টানা না হওয়া পর্যন্ত আপনি সেই তথ্যটি পেতে পারবেন না। আমি একটি (মোড়ানোর শৈলী) নকল TextViewsকরতে একাধিক যুক্ত করার চেষ্টা করছিলাম এবং তাই ব্যবহার করতে পারিনি । প্রক্রিয়াটি শুরু হয়ে গেলে এটি সিঙ্ক্রোনসিভভাবে চালিয়ে যাওয়া উচিত। সুতরাং এই জাতীয় ক্ষেত্রে, আপনি পরে এটিকে ব্যবহার করতে প্রস্থটি কোনও ভেরিয়েবলের মধ্যে রাখতে চান, লেআউটে ভিউ যুক্ত করার সময় আপনার এটির প্রয়োজন হতে পারে।LinearLayoutsFlowLayoutListeners


1

যদিও প্রস্তাবিত সমাধানটি কাজ করে, এটি প্রতিটি ক্ষেত্রে সেরা সমাধান নাও হতে পারে কারণ ডকুমেন্টের ভিত্তিতে ViewTreeObserver.OnGlobalLayoutListener

গ্লোবাল বিন্যাসের স্থিতি বা দৃশ্য গাছের মধ্যে দর্শনগুলির দৃশ্যমানতার পরিবর্তিত হলে কলব্যাকের জন্য ইন্টারফেস সংজ্ঞাটি ডাকা হয়।

যার অর্থ এটি বহুবার বলা হয়ে থাকে এবং সবসময় দৃশ্যটি পরিমাপ করা হয় না (এটির দৈর্ঘ্য এবং প্রস্থ নির্ধারিত রয়েছে)

বিকল্পটি ব্যবহার করা হয় ViewTreeObserver.OnPreDrawListenerযা কেবল তখনই কল করা হয় যখন দৃশ্যটি আঁকতে প্রস্তুত থাকে এবং এর সমস্ত পরিমাপ থাকে।

final TextView tv = (TextView)findViewById(R.id.image_test);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnPreDrawListener(new OnPreDrawListener() {

    @Override
    public void onPreDraw() {
        tv.getViewTreeObserver().removeOnPreDrawListener(this);
        // Your view will have valid height and width at this point
        tv.getHeight();
        tv.getWidth();
    }

});

0

পরিবর্তে আপনার জীবনচক্র দেখুন দেখুন: http://developer.android.com/references/android/view/View.html সাধারণত আপনার ক্রিয়াকলাপটি পুনরায় শুরু না হওয়া অবধি আপনার প্রস্থ এবং উচ্চতা সম্পর্কে নিশ্চিত হওয়া উচিত নয়।


0

আপনি একটি সম্প্রচার ব্যবহার করতে পারেন যা অনারিউম () নামে ডাকা হয়

উদাহরণ স্বরূপ:

int vh = 0;   
int vw = 0;

public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.maindemo);  //<- includes the grid called "board"

      registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                TableLayout tl = (TableLayout) findViewById(R.id.board);  
                tl = (TableLayout) findViewById(R.id.board);
                vh = tl.getHeight();       
                vw = tl.getWidth();               
            }
      }, new IntentFilter("Test"));
}

protected void onResume() {
        super.onResume();

        Intent it = new Intent("Test");
        sendBroadcast(it);

}

আপনি যে কারণে কেকপপকের প্রতিক্রিয়া দেখিয়েছেন তাতে অনক্রিয়াট (), অন স্টার্ট (), এমনকি এমনকি অনারিউম () তেও একটি দর্শন উচ্চতা পেতে পারবেন না


0

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

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

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


-1

সাধারণ প্রতিক্রিয়া: এটি কোনও সমস্যা ছাড়াই আমার পক্ষে কাজ করেছে। দেখে মনে হচ্ছে কীটি হাইট পাওয়ার আগে ভিউটিতে ফোকাস রয়েছে তা নিশ্চিত করা etc. হ্যাশফোকাস () পদ্ধতিটি ব্যবহার করে, তারপর সেই ক্রমে getHeight () পদ্ধতি ব্যবহার করে এটি করুন। কোডের মাত্র 3 লাইন প্রয়োজন।

ImageButton myImageButton1 =(ImageButton)findViewById(R.id.imageButton1); myImageButton1.hasFocus();

int myButtonHeight = myImageButton1.getHeight();

Log.d("Button Height: ", ""+myButtonHeight );//Not required

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


-3

আপনার দর্শনের জন্য getMeasuredWidth () এবং getMeasuredHeight () ব্যবহার করুন।

বিকাশকারী গাইড: দেখুন


4
যেহেতু এই পদ্ধতি সামনে বিবৃত শুধুমাত্র একটি বৈধ ফলাফল আসতে efter আকার meassured হয়েছে। ক্রিয়াকলাপের মধ্যে এটি সত্য হয়ে যায় যখন উইন্ডো ফোকাস চ্যাঞ্জড ওএস পদ্ধতিটি কল করে।
স্লট

-8

সংশোধন: আমি খুঁজে পেয়েছি যে উপরের সমাধানটি ভয়ানক। বিশেষত যখন আপনার ফোনটি ধীর হয়। এবং এখানে আমি আরও একটি সমাধান পেয়েছি: মার্জিন এবং প্যাডিং সহ উপাদানটির px মান গণনা করুন: dp থেকে px: https://stackoverflow.com/a/6327095/1982712

বা dimens.xML থেকে px: https://stackoverflow.com/a/16276351/1982712

sp থেকে px: https://stackoverflow.com/a/9219417/1982712 (সমাধানটি বিপরীত করুন)

বা ডাইমেন্স পিক্সে: https://stackoverflow.com/a/16276351/1982712

এবং এটাই.


10
এটি নির্ধারণ করা সাধারণত একটি খারাপ ধারণা যে কিছু নির্বিচারে নির্বাচিত সংখ্যক মিলিসেকেন্ডের পরে সবকিছু সঠিকভাবে সেট হয়ে যাবে। ডিভাইসটি ধীর হতে পারে, অন্যান্য প্রক্রিয়াগুলি / থ্রেডগুলি চলমান থাকতে পারে, ডিবাগারে কাজ নাও করতে পারে, ওএসের পরবর্তী সংস্করণে কাজ নাও করতে পারে, ...
ক্রিস্টোফার জনসন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.