আমি কীভাবে প্রোগ্রামে অ্যান্ড্রয়েড নেভিগেশন বারের উচ্চতা এবং প্রস্থ পাব?


122

স্ক্রিনের নীচে কালো নেভিগেশন বারটি অ্যান্ড্রয়েডে সহজেই অপসারণযোগ্য নয়। হার্ডওয়্যার বোতামগুলির প্রতিস্থাপন হিসাবে এটি 3.0 থেকে অ্যান্ড্রয়েডের অংশ। এখানে একটি ছবি:

সিস্টেম বার

আমি পিক্সেলগুলিতে এই ইউআই উপাদানটির প্রস্থ এবং উচ্চতা কীভাবে পেতে পারি?


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

উত্তর:


178

কোড নীচে চেষ্টা করুন:

Resources resources = context.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
    return resources.getDimensionPixelSize(resourceId);
}
return 0;

7
ধন্যবাদ। +1 টি। আপনি জানেন যে এই পদ্ধতির কতটা স্থিতিশীল? রিসোর্স শনাক্তকারীরা কি বিভিন্ন প্ল্যাটফর্ম সংস্করণ জুড়ে পরিবর্তিত হতে পারে?
বেন পিয়ারসন

59
নোট করুন যে এই কোডের টুকরাটি নেভিগেশন বার ছাড়াই ডিভাইসে 0 ফেরায় না। স্যামসুং এস 2 এবং এস 3-তে পরীক্ষিত। আমি পেয়েছি 72 এবং 96.
Egis

4
আমার উত্তর এ @Egidijus তাকান, এটি ডিভাইস আছে শারীরিক নেভিগেশনের জন্য 0 ফিরে আসবে stackoverflow.com/a/29938139/1683141
Mdlc

1
গ্যালাক্সি এস edge প্রান্তটিও 0 ফিরে আসে না, যদিও নীচে কোনও নেভিগেশন বার নেই। 192. ফিরে আসে
আগামোভ

5
এই কোডটি নেভিগেশন বারের ডিফল্ট আকার দেখায় ( navigation_bar_height_landscapeল্যান্ডস্কেপ মোডে নেভিগেশন বারের উচ্চতার navigation_bar_widthজন্য এবং উল্লম্ব নেভিগেশন বারের প্রস্থের জন্যও চেষ্টা করুন )। নেভিগেশন বারটি আসলে প্রদর্শিত হচ্ছে কিনা এবং আপনাকে আলাদাভাবে খুঁজে বের করতে হবে, যেমন কোনও শারীরিক মেনু বোতামের উপস্থিতি পরীক্ষা করে for হতে পারে আপনি সাইটে Android souce কোডে পরিবর্তে অন্য কোন ভাবে জানতে পারেন android.googlesource.com/platform/frameworks/base/+/...
user149408

103

বাস্তব-পর্দার আকারের সাথে অ্যাপ-ব্যবহারযোগ্য স্ক্রিন আকারের তুলনা করে আমি নেভিগেশন বারের আকার পাই get আমি ধরে নিয়েছি যে অ্যাপ্লিকেশন-ব্যবহারযোগ্য স্ক্রিনের আকারটি বাস্তব পর্দার আকারের চেয়ে ছোট হলে নেভিগেশন বারটি উপস্থিত থাকে। তারপরে আমি নেভিগেশন বারের আকারটি গণনা করি। এই পদ্ধতিটি 14 এবং ততোধিক এপিআই সহ কাজ করে।

public static Point getNavigationBarSize(Context context) {
    Point appUsableSize = getAppUsableScreenSize(context);
    Point realScreenSize = getRealScreenSize(context);

    // navigation bar on the side
    if (appUsableSize.x < realScreenSize.x) {
        return new Point(realScreenSize.x - appUsableSize.x, appUsableSize.y);
    }

    // navigation bar at the bottom
    if (appUsableSize.y < realScreenSize.y) {
        return new Point(appUsableSize.x, realScreenSize.y - appUsableSize.y);
    }

    // navigation bar is not present
    return new Point();
}

public static Point getAppUsableScreenSize(Context context) {
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = windowManager.getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);
    return size;
}

public static Point getRealScreenSize(Context context) {
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = windowManager.getDefaultDisplay();
    Point size = new Point();

    if (Build.VERSION.SDK_INT >= 17) {
        display.getRealSize(size);
    } else if (Build.VERSION.SDK_INT >= 14) {
        try {
            size.x = (Integer) Display.class.getMethod("getRawWidth").invoke(display);
            size.y = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
        } catch (IllegalAccessException e) {} catch (InvocationTargetException e) {} catch (NoSuchMethodException e) {}
    }

    return size;
}

হালনাগাদ

অ্যাকাউন্টে ডিসপ্লে কাটআউটগুলি গ্রহণ করে এমন কোনও সমাধানের জন্য দয়া করে জন এর উত্তর পরীক্ষা করে দেখুন ।


2
এটিই একমাত্র সমাধান যা আমার জন্য পরীক্ষা করা সমস্ত ডিভাইস জুড়ে কাজ করে। আমার রেক হ'ল অরিয়েন্টেশনটি গ্রহণ করে নেভারটি পর্দার নীচে রয়েছে কিনা তা নির্ধারণ করা। আমি আমাকে স্ক্রিনের নীচে এনএভি বারের আকারটি ফিরিয়ে দিতে উত্তরে কোডটি সামান্য টুইট করেছি, 0টি উপস্থিত নেই তা নির্দেশ করে। আমার পরীক্ষাটি দেখায় যে Nexus5 = প্রতিকৃতি: 144, ল্যান্ডস্কেপ: 0 | Nexus7 = প্রতিকৃতি: 96, ল্যান্ডস্কেপ: 96 | স্যামসাং নোট II = প্রতিকৃতি: 0, ল্যান্ডস্কেপ: 0 | স্যামসাং এস 10 = প্রতিকৃতি: 0, ল্যান্ডস্কেপ: 0
se22as

2
আমি নিশ্চিত করতে পারি যে ড্যানিয়েলোর সমাধানটি কেবলমাত্র কিছু মডেলগুলিতে কাজ করে। এজিডিজাসের এই সমাধানটি একটি কার্যকরী সমাধান এবং এটি এখন পর্যন্ত পরীক্ষিত সমস্ত মডেলের জন্য কাজ করেছে। এই জন্য আপনাকে ধন্যবাদ.
বিস্ক্লাভ্রেট

2
স্ট্যাটাস বারটি অ্যাপ ব্যবহারযোগ্য স্ক্রিনের অংশ part
ডিম

1
এটি কাজ করে তবে বিদ্যমান বারটি লুকিয়ে আছে কিনা তা বিবেচনা করে না। এই চেক কিভাবে কোন ধারণা?
এক্স-হুমান

1
এটি নেভিগেশন বারের পরিবর্তে নেভিগেশন অঙ্গভঙ্গি চলাকালীন অ্যান্ড্রয়েড পি এর জন্য কাজ করছে না। আপনি কি দয়া করে আমাকে এই পরিস্থিতির জন্য কীভাবে সমাধান করবেন তা গাইড করতে পারেন
নিক

36

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

public int getNavBarHeight(Context c) {
         int result = 0;
         boolean hasMenuKey = ViewConfiguration.get(c).hasPermanentMenuKey();
         boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);

         if(!hasMenuKey && !hasBackKey) {
             //The device has a navigation bar
             Resources resources = c.getResources();

             int orientation = resources.getConfiguration().orientation;
             int resourceId;
             if (isTablet(c)){
                 resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "android");
             }  else {
                 resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_width", "dimen", "android");     
             }

             if (resourceId > 0) {
                 return resources.getDimensionPixelSize(resourceId);
             }
         }
         return result;
} 


private boolean isTablet(Context c) {
    return (c.getResources().getConfiguration().screenLayout
            & Configuration.SCREENLAYOUT_SIZE_MASK)
            >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}

এটি আমার পক্ষে কাজ করে না, Nexus5 hasMenuKey এবং hasBackKey এর জন্য সত্য ফিরে আসে তাই এটি মনে করে যে কোনও নাবার নেই। (Nexus7 সঠিকভাবে #MenuKey এবং #BackKey এর জন্য মিথ্যা ফিরিয়ে দিয়েছে)
se22as

5
আমি এই কোডটি নেক্সাস 5 এ পরীক্ষা করেছি এবং এটি উভয়ের জন্যই মিথ্যা প্রত্যাবর্তন করে। আপনি কি নিশ্চিত যে কোনও এমুলেটর বা রোমে নেই?
মোডলক

হ্যাঁ আমি একটি এমুলেটর ব্যবহার করছিলাম, দুঃখিত আমার আগে আমার বিবৃতিতে স্পষ্ট করা উচিত ছিল
se22as

এটি হওয়া উচিত নয়! #MenuKey || মেনুকি && এর! হ্যাকব্যাকির পরিবর্তে! দয়া করে যাচাই করুন
yongsunCN

2
দুর্ভাগ্যক্রমে, সনি এক্স্পেরিয়া জেড 3 এ কাজ করে না hasBackKey = false!যদিও এটি সত্য হওয়া উচিত। নিম্নলিখিতটি পরিবর্তে কাজ করেছে: boolean navBarExists = getResources().getBoolean(getResources().getIdentifier("config_showNavigationBar", "bool", "android"));
হামজেহ সোবহ

26

প্রকৃতপক্ষে ট্যাবলেটগুলিতে নেভিগেশন বারের (কমপক্ষে নেক্সাস 7) প্রতিকৃতি এবং ল্যান্ডস্কেপতে আলাদা আকার রয়েছে তাই এই ফাংশনটি দেখতে এইরকম হওয়া উচিত:

private int getNavigationBarHeight(Context context, int orientation) {
    Resources resources = context.getResources();

    int id = resources.getIdentifier(
            orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape",
            "dimen", "android");
    if (id > 0) {
        return resources.getDimensionPixelSize(id);
    }
    return 0;
}

6
প্রসঙ্গ থেকে অভিযোজন উদ্ধার করতে,context.getResources().getConfiguration().orientation
হুগো Gresse

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

17

আমি মনে করি আরও ভাল উত্তর এখানে কারণ এটি আপনাকে এমনকি কাটআউট উচ্চতাও পেতে দেয়।

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

আমার ক্যামেরার ক্রিয়াকলাপে, আমি আমার নীচের বিন্যাসে সিস্টেম উইন্ডো ইনসেটবটমের সমান প্যাডিং যুক্ত করি। এবং অবশেষে, এটি কাটাআউট ইস্যু ঠিক করে।

ক্যামেরা কার্যকলাপের পোকামাকড়

অ্যাপকম্প্যাট সহ এটি এটির মতো

ViewCompat.setOnApplyWindowInsetsListener(mCameraSourcePreview, (v, insets) -> {
    takePictureLayout.setPadding(0,0,0,insets.getSystemWindowInsetBottom());
    return insets.consumeSystemWindowInsets();
});

অ্যাপকম্প্যাট ছাড়াই, এটি:

mCameraSourcePreview.setOnApplyWindowInsetsListener((v, insets) -> { ... })

setOnApplyWindowInsetsListenerপরিবর্তে এটি ব্যবহার করা সম্ভব ? যদি তাই হয়, কিভাবে? এবং কেন আপনি ললিপপ এবং বাকিগুলির মধ্যে পার্থক্য করলেন?
অ্যান্ড্রয়েড বিকাশকারী

হ্যাঁ, এটি সম্ভব, এবং আরও ভাল। আমি উত্তর ঠিক করব। এবং আলাদা করার খুব প্রয়োজন নেই
জন

1
এটি সেরা উত্তর। আমি আপনাকে আক্ষরিক ভালবাসি।
হিমাংশু রাওয়াত

1
এটিই আসল উত্তর।
25:39

1
শ্রোতাদের কখনই মৃত্যুদন্ড কার্যকর করা হয় না যখন আমি এটি অনক্রিট () থেকে কল করি। আমি কিছু অনুপস্থিত করছি?
হোয়েটল

12

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

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

public int getNavigationBarHeight()
{
    boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
    int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
    if (resourceId > 0 && !hasMenuKey)
    {
        return getResources().getDimensionPixelSize(resourceId);
    }
    return 0;
}

5

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

পূর্ববর্তী কোনও সমাধান আমার পক্ষে কাজ করেনি। অ্যান্ড্রয়েড .0.০ হিসাবে আপনাকে মাল্টি উইন্ডো মোডটি বিবেচনায় নিতে হবে। এই বিরতি বাস্তবায়নের তুলনা display.realSize সঙ্গে display.size যেহেতু realSize আপনি পুরো পর্দার মাত্রা (উভয় বিভক্ত উইন্ডো) দেয় এবং আকার শুধুমাত্র জন্য আপনি নিজের অ্যাপ্লিকেশনটি উইন্ডোর মাত্রা দেয়। এই পার্থক্যে প্যাডিং সেট করা আপনার পুরো দর্শন প্যাডিংয়ের মতো ছেড়ে যাবে।

/** Adds padding to a view to dodge the navigation bar.

    Unfortunately something like this needs to be done since there
    are no attr or dimens value available to get the navigation bar
    height (as of December 2016). */
public static void addNavigationBarPadding(Activity context, View v) {
    Resources resources = context.getResources();
    if (hasNavigationBar(resources)) {
        int orientation = resources.getConfiguration().orientation;
        int size = getNavigationBarSize(resources);
        switch (orientation) {
        case Configuration.ORIENTATION_LANDSCAPE:
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
                context.isInMultiWindowMode()) { break; }
            v.setPadding(v.getPaddingLeft(), v.getPaddingTop(),
                         v.getPaddingRight() + size, v.getPaddingBottom());
            break;
        case Configuration.ORIENTATION_PORTRAIT:
            v.setPadding(v.getPaddingLeft(), v.getPaddingTop(),
                         v.getPaddingRight(), v.getPaddingBottom() + size);
            break;
        }
    }
}

private static int getNavigationBarSize(Resources resources) {
    int resourceId = resources.getIdentifier("navigation_bar_height",
                                             "dimen", "android");
    return resourceId > 0 ? resources.getDimensionPixelSize(resourceId) : 0;
}

private static boolean hasNavigationBar(Resources resources) {
    int hasNavBarId = resources.getIdentifier("config_showNavigationBar",
                                              "bool", "android");
    return hasNavBarId > 0 && resources.getBoolean(hasNavBarId);
}

1

নীচের নেভিগেশন বারের উচ্চতা 48 ডিপি (উভয় প্রতিকৃতি এবং ল্যান্ডস্কেপ মোডে) এবং যখন বারটি উল্লম্বভাবে স্থাপন করা হয় তখন 42 ডিপি হয়।


4
উচ্চতাটি সাধারণ 48dp। তবে কিছু নির্মাতারা এটি পরিবর্তন করতে পারে, কিছু কাস্টম রম এটিকে পরিবর্তন করতে পারে এবং আরও অনেক কিছু। এটা তোলে Danylo উত্তর (উপর নির্ভর ভালো stackoverflow.com/a/26118045/1377145 ) সঠিক আকার আছে
হুগো Gresse

ওটা আগের থেকে ভালো. ধন্যবাদ।
অরিত্র রায়

উল্লম্বভাবে স্থাপন? পছন্দ যখন এটি ল্যান্ডস্কেপ মোডে?
সুডোকোডার

1

Egidijus দ্বারা প্রস্তাবিত সমাধান এবং বিল্ডের জন্য নিখুঁতভাবে কাজ করে V VERSION.SDK_INT> = 17

কিন্তু আমার ডিভাইসে বিল্ড.ভেরিশন.এসডি কেএনপিটি <17 দিয়ে নিম্নলিখিত বিবৃতিটি কার্যকর করার সময় আমি "NoSuchMethodException" পেয়েছি:

Display.class.getMethod("getRawHeight").invoke(display);

এই জাতীয় ক্ষেত্রে আমি রিয়েলস্ক্রিনসাইজ () get পদ্ধতিটি পরিবর্তন করেছি:

else if(Build.VERSION.SDK_INT >= 14) 
{
    View decorView = getActivity().getWindow().getDecorView();
    size.x = decorView.getWidth();
    size.y = decorView.getHeight();
}

1

আমি এই সমস্যাটি সমস্ত ডিভাইসের জন্য (নেক্সাস 5, স্যামসং গ্যালাক্সি নেক্সাস 6 প্রান্ত +, স্যামসাং এস 10, স্যামসাং নোট II ইত্যাদি সহ) সমাধান করেছি। আমি মনে করি এটি আপনাকে ডিভাইস নির্ভর সমস্যাগুলি পরিচালনা করতে সহায়তা করবে।

এখানে আমি দুই ধরণের কোড যুক্ত করছি,

জাভা কোড (নেটিভ অ্যান্ড্রয়েডের জন্য):

import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.ViewConfiguration;
import android.view.WindowManager;

public class DeviceSpec {

    private int resourceID = -1;
    private Display display = null;
    private DisplayMetrics displayMetrics = null;
    private DisplayMetrics realDisplayMetrics = null;
    private Resources resources = null;
    private WindowManager windowManager = null;

    public double GetNavigationBarHeight(Context context) {
        try {
            windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            display = windowManager.getDefaultDisplay();
            displayMetrics = new DisplayMetrics();
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
                realDisplayMetrics = new DisplayMetrics();
                display.getMetrics(displayMetrics);
                display.getRealMetrics(realDisplayMetrics);
                if(displayMetrics.heightPixels != realDisplayMetrics.heightPixels) {
                    resources = context.getResources();
                    return GetNavigationBarSize(context);
                }
            }
            else {
                resources = context.getResources();
                resourceID = resources.getIdentifier("config_showNavigationBar", "bool", "android");
                if (resourceID > 0 && resources.getBoolean(resourceID))
                    return GetNavigationBarSize(context);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }

    private double GetNavigationBarSize(Context context) {
        resourceID = resources.getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceID > 0 && ViewConfiguration.get(context).hasPermanentMenuKey())
           return (resources.getDimensionPixelSize(resourceID) / displayMetrics.density);
        return 0;
    }
}

এবং সি # কোড (জ্যামারিন ফর্ম / অ্যান্ড্রয়েডের জন্য)

int resourceId = -1;
        IWindowManager windowManager = null;
        Display defaultDisplay = null;
        DisplayMetrics displayMatrics = null;
        DisplayMetrics realMatrics = null;
        Resources resources = null;

        public double NavigationBarHeight
        {
            get
            {
                try
                {
                    windowManager = Forms.Context.GetSystemService(Context.WindowService).JavaCast<IWindowManager>();
                    defaultDisplay = windowManager.DefaultDisplay;
                    displayMatrics = new DisplayMetrics();
                    if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBeanMr2)
                    {
                        realMatrics = new DisplayMetrics();
                        defaultDisplay.GetMetrics(displayMatrics);
                        defaultDisplay.GetRealMetrics(realMatrics);
                        if (displayMatrics.HeightPixels != realMatrics.HeightPixels)
                        {
                            resources = Forms.Context.Resources;
                            return GetHeightOfNivigationBar();
                        }
                    }
                    else {
                        resources = Forms.Context.Resources;
                        resourceId = resources.GetIdentifier("config_showNavigationBar", "bool", "android");
                        if (resourceId > 0 && resources.GetBoolean(resourceId))
                            return GetHeightOfNivigationBar();
                    }
                }
                catch (Exception e) { }
                return 0;
            }
        }

        private double GetHeightOfNivigationBar()
        {
            resourceId = resources.GetIdentifier("navigation_bar_height", "dimen", "android");
            if (!ViewConfiguration.Get(Forms.Context).HasPermanentMenuKey && resourceId > 0)
            {
                return resources.GetDimensionPixelSize(resourceId) / displayMatrics.Density;
            }
            return 0;
        }

Display.getRealMetrics()এপিআই স্তরের 17
Weizhi

যদি (বিল্ড.ভি.এস.আর.এসইডকিন্ট> = বিল্ড ভার্সনকোডস.জেলিবিয়ান এমআর 2) ইতিমধ্যে চেক করা আছে।
সিনো রাজ

কোডটি ঠিক করা দরকার। আমার এলজি নেক্সাস 5 এক্স কারণে 0.0 পাবেন: [1] যখন screenOrientationডিফল্ট, hasPermanentMenuKeyহয় falseশুধুমাত্র ঘোরান না পারেন। [2] screenOrientationল্যান্ডস্কেপ যখন হয় তখন তা displayMetrics.heightPixels != realDisplayMetrics.heightPixels)অন্য কোনও ক্ষেত্রে পড়ে । [3] যখন screenOrientationপ্রতিকৃতি হয়, hasPermanentMenuKeyহয় false
ফলমূল

এটি কাজ করে, তবে 4.x এ (যদি পারমানেন্ট মেনুকি) নষ্ট হয় তবে মন্তব্য করুন
ডিজেড্যান্স

আপনার অবস্থাটি যদি হওয়া উচিত (বিল্ড.VERSION.SDK_INT> = বিল্ড T VERSION_CODES.JELLY_BEAN_MR1)। সার্বজনীন শূন্য রাইলমেট্রিক্স (ডিসপ্লেমেট্রিক্স আউটমেট্রিক্স) করার জন্য এপিআই 17 প্রয়োজন। দস্তাবেজগুলি দেখুন: বিকাশকারী
পোর্টফোলিওবিল্ডার

1

@ ইগিস এবং অন্যদের থেকে উত্তরটির সংমিশ্রণ - এটি পিক্সেল ইএমইউ, স্যামসাং এস 6, সনি জেড 3, নেক্সাস 4 এ পরীক্ষা করা বিভিন্ন ডিভাইসগুলিতে ভাল কাজ করে nav সিস্টেম এনএভি বার বার উপস্থিত থাকলে।

/**
 * Calculates the system navigation bar size.
 */

public final class NavigationBarSize {

	private final int systemNavBarHeight;
	@NonNull
	private final Point navBarSize;

	public NavigationBarSize(@NonNull Context context) {
		Resources resources = context.getResources();
		int displayOrientation = resources.getConfiguration().orientation;
		final String name;
		switch (displayOrientation) {
			case Configuration.ORIENTATION_PORTRAIT:
				name = "navigation_bar_height";
				break;
			default:
				name = "navigation_bar_height_landscape";
		}
		int id = resources.getIdentifier(name, "dimen", "android");
		systemNavBarHeight = id > 0 ? resources.getDimensionPixelSize(id) : 0;
		navBarSize = getNavigationBarSize(context);
	}

	public void adjustBottomPadding(@NonNull View view, @DimenRes int defaultHeight) {
		int height = 0;
		if (navBarSize.y > 0) {
			// the device has a nav bar, get the correct size from the system
			height = systemNavBarHeight;
		}
		if (height == 0) {
			// fallback to default
			height = view.getContext().getResources().getDimensionPixelSize(defaultHeight);
		}
		view.setPadding(0, 0, 0, height);
	}

	@NonNull
	private static Point getNavigationBarSize(@NonNull Context context) {
		Point appUsableSize = new Point();
		Point realScreenSize = new Point();
		WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		if (windowManager != null) {
			Display display = windowManager.getDefaultDisplay();
			display.getSize(appUsableSize);
			display.getRealSize(realScreenSize);
		}
		return new Point(realScreenSize.x - appUsableSize.x, realScreenSize.y - appUsableSize.y);
	}

}


আমি যদি প্রোগ্রামটিমে স্ক্রিনের ব্যবহারযোগ্য উচ্চতার নীচে কোনও পাঠ্য ভিউয়ের উচ্চতা সেট করতে চাই, তবে আমি এই শ্রেণিটি কীভাবে ব্যবহার করব?
নাভেদ আব্বাস

1

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

এটি স্ট্যাটাস বারের উচ্চতা পেতে কোড

private fun getStatusBarHeight(resources: Resources): Int {
        var result = 0
        val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
        if (resourceId > 0) {
            result = resources.getDimensionPixelSize(resourceId)
        }
        return result
    }

ন্যাভিগেশন বারটি লুকানো থাকলেও এই পদ্ধতিটি সর্বদা নেভিগেশন বারের উচ্চতা প্রদান করে।

private fun getNavigationBarHeight(resources: Resources): Int {
    val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
    return if (resourceId > 0) {
        resources.getDimensionPixelSize(resourceId)
    } else 0
}

দ্রষ্টব্য: স্যামসাং এ 70 এ, এই পদ্ধতিটি নেভিগেশন বারের স্থিতি বারের উচ্চতা + উচ্চতা প্রদান করে। অন্যান্য ডিভাইসে (হুয়াওয়ে) নেভিগেশন বারটি কেবলমাত্র উচ্চতা ফিরিয়ে দেয় এবং নেভিগেশন বারটি লুকিয়ে থাকলে 0 প্রদান করে।

private fun getNavigationBarHeight(): Int {
        val display = activity?.windowManager?.defaultDisplay
        return if (display == null) {
            0
        } else {
            val realMetrics = DisplayMetrics()
            display.getRealMetrics(realMetrics)
            val metrics = DisplayMetrics()
            display.getMetrics(metrics)
            realMetrics.heightPixels - metrics.heightPixels
        }
    }

নেভিগেশন বার এবং স্ট্যাটাস বারের উচ্চতা পেতে কোড এটি

val metrics = DisplayMetrics()
        activity?.windowManager?.defaultDisplay?.getRealMetrics(metrics)

        //resources is got from activity

        //NOTE: on SamSung A70, this height = height of status bar + height of Navigation bar
        //On other devices (Huawei), this height = height of Navigation bar
        val navigationBarHeightOrNavigationBarPlusStatusBarHeight = getNavigationBarHeight()

        val statusBarHeight = getStatusBarHeight(resources)
        //The method will always return the height of navigation bar even when the navigation bar was hidden.
        val realNavigationBarHeight = getNavigationBarHeight(resources)

        val realHeightOfStatusBarAndNavigationBar =
                if (navigationBarHeightOrNavigationBarPlusStatusBarHeight == 0 || navigationBarHeightOrNavigationBarPlusStatusBarHeight < statusBarHeight) {
                    //Huawei: navigation bar is hidden
                    statusBarHeight
                } else if (navigationBarHeightOrNavigationBarPlusStatusBarHeight == realNavigationBarHeight) {
                    //Huawei: navigation bar is visible
                    statusBarHeight + realNavigationBarHeight
                } else if (navigationBarHeightOrNavigationBarPlusStatusBarHeight < realNavigationBarHeight) {
                    //SamSung A70: navigation bar is still visible but it only displays as a under line
                    //navigationBarHeightOrNavigationBarPlusStatusBarHeight = navigationBarHeight'(under line) + statusBarHeight
                    navigationBarHeightOrNavigationBarPlusStatusBarHeight
                } else {
                    //SamSung A70: navigation bar is visible
                    //navigationBarHeightOrNavigationBarPlusStatusBarHeight == statusBarHeight + realNavigationBarHeight
                    navigationBarHeightOrNavigationBarPlusStatusBarHeight
                }

1

আমি এটি করেছি, এটি আমার পরীক্ষিত প্রতিটি ডিভাইসে এবং এমনকি অনুকরণকারীগুলিতেও কাজ করে:

// Return the NavigationBar height in pixels if it is present, otherwise return 0
public static int getNavigationBarHeight(Activity activity) {
    Rect rectangle = new Rect();
    DisplayMetrics displayMetrics = new DisplayMetrics();
    activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rectangle);
    activity.getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics);
    return displayMetrics.heightPixels - (rectangle.top + rectangle.height());
}

0

আমি এখানে এটি সমাধান করেছি। আমি একটি আড়ালযোগ্য নীচের বারটি তৈরি করেছি যা নেভিগেশন বার ছিল কিনা তার উপর নির্ভর করে প্যাডিংয়ের প্রয়োজন ছিল (ক্যাপাসিটিভ, অন-স্ক্রিনে বা কেবল প্রাক ললিপপ)।


দৃশ্য

setPadding(0, 0, 0, Utils.hasNavBar(getContext()) ? 30 : 0);

Utils.java

public static boolean hasNavBar(Context context) {
    // Kitkat and less shows container above nav bar
    if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
        return false;
    }
    // Emulator
    if (Build.FINGERPRINT.startsWith("generic")) {
        return true;
    }
    boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
    boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
    boolean hasNoCapacitiveKeys = !hasMenuKey && !hasBackKey;
    Resources resources = context.getResources();
    int id = resources.getIdentifier("config_showNavigationBar", "bool", "android");
    boolean hasOnScreenNavBar = id > 0 && resources.getBoolean(id);
    return hasOnScreenNavBar || hasNoCapacitiveKeys || getNavigationBarHeight(context, true) > 0;
}

public static int getNavigationBarHeight(Context context, boolean skipRequirement) {
    int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
    if (resourceId > 0 && (skipRequirement || hasNavBar(context))) {
        return context.getResources().getDimensionPixelSize(resourceId);
    }
    return 0;
}

0

আমার ক্ষেত্রে যেখানে আমি এই জাতীয় কিছু পেতে চাই:

স্ক্রিনশট

আমাকে @ এমডিলসি দ্বারা প্রস্তাবিত একই জিনিসটি অনুসরণ করতে হয়েছিল তবে সম্ভবত কিছুটা সহজ ( কেবলমাত্র টার্গেট করে > = 21):

    //kotlin
    val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
    val realSize = Point()
    windowManager.defaultDisplay.getRealSize(realSize);
    val usableRect = Rect()
    windowManager.defaultDisplay.getRectSize(usableRect)
    Toast.makeText(this, "Usable Screen: " + usableRect + " real:"+realSize, Toast.LENGTH_LONG).show()

    window.decorView.setPadding(usableRect.left, usableRect.top, realSize.x - usableRect.right, realSize.y - usableRect.bottom)

এটি ল্যান্ডস্কেপেও কাজ করে:

ভূদৃশ্য

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

সজ্জা ভিউ প্যাডিংয়ের কোনও পরিবর্তন ছাড়াই একাধিক উইন্ডো সজ্জা ভিউ প্যাডিংয়ে কোনও পরিবর্তন ছাড়াই একক উইন্ডো

এগুলিতে নেভিগেশন বার কীভাবে অ্যাপের নীচে দৃশ্যমান হয় তার মধ্যে পার্থক্যটি নোট করুন। ভাগ্যক্রমে, এটি ঠিক করা সহজ। অ্যাপটি মাল্টি উইন্ডো কিনা তা আমরা পরীক্ষা করতে পারি। নীচের কোডটিতেও সরঞ্জামদণ্ডের অবস্থান গণনা এবং সমন্বয় করার অংশটি অন্তর্ভুক্ত রয়েছে (সম্পূর্ণ সমাধান: https://stackoverflow.com/a/14213035/477790 )

    // kotlin
    // Let the window flow into where window decorations are
    window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
    window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

    // calculate where the bottom of the page should end up, considering the navigation bar (back buttons, ...)
    val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
    val realSize = Point()
    windowManager.defaultDisplay.getRealSize(realSize);
    val usableRect = Rect()
    windowManager.defaultDisplay.getRectSize(usableRect)
    Toast.makeText(this, "Usable Screen: " + usableRect + " real:" + realSize, Toast.LENGTH_LONG).show()

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N || !isInMultiWindowMode) {
        window.decorView.setPadding(usableRect.left, usableRect.top, realSize.x - usableRect.right, realSize.y - usableRect.bottom)
        // move toolbar/appbar further down to where it should be and not to overlap with status bar
        val layoutParams = ConstraintLayout.LayoutParams(appBarLayout.layoutParams as ConstraintLayout.LayoutParams)
        layoutParams.topMargin = getSystemSize(Constants.statusBarHeightKey)
        appBarLayout.layoutParams = layoutParams
    }

স্যামসাং পপআপ মোডে ফলাফল:

এখানে চিত্র বর্ণনা লিখুন


0

নেভিগেশন বারের উচ্চতা পাওয়ার জন্য পরীক্ষিত কোড (পিক্সেলগুলিতে):

public static int getNavBarHeight(Context c) {
    int resourceId = c.getResources()
                      .getIdentifier("navigation_bar_height", "dimen", "android");
    if (resourceId > 0) {
        return c.getResources().getDimensionPixelSize(resourceId);
    }
    return 0;
}

স্থিতি দণ্ডের উচ্চতা পাওয়ার জন্য পরীক্ষিত কোড (পিক্সেলগুলিতে):

public static int getStatusBarHeight(Context c) {
    int resourceId = c.getResources()
                      .getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        return c.getResources().getDimensionPixelSize(resourceId);
    }
    return 0;
}

পিক্সেলকে ডিপিতে রূপান্তর করা হচ্ছে:

public static int pxToDp(int px) {
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}

0

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

এখানে KeyboardHeightProvider.java:

import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager.LayoutParams;
import android.widget.PopupWindow;


/**
 * The keyboard height provider, this class uses a PopupWindow
 * to calculate the window height when the floating keyboard is opened and closed. 
 */
public class KeyboardHeightProvider extends PopupWindow {

    /** The tag for logging purposes */
    private final static String TAG = "sample_KeyboardHeightProvider";

    /** The keyboard height observer */
    private KeyboardHeightObserver observer;

    /** The cached landscape height of the keyboard */
    private int keyboardLandscapeHeight;

    /** The cached portrait height of the keyboard */
    private int keyboardPortraitHeight;

    /** The view that is used to calculate the keyboard height */
    private View popupView;

    /** The parent view */
    private View parentView;

    /** The root activity that uses this KeyboardHeightProvider */
    private Activity activity;

    /** 
     * Construct a new KeyboardHeightProvider
     * 
     * @param activity The parent activity
     */
    public KeyboardHeightProvider(Activity activity) {
        super(activity);
        this.activity = activity;

        LayoutInflater inflator = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        this.popupView = inflator.inflate(R.layout.popupwindow, null, false);
        setContentView(popupView);

        setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_RESIZE | LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);

        parentView = activity.findViewById(android.R.id.content);

        setWidth(0);
        setHeight(LayoutParams.MATCH_PARENT);

        popupView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

                @Override
                public void onGlobalLayout() {
                    if (popupView != null) {
                        handleOnGlobalLayout();
                    }
                }
            });
    }

    /**
     * Start the KeyboardHeightProvider, this must be called after the onResume of the Activity.
     * PopupWindows are not allowed to be registered before the onResume has finished
     * of the Activity.
     */
    public void start() {

        if (!isShowing() && parentView.getWindowToken() != null) {
            setBackgroundDrawable(new ColorDrawable(0));
            showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0);
        }
    }

    /**
     * Close the keyboard height provider, 
     * this provider will not be used anymore.
     */
    public void close() {
        this.observer = null;
        dismiss();
    }

    /** 
     * Set the keyboard height observer to this provider. The 
     * observer will be notified when the keyboard height has changed. 
     * For example when the keyboard is opened or closed.
     * 
     * @param observer The observer to be added to this provider.
     */
    public void setKeyboardHeightObserver(KeyboardHeightObserver observer) {
        this.observer = observer;
    }

    /**
     * Get the screen orientation
     *
     * @return the screen orientation
     */
    private int getScreenOrientation() {
        return activity.getResources().getConfiguration().orientation;
    }

    /**
     * Popup window itself is as big as the window of the Activity. 
     * The keyboard can then be calculated by extracting the popup view bottom 
     * from the activity window height. 
     */
    private void handleOnGlobalLayout() {

        Point screenSize = new Point();
        activity.getWindowManager().getDefaultDisplay().getSize(screenSize);

        Rect rect = new Rect();
        popupView.getWindowVisibleDisplayFrame(rect);

        // REMIND, you may like to change this using the fullscreen size of the phone
        // and also using the status bar and navigation bar heights of the phone to calculate
        // the keyboard height. But this worked fine on a Nexus.
        int orientation = getScreenOrientation();
        int keyboardHeight = screenSize.y - rect.bottom;

        if (keyboardHeight == 0) {
            notifyKeyboardHeightChanged(0, orientation);
        }
        else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            this.keyboardPortraitHeight = keyboardHeight; 
            notifyKeyboardHeightChanged(keyboardPortraitHeight, orientation);
        } 
        else {
            this.keyboardLandscapeHeight = keyboardHeight; 
            notifyKeyboardHeightChanged(keyboardLandscapeHeight, orientation);
        }
    }

    /**
     *
     */
    private void notifyKeyboardHeightChanged(int height, int orientation) {
        if (observer != null) {
            observer.onKeyboardHeightChanged(height, orientation);
        }
    }

    public interface KeyboardHeightObserver {
        void onKeyboardHeightChanged(int height, int orientation);
    }
}

popupwindow.xml :

<?xml version="1.0" encoding="utf-8"?>
<View
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/popuplayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent"
    android:orientation="horizontal"/>

ব্যবহার MainActivity

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

/**
 * Created by nileshdeokar on 22/02/2018.
 */
class MainActivity : AppCompatActivity() , KeyboardHeightProvider.KeyboardHeightObserver  {

    private lateinit var keyboardHeightProvider : KeyboardHeightProvider


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        keyboardHeightProvider = KeyboardHeightProvider(this)
        parentActivityView.post { keyboardHeightProvider?.start() }
    }

    override fun onKeyboardHeightChanged(height: Int, orientation: Int) {
        // In case of 18:9 - e.g. Samsung S8
        // here you get the height of the navigation bar as negative value when keyboard is closed.
        // and some positive integer when keyboard is opened.
    }

    public override fun onPause() {
        super.onPause()
        keyboardHeightProvider?.setKeyboardHeightObserver(null)
    }

    public override fun onResume() {
        super.onResume()
        keyboardHeightProvider?.setKeyboardHeightObserver(this)
    }

    public override fun onDestroy() {
        super.onDestroy()
        keyboardHeightProvider?.close()
    }
}

আরও কোনও সহায়তার জন্য আপনি এখানে এর উন্নত ব্যবহারের দিকে নজর রাখতে পারেন ।


0

সাধারণ এক-লাইন সমাধান

যেমন উপরোক্ত উত্তরের অনেকটিতে পরামর্শ দেওয়া হয়েছে, উদাহরণস্বরূপ

কেবল নেভিগেশন বারের উচ্চতা পাওয়া যথেষ্ট নাও হতে পারে। আমাদের 1. নেভিগেশন বারের উপস্থিতি আছে কিনা তা বিবেচনা করা উচিত, ২. এটি নীচে বা ডান বা বামে, ৩. মাল্টি-উইন্ডো মোডে অ্যাপ্লিকেশনটি খোলা আছে।

ভাগ্যক্রমে আপনি সহজেই android:fitsSystemWindows="true"আপনার মূল বিন্যাসে সেট করে সমস্ত দীর্ঘ কোডিংকে সহজেই বাইপাস করতে পারেন । অ্যান্ড্রয়েড সিস্টেমটি স্বয়ংক্রিয়ভাবে রুট বিন্যাসে প্রয়োজনীয় প্যাডিং যুক্ত করার যত্ন নেবে যাতে শিশু দৃষ্টিভঙ্গিগুলি নেভিগেশন বারে বা স্ট্যাটাসবার অঞ্চলে না যায় make

একটি সহজ একটি লাইন সমাধান আছে

android:fitsSystemWindows="true"

বা প্রোগ্রামক্রমে

findViewById(R.id.your_root_view).setFitsSystemWindows(true);

আপনি এর মাধ্যমেও রুট ভিউ পেতে পারেন

findViewById(android.R.id.content).getRootView();
or
getWindow().getDecorView().findViewById(android.R.id.content)

রুট-ভিউ পাওয়ার বিষয়ে আরও তথ্যের জন্য দেখুন - https://stackoverflow.com/a/4488149/9640177

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