OnMeasure () কে ওভাররাইড করার রচনামূলক উপায়?


89

ওভারঅরাইডিংয়ের সঠিক পদ্ধতিটি কি পরিমাণে ()? আমি বিভিন্ন পন্থা দেখেছি। উদাহরণস্বরূপ, পেশাদার অ্যান্ড্রয়েড বিকাশ পরিমাপগুলি গণনা করার জন্য মেজারস্পেক ব্যবহার করে, তারপরে সেটমিজুরডিমাইশন () সেট করার কল দিয়ে শেষ হয়। উদাহরণ স্বরূপ:

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth/2, parentHeight);
}

অন্যদিকে, অনুযায়ী এই পোস্টে , "সঠিক" পথ MeasureSpec ব্যবহার করা, কল setMeasuredDimensions (), দ্বারা অনুসরণ setLayoutParams () একটি কল, এবং super.onMeasure একটি কল () দিয়ে শেষ। উদাহরণ স্বরূপ:

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth/2, parentHeight);
this.setLayoutParams(new *ParentLayoutType*.LayoutParams(parentWidth/2,parentHeight));
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

তাহলে সঠিক পথটি কোনটি? উভয়ই আমার পক্ষে 100% কাজ করে না।

আমি অনুমান করি যে আমি যা জিজ্ঞাসা করছি তা কি কেউ এমন টিউটোরিয়াল সম্পর্কে জানে যে onMeasure (), লেআউট, শিশু দর্শনের মাত্রা ইত্যাদি ব্যাখ্যা করে?


16
আপনি উত্তরটি সঠিক / সঠিক খুঁজে পেয়েছেন? কেন হিসাবে চিহ্নিত না উত্তর দিয়েছিলেন?
সুপারজোজ

উত্তর:


69

অন্যান্য সমাধানগুলি ব্যাপক নয়। তারা কিছু ক্ষেত্রে কাজ করতে পারে এবং এটি শুরু করার জন্য ভাল জায়গা তবে তারা কাজ করার নিশ্চয়তা পায় না।

অনম্যাসার যখন কল হয় তখন আপনাকে আকার পরিবর্তন করার অধিকার থাকতে পারে বা থাকতে পারে না। আপনার অন-মেজার ( widthMeasureSpec, heightMeasureSpec) এ যে মানগুলি পাস করা হয়েছে সেগুলিতে আপনার সন্তানের দর্শন কী করতে দেওয়া হচ্ছে সে সম্পর্কে তথ্য রয়েছে। বর্তমানে তিনটি মান রয়েছে:

  1. MeasureSpec.UNSPECIFIED - আপনি নিজের মতো করে বড় হতে পারেন
  2. MeasureSpec.AT_MOST - আপনি যতটা বড় চান (ফটোগুলি আকার পর্যন্ত), এটি parentWidth আপনার উদাহরণে।
  3. MeasureSpec.EXACTLY- কোন পছন্দ নাই. পিতা বা মাতা বেছে নিয়েছে।

এটি করা হয়েছে যাতে প্রতিটি আইটেমের জন্য সঠিক আকার খুঁজতে অ্যান্ড্রয়েড একাধিক পাস করতে পারে, এখানে দেখুন আরো বিস্তারিত জানার জন্য।

আপনি যদি এই বিধিগুলি অনুসরণ না করেন তবে আপনার পদ্ধতির কাজ করার গ্যারান্টি নেই।

উদাহরণস্বরূপ, আপনি যদি আকারটি একেবারে পরিবর্তন করার অনুমতি পেয়ে থাকেন তবে আপনি যা করতে চান তা পরীক্ষা করতে চান:

final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
boolean resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
boolean resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;

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

int রিসাইজএন্ডস্টেট (ইনট সাইজ, ইন্ট মাপারস্পেস, ইন চাইল্ডমিউজড স্টেট)

int রিসাইজ সাইজ (ইনট সাইজ, ইন্ট মাপারস্পেস)

প্রথমটি কেবল হানিকম্বে উপলভ্য থাকলেও দ্বিতীয়টি সমস্ত সংস্করণে উপলভ্য।

দ্রষ্টব্য: আপনি এটি খুঁজে পেতে পারেন resizeWidthবা resizeHeightসর্বদা মিথ্যা। আমি অনুরোধ করা হলে আমি এটি কেস হিসাবে পেয়েছি MATCH_PARENT। আমি WRAP_CONTENTআমার প্যারেন্ট লেআউটটিতে অনুরোধ করে এবং তারপরে UNSPECIFIED পর্যায়ে একটি আকারের অনুরোধ করে এটি ঠিক করতে সক্ষম হয়েছি Integer.MAX_VALUE। এটি করা আপনাকে আপনার পিতামাতার অনম্যাসের মাধ্যমে পরবর্তী পাসে সর্বাধিক আকার দেয়।


39

এই বিষয়ে ডকুমেন্টেশন হ'ল কর্তৃপক্ষ: http://developer.android.com/guide/topics/ui/how-android-draws.html এবং http://developer.android.com/guide/topics/ui/custom -কম্পোনস html

সংক্ষিপ্তসার হিসাবে: আপনার ওভাররাইড onMeasureপদ্ধতির শেষে আপনার কল করা উচিতsetMeasuredDimension

কল করার super.onMeasureপরে আপনাকে কল করা উচিত নয় setMeasuredDimension, যা আপনি সেট করেছেন তা কেবল মুছে ফেলবে। কিছু পরিস্থিতিতে আপনি super.onMeasureপ্রথমে কল করতে পারেন এবং তারপরে ফোন করে ফলাফল পরিবর্তন করতে পারেন setMeasuredDimension

ডেকো না setLayoutParamsযে onMeasure। বিন্যাস পরিমাপের পরে দ্বিতীয় পাসে ঘটে happens


আমার অভিজ্ঞতা হ'ল যদি আমি সুপার.অনম্যাসারকে কল না করে ওমেনসারকে ওভাররাইড করি তবে শিশুদের মতামতগুলিতে অনলয়েট কল করা হবে না।
উইলিয়াম জকুশ

2

আমি মনে করি এটি আপনার পিতামাতার উপর নির্ভর করে যা আপনি ওভাররাইড করছেন।

উদাহরণস্বরূপ, আপনি যদি আকারটি পরিমাপ করেছেন, যখন আপনি একটি ভিউগ্রুপ (ফ্রেমলাইআউটের মতো) প্রসারিত করছেন, আপনার নীচের মত কল করা উচিত

super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));

কারণ আপনি বিশ্রাম কাজটি বিশ্রামের কাজ করতে চান (শিশু দর্শনে কিছু স্টাফ করুন)

যদি আপনি একটি ভিউ (ইমেজভিউয়ের মতো) প্রসারিত করে থাকেন তবে আপনি কেবল কল করতে পারেন this.setMeasuredDimension(width, height);, কারণ পিতামাত্ত শ্রেণি সাধারণত আপনার মতো কিছু করবে।

এক কথায়, যদি আপনি কিছু বৈশিষ্ট্য চান তবে আপনার পিতামাতার ক্লাসটি আপনাকে বিনামূল্যে কল করতে হবে super.onMeasure()(MeasureSpec.EXACTLY মোড পরিমাপের বৈশিষ্টটি সাধারণত পাস করুন), অন্যথায় কল this.setMeasuredDimension(width, height);যথেষ্ট।


1

এখানে আমি কীভাবে সমস্যার সমাধান করেছি:

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

        ....

        setMeasuredDimension( measuredWidth, measuredHeight );

        widthMeasureSpec = MeasureSpec.makeMeasureSpec( measuredWidth, MeasureSpec.EXACTLY );
        heightMeasureSpec = MeasureSpec.makeMeasureSpec( measuredHeight, MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

}

তবুও ভিউপেজার উপাদানটির জন্য এটি প্রয়োজনীয় ছিল


4
এটি সঠিক সমাধান নয়। super.onMeasureব্যবহার করে সেট মাত্রা সাফ করবে setMeasuredDimension
টমরোজব

@tomrozb এটা না humptydevelopers.com/2013/05/... এবং আপনার অ্যান্ড্রয়েড সূত্র পরীক্ষা করতে পারবেন
Yuli Reiri

@ ইউলিরিরি: নিখুঁত সমাধান!
শায়ান তাবতাবাই

0

onMeasureআপনার সমস্ত প্রয়োজনের ভিতরে ভিউজের আকার পরিবর্তন করা হলে setMeasuredDimensionকল হয়। আপনি যদি আকারের বাইরে থাকেন তবে onMeasureআপনার কল করতে হবে setLayoutParams। উদাহরণস্বরূপ যখন পাঠ্য পরিবর্তন করা হয় তখন একটি পাঠ্য দৃশ্যের আকার পরিবর্তন করা।


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

0

আপনি যে নিয়ন্ত্রণটি ব্যবহার করছেন তার উপর নির্ভর করে। ডকুমেন্টেশনের নির্দেশাবলী কিছু নিয়ন্ত্রণের জন্য কাজ করে (টেক্সটভিউ, বোতাম, ...) তবে অন্যদের জন্য নয় (লিনিয়ারলআউট, ...)। আমার জন্য যে পদ্ধতিটি খুব ভালভাবে কাজ করেছিল তা হ'ল একবার হয়ে গেলে সুপারকে কল করা। নীচের লিঙ্কে নিবন্ধের ভিত্তিতে।

http://humptydevelopers.blogspot.in/2013/05/android-view-overriding-onmeasure.html


-1

আমার ধারণা, লেআউটপ্যারামগুলি সেট করা এবং পরিমাপগুলি পুনরায় গণনা করা শিশুদের দৃষ্টিভঙ্গিগুলিকে সঠিকভাবে আকার দেওয়ার জন্য এক কার্যকরী কাজ, কারণ এটি সাধারণত ডেরিভড ক্লাসের onMeasure এ করা হয়।

তবে, এটি খুব কমই সঠিকভাবে কাজ করে (যাই হোক না কেন কারণেই ...), পরিমাপের চিকিত্সা (বাছাইয়ের গোষ্ঠীটি প্রাপ্ত করার সময়) বা প্রয়োজনীয় হলে অনুরূপ কিছু চেষ্টা করুন।


-5

আপনি কোডটির এই অংশটি onMeasure () এর উদাহরণ হিসাবে নিতে পারেন ::

public class MyLayerLayout extends RelativeLayout {

    public MyLayerLayout(Context context) {
        super(context);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);

        int currentChildCount = getChildCount();
        for (int i = 0; i < currentChildCount; i++) {
            View currentChild = getChildAt(i);

            //code to find information

            int widthPercent = currentChildInfo.getWidth();
            int heightPercent = currentChildInfo.getHeight();

//considering we will pass height & width as percentage

            int myWidth = (int) Math.round(parentWidth * (widthPercent / 100.0));
            int myHeight = (int) Math.round(parentHeight * (heightPercent / 100.0));

//Considering we need to set horizontal & vertical position of the view in parent

            AlignmentTraitValue vAlign = currentChildInfo.getVerticalLocation() != null ? currentChildlayerInfo.getVerticalLocation() : currentChildAlignmentTraitValue.TOP;
            AlignmentTraitValue hAlign = currentChildInfo.getHorizontalLocation() != null ? currentChildlayerInfo.getHorizontalLocation() : currentChildAlignmentTraitValue.LEFT;
            int topPadding = 0;
            int leftPadding = 0;

            if (vAlign.equals(currentChildAlignmentTraitValue.CENTER)) {
                topPadding = (parentHeight - myHeight) / 2;
            } else if (vAlign.equals(currentChildAlignmentTraitValue.BOTTOM)) {
                topPadding = parentHeight - myHeight;
            }

            if (hAlign.equals(currentChildAlignmentTraitValue.CENTER)) {
                leftPadding = (parentWidth - myWidth) / 2;
            } else if (hAlign.equals(currentChildAlignmentTraitValue.RIGHT)) {
                leftPadding = parentWidth - myWidth;
            }
            LayoutParams myLayoutParams = new LayoutParams(myWidth, myHeight);
            currentChildLayoutParams.setMargins(leftPadding, topPadding, 0, 0);
            currentChild.setLayoutParams(myLayoutParams);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

6
এই কোডটি মূলত ভুল। প্রথমত, এটি লেআউট মোডটিকে বিবেচনায় নেয় না (গ্রিমাসের উত্তর দেখুন)। এটি খারাপ তবে আপনি এর প্রভাব দেখতে পাবেন না কারণ আপনি একেবারে শেষে সুপার.অনম্যাসার () কেও কল করেন যা আপনার নির্ধারিত মানগুলিকে ওভাররাইড করে (স্যাটার9nine এর উত্তর দেখুন) এবং onMeasure () কে ওভাররাইডিংয়ের উদ্দেশ্যটি একেবারে পরাস্ত করে।
spaaarky21
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.