Поўная шырыня панэлі навігацыі

Я хацеў бы стварыць поўную шырыню панэлі навігацыі. Настройка layout_width для match_parent на @ + ідэнтыфікатар/left_drawer дае ў шырыню каля 80% экраннага прасторы. Гэта, здаецца, стандартныя паводзіны. Ці павінен я перавызначыць onMeasure() з DrawerLayout ?

Мой бягучы код:

<?xml version="1.0" encoding="utf-8"?>


    
    

    

Дзякуючы.

28

15 адказы

Калі вы хочаце больш простае рашэнне, якое вы можаце проста ўсталяваць адмоўны запас

android:layout_marginLeft="-64dp"

для left_drawer:


109
дададзена
Гэта на sw600dp? напрыклад ? Я хачу, каб мець магчымасць усталяваць навігацыйны скрыню, поўны на маім экране планшэта. Да гэтага часу гэта здаецца палова, і я не магу бачыць, дзе змяніць і змяніць налады гэтага. @Robert
дададзена аўтар Madonah Syombua, крыніца
Вы выратавалі маё жыццё, браценік! Дзякуй
дададзена аўтар Adnan Bin Mustafa, крыніца
Я думаю, што гэта павінна было быць прынята адказваць. Я паглядзеў зыходны код. Ён не бярэ на сябе 80% адсоткаў прасторы. Гэта проста паставіць мінімум краю 64DP. Паклаўшы адмоўныя поля мудра.
дададзена аўтар tasomaniac, крыніца
Працаваў на 5,0 і вышэй.
дададзена аўтар JaydeepW, крыніца
проста без якога-небудзь кадавання, 65dp лепш
дададзена аўтар leegor, крыніца
Працуе выдатна. Я заўважыў, што там быў яшчэ адзін піксель шчылінай так 65dp працуе для мяне
дададзена аўтар Chris, крыніца
Гэта рашэнне не працуе з Android 5.0 і вышэй :(
дададзена аўтар nguoitotkhomaisao, крыніца

Yes, you have to extend DrawerLayout and override some methods because MIN_DRAWER_MARGIN is private

Вось адно з магчымых рашэнняў:

public class FullDrawerLayout extends DrawerLayout {

    private static final int MIN_DRAWER_MARGIN = 0;//dp

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

    public FullDrawerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FullDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
            throw new IllegalArgumentException(
                    "DrawerLayout must be measured with MeasureSpec.EXACTLY.");
        }

        setMeasuredDimension(widthSize, heightSize);

       //Gravity value for each drawer we've seen. Only one of each permitted.
        int foundDrawers = 0;
        final int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);

            if (child.getVisibility() == GONE) {
                continue;
            }

            final LayoutParams lp = (LayoutParams) child.getLayoutParams();

            if (isContentView(child)) {
               //Content views get measured at exactly the layout's size.
                final int contentWidthSpec = MeasureSpec.makeMeasureSpec(
                        widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY);
                final int contentHeightSpec = MeasureSpec.makeMeasureSpec(
                        heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY);
                child.measure(contentWidthSpec, contentHeightSpec);
            } else if (isDrawerView(child)) {
                final int childGravity =
                        getDrawerViewGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK;
                if ((foundDrawers & childGravity) != 0) {
                    throw new IllegalStateException("Child drawer has absolute gravity " +
                            gravityToString(childGravity) + " but this already has a " +
                            "drawer view along that edge");
                }
                final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec,
                        MIN_DRAWER_MARGIN + lp.leftMargin + lp.rightMargin,
                        lp.width);
                final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec,
                        lp.topMargin + lp.bottomMargin,
                        lp.height);
                child.measure(drawerWidthSpec, drawerHeightSpec);
            } else {
                throw new IllegalStateException("Child " + child + " at index " + i +
                        " does not have a valid layout_gravity - must be Gravity.LEFT, " +
                        "Gravity.RIGHT or Gravity.NO_GRAVITY");
            }
        }
    }

    boolean isContentView(View child) {
        return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY;
    }

    boolean isDrawerView(View child) {
        final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
        final int absGravity = Gravity.getAbsoluteGravity(gravity,
                child.getLayoutDirection());
        return (absGravity & (Gravity.LEFT | Gravity.RIGHT)) != 0;
    }

    int getDrawerViewGravity(View drawerView) {
        final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
        return Gravity.getAbsoluteGravity(gravity, drawerView.getLayoutDirection());
    }

    static String gravityToString(int gravity) {
        if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
            return "LEFT";
        }
        if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
            return "RIGHT";
        }
        return Integer.toHexString(gravity);
    }

}
27
дададзена
Замяніць getLayoutDirection з ViewCompat.getLayoutDirection, каб атрымаць больш сумяшчальнасці. У любым выпадку гэта не працуе для мяне на андроіда 7.0. Маржа не змянілася і ў цяперашні час ахоплівае ActionBar радка стану.
дададзена аўтар Makalele, крыніца
Дзякуй за адказ.
дададзена аўтар Jinal Patel, крыніца
Цяпер, калі я думаю пра гэта, прыбраўшы гэта поле MIN_DRAWER_MARGIN цалкам ужо дазваляе карыстальнікам змяняць гэта праз layout_margin * палі, ці не паказваць яго на ўсё, што будзе па змаўчанні 0dp.
дададзена аўтар yiati, крыніца
Для тых, хто з невялікім веданнем зыходнага кода DrawerLayout, гэты адказ можа здацца, што дэман магіі начараваў ў галаве майстра, і зрабіць вы хочаце адмовіцца ад праграмавання. Ладоў няма! Гэта проста зыходны код DrawerLayout з адзінымі метадамі неабходна выняты. Адзінае, што сапраўды мяняецца ў тым, што «MIN_DRAWER_MARGIN = 64;" было зменена на "MIN_DRAWER_MARGIN = 0;". Яшчэ адна ідэя распаўсюдзіць на гэта было б замест гэтага зрабіць MIN_DRAWER_MARGIN высоўная атрыбут XML.
дададзена аўтар yiati, крыніца
Атрыманне Fatal Exception: java.lang.IllegalArgumentException: злом або далучаныя прадстаўлення не могуць быць перапрацаваныя. isScrap хлусня isAttached: праўдзівы у onMeasure()
дададзена аўтар Nikhil, крыніца

Таму што ўсе гэтыя адказы не працуе на OS 6.0.1, я выкладу тут рашэнне, якое працавала для мяне ў камбінацыі з DrawerLayout + NavigationView .

Так што ўсё, што я раблю, гэта змяніць шырыню NavigationView праграмна:

mNavigationView = (NavigationView) findViewById(R.id.nv_navigation);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) mNavigationView.getLayoutParams();
params.width = metrics.widthPixels;
mNavigationView.setLayoutParams(params);

Гэта працуе для ўсіх памераў экрана.

19
дададзена
я не бачу, дзе палова экрана ствараецца па шырыні (я таксама паспрабаваў params.width = metrics.widthPixels/2), але не нічога не робіць, незалежна ад таго, што я змяніць шырыню
дададзена аўтар Lion789, крыніца
Гэта працуе !!
дададзена аўтар Makalele, крыніца
дзякуй ... працуе для мяне
дададзена аўтар Bhavesh Vadalia, крыніца

На аснове Роберта Адказ , вы можаце выкарыстоўваць layout_marginLeft = -64dp , каб вырашыць гэтую праблему лёгка ,

Аднак <�моцны> не падаецца больш працаваць на Android 5.0 і вышэй . Дык вось маё рашэнне, якое працуе для мяне.

<?xml version="1.0" encoding="utf-8"?>


    

    


У прынцыпе, дадаць Android: layout_marginRight = "- 64DP" у каранёвай каталог DrawerLayout так што ўсе раскладка будзе ісці направа для 64DP.

Затым я дадаю layout_marginRight = 64DP да зместу, так што вяртаецца да зыходнай пазіцыі. Тады вы можаце мець поўны скрыню там.

10
дададзена

Варыянт рашэння Grogory у:

Замест таго, каб падкласы я называю наступны метад карыснасці адразу пасля я захапіць спасылку на макет скрыні:

/**
 * The specs tell that
 * 
    *
  1. Navigation Drawer should be at most 5*56dp wide on phones and 5*64dp wide on tablets.
  2. *
  3. Navigation Drawer should have right margin of 56dp on phones and 64dp on tablets.
  4. *
 * yet the minimum margin is hardcoded to be 64dp instead of 56dp. This fixes it.
 */
public static void fixMinDrawerMargin(DrawerLayout drawerLayout) {
  try {
    Field f = DrawerLayout.class.getDeclaredField("mMinDrawerMargin");
    f.setAccessible(true);
    f.set(drawerLayout, 0);

    drawerLayout.requestLayout();
  } catch (Exception e) {
    e.printStackTrace();
  }
}
8
дададзена
Я не ўпэўнены, калі яго правільны шлях, але вельмі разумнае рашэнне
дададзена аўтар Rafay Ali, крыніца
mDrawerLayout = (DrawerLayout) view.findViewById(R.id.drawer_layout);
mDrawerList = (ListView) view.findViewById(R.id.top_sectionlist);

int width = getResources().getDisplayMetrics().widthPixels/2;
DrawerLayout.LayoutParams params = (android.support.v4.widget.DrawerLayout.LayoutParams) mDrawerList.getLayoutParams();
params.width = width;
mDrawerList.setLayoutParams(params);
5
дададзена
INT шырыня = GetResources() getDisplayMetrics() widthPixels ..; выдаленне/2 з яго зрабіў трук для мяне. Працаваў на лядзяш і Oreo.
дададзена аўтар March3April4, крыніца
Лепшы падыход, працуе ва ўсіх версіях Android OS
дададзена аўтар Ajit, крыніца

Іншы магчымы спосаб вырашыць гэтую праблему, не перакрываючы зашмат:

public class FullScreenDrawerLayout extends DrawerLayout {

... //List of constructors calling
... //super(...);
... //init();

/** Make DrawerLayout to take the whole screen. */
protected void init() {
    try {

        Field field = getClass().getSuperclass().getDeclaredField("mMinDrawerMargin");
        field.setAccessible(true);
        field.set(this, Integer.valueOf(0));

    } catch (Exception e) {
        throw new IllegalStateException("android.support.v4.widget.DrawerLayout has changed and you have to fix this class.", e);
    }
}

}

Калі ў нейкі момант, бібліятэка падтрымкі абнаўляецца і mMinDrawerMargin не там больш вы атрымаеце выключэнне і выправіць праблему, перш чым апублікаваць чарговае абнаўленне.

Я не рабіў вымярэнне, але выкажу здагадку, што існуе не так шмат адлюстравання, каб паўплываць на прадукцыйнасць. Акрамя таго, ён выконвае толькі на стварэнне прадстаўлення.

PS гэта дзіўна, чаму DrawerLayout зроблена так нягнуткая (я аб прыватным маржы мін) у гэтай кропцы ...

4
дададзена
Не працуе на андроіда 7.0.
дададзена аўтар Makalele, крыніца

FullDrawerLayout Класс кусачак з'яўляецца проста дзіўным .. гэта прадукцыйнасць таксама хутчэй, чым скрынка па змаўчанні як заўсёды вы можаце; т выкарыстоўваць яго на прыладах з API, якія не маюць view.getLayoutDirection (); (I'e: Класс Абыякава; т працаваць на ўсіх прыладах пернікавыя)

так што я зрабіў

замяніць усе

view.getLayoutDirection();

з кодам ніжэй

GravityCompat.getAbsoluteGravity(gravity,ViewCompat.getLayoutDirection(this));

Я мая бібліятэка падтрымкі абноўленая да апошняга таксама пашырыў fullDrawerlayout на падтрымку навігацыйнага скрыню. Цяпер ён працуе выдатна прылады Gingerbread, а таксама

4
дададзена

Паспрабуйце гэта працуе для мяне:


Ўстаноўка шырыні уключанага макета АНДРОІД: layout_width = "320dp" . Для прылад з розным памерам экрана вы можаце дынамічна ўсталёўваць шырыню гэтага уключаны макета.

3
дададзена

Вы можаце выкарыстоўваць гэта. Натхнёны гэтым паведамленні , я мадэрнізаваны для 5-га выдання. Таму што былі праблемы з StatusBar ў версіі 5 і больш позніх версій.

Вы павінны пашырыць DrawerLayout і перавызначыць некаторыя метады, таму што MIN_DRAWER_MARGIN прыватная

public class FullDrawerLayout extends DrawerLayout {

    private static final int MIN_DRAWER_MARGIN = 0;//dp

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

    public FullDrawerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FullDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
            throw new IllegalArgumentException(
                    "DrawerLayout must be measured with MeasureSpec.EXACTLY.");
        }

        setMeasuredDimension(widthSize, heightSize);

        //for support Android 5+
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
            FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
            params.topMargin = getStatusBarHeight();
            setLayoutParams(params);
        }

       //Gravity value for each drawer we've seen. Only one of each permitted.
        int foundDrawers = 0;
        final int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);

            if (child.getVisibility() == GONE) {
                continue;
            }

            final LayoutParams lp = (LayoutParams) child.getLayoutParams();

            if (isContentView(child)) {
               //Content views get measured at exactly the layout's size.
                final int contentWidthSpec = MeasureSpec.makeMeasureSpec(
                        widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY);
                final int contentHeightSpec = MeasureSpec.makeMeasureSpec(
                        heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY);
                child.measure(contentWidthSpec, contentHeightSpec);
            } else if (isDrawerView(child)) {
                final int childGravity =
                        getDrawerViewGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK;
                if ((foundDrawers & childGravity) != 0) {
                    throw new IllegalStateException("Child drawer has absolute gravity " +
                            gravityToString(childGravity) + " but this already has a " +
                            "drawer view along that edge");
                }
                final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec,
                        MIN_DRAWER_MARGIN + lp.leftMargin + lp.rightMargin,
                        lp.width);
                final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec,
                        lp.topMargin + lp.bottomMargin,
                        lp.height);
                child.measure(drawerWidthSpec, drawerHeightSpec);
            } else {
                throw new IllegalStateException("Child " + child + " at index " + i +
                        " does not have a valid layout_gravity - must be Gravity.LEFT, " +
                        "Gravity.RIGHT or Gravity.NO_GRAVITY");
            }
        }
    }

    boolean isContentView(View child) {
        return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY;
    }

    boolean isDrawerView(View child) {
        final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
        final int absGravity = Gravity.getAbsoluteGravity(gravity,
                child.getLayoutDirection());
        return (absGravity & (Gravity.LEFT | Gravity.RIGHT)) != 0;
    }

    int getDrawerViewGravity(View drawerView) {
        final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
        return Gravity.getAbsoluteGravity(gravity, drawerView.getLayoutDirection());
    }

    static String gravityToString(int gravity) {
        if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
            return "LEFT";
        }
        if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
            return "RIGHT";
        }
        return Integer.toHexString(gravity);
    }


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

}
2
дададзена

вы можаце ніжэй код

 int width = getResources().getDisplayMetrics().widthPixels/2;
        DrawerLayout.LayoutParams params = (android.support.v4.widget.DrawerLayout.LayoutParams) drawer_Linear_layout.getLayoutParams();
        params.width = width;
        drawer_Linear_layout.setLayoutParams(params);
1
дададзена

Вы таксама можаце паглядзець на SlidingDrawer класа. Гэта састарэлы клас, але, як сказана ў дакументацыі, вы можаце напісаць сваю ўласную рэалізацыю на аснове зыходнага кода.

1
дададзена

Google рэкамендуе мець шырыню максімы 320 купання ў адпаведнасці з кіруючымі прынцыпамі інтэрфейсу тут , Акрамя таго, шырыня можа быць ўстаноўлена з дапамогай названага ў layout_width з left_drawer ListView.

1
дададзена
<?xml version="1.0" encoding="utf-8"?>


    

        
    


    

        

    


Гэта працуе выдатна для мяне. Спадзяюся дапамагчы іншым.

1
дададзена
<?xml version="1.0" encoding="utf-8"?>



    

        

        

        
    

    

        

        
    






    

    


0
дададзена