以编程方式构建导航抽屉

Posted

技术标签:

【中文标题】以编程方式构建导航抽屉【英文标题】:Programmatically build Navigation Drawer 【发布时间】:2016-06-16 17:34:56 【问题描述】:

我有一个 DrawerLayout,它使用 2 个布局。

    为主要内容。 (相对布局) 抽屉窗格。 (线性布局)

我需要动态创建所有内容,因此不必使用 XML。

这是创建drawerPane的代码:

public class Test2 extends AppCompatActivity

    ListView myList;
    DrawerLayout drawerLayout;

    LinearLayout drawerPane;
    RelativeLayout content;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        myList=new ListView(this);

        drawerLayout=new DrawerLayout(this);

        DrawerLayout.LayoutParams drawerLayout_params=new DrawerLayout.LayoutParams(280, DrawerLayout.LayoutParams.MATCH_PARENT);

        drawerLayout.setId(0);

        drawerPane=new LinearLayout(this);
        drawerPane.setGravity(Gravity.START);
        drawerPane.setClickable(true);

        myList=new ListView(this);

        myList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

        LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(280,LinearLayout.LayoutParams.MATCH_PARENT);
        lp.gravity=Gravity.START;

        drawerPane.setLayoutParams(lp);

        drawerPane.addView(myList,new ListView.LayoutParams(280,ListView.LayoutParams.MATCH_PARENT));

        drawerPane.setGravity(Gravity.START);
        drawerPane.setOrientation(LinearLayout.VERTICAL);

        setContentView(drawerLayout,drawerLayout_params);

        content=new RelativeLayout(this);

        drawerLayout.addView(content,new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        drawerLayout.addView(drawerPane,lp);

        LinkedList<String> list=new LinkedList<>();

        list.add("Item #1");
        list.add("Item #2");
        list.add("Item #3");

        myList.setAdapter(new My_Adapter<String>(this,R.layout.drawer_item,list) 
            @Override
            protected void set(String item, View customView) 

                TextView title=(TextView)customView.findViewById(R.id.title);
                TextView subTitle=(TextView)customView.findViewById(R.id.subTitle);

                title.setText(item);
                subTitle.setText(item);
            
        );
    

我为我的 ListView 的适配器使用了一个 My_Adapter 自定义类:

public abstract class My_Adapter<T> extends BaseAdapter 

    private int customLayoutID;

    private Context myContext;

    private Collection<T> listValues;
    private T[] arrayValues;

    private final boolean listMode;
    private final boolean arrayMode;

    public My_Adapter(Context context,int layoutID, T[] values) 

        arrayMode=true;
        listMode=false;

        myContext=context;
        arrayValues=values;
        customLayoutID=layoutID;
    

    public My_Adapter(Context context,int layoutID, Collection<T> values) 

        listMode=true;
        arrayMode=false;

        myContext=context;
        listValues=values;
        customLayoutID=layoutID;
    

    @Override
    public int getCount() 

        if (listMode)

            return listValues.size();
        
        else if (arrayMode)

            return arrayValues.length;
        
        else return -1;
    

    @Override
    public T getItem(int position) 

        if (listMode)

            return ((List<T>) listValues).get(position);
        
        else if (arrayMode)

            return arrayValues[position];
        
        else return null;
    

    @Override
    public long getItemId(int position) 

        return position;
    


    @Override
    public View getView(int position, View convertView, ViewGroup parent) 

        LayoutInflater inflater= LayoutInflater.from(myContext);

        View myView= inflater.inflate(customLayoutID,parent,false);

        T item=getItem(position);

        set(item,myView);

        return myView;
    

    protected abstract void set(T item, View customView);

使用此代码,应用程序如下所示:

这是drawer_item.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:paddingTop="10dp"
    android:paddingBottom="10dp">

    <TextView
        android:id="@+id/title"
        android:layout_
        android:layout_
        android:textSize="18sp"
        android:gravity="center_vertical"
        android:textColor="@color/abc_primary_text_material_dark"
        android:text="Line 1"
        android:textStyle="bold" />

    <TextView android:id="@+id/subTitle"
        android:layout_
        android:layout_
        android:text="Line 2"
        android:textColor="#717171"
        android:layout_below="@+id/title"
        android:layout_alignRight="@+id/title"
        android:layout_alignEnd="@+id/title" />

</RelativeLayout>

编辑/更新

我想获得与以下 xml 代码相同的结果。 查看 LinearLayout 的“LAYOUT_GRAVITY”。

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawerLayout"
    android:layout_
    android:layout_>

    <!-- The main content view -->
    <RelativeLayout
        android:id="@+id/mainContent"
        android:layout_
        android:layout_ >

    </RelativeLayout>

    <!-- The navigation drawer -->
    <LinearLayout
        android:layout_
        android:layout_
        android:id="@+id/drawerPane"
        android:layout_gravity="start"
        android:clickable="true"
        android:orientation="vertical">

        <!-- Profile Box -->

        <RelativeLayout
            android:id="@+id/profileBox"
            android:layout_
            android:layout_
            android:background="@color/material_blue_grey_900"
            android:padding="8dp" >

            <LinearLayout
                android:layout_
                android:layout_
                android:layout_centerVertical="true"
                android:layout_marginLeft="15dp"
                android:orientation="vertical" >

                <TextView
                    android:id="@+id/userName"
                    android:layout_
                    android:layout_
                    android:text="ElektroFR"
                    android:textColor="#fff"
                    android:textSize="16sp"
                    android:textStyle="bold" />

                <TextView
                    android:id="@+id/desc"
                    android:layout_
                    android:layout_
                    android:layout_below="@+id/userName"
                    android:layout_marginTop="4dp"
                    android:text="View Profile"
                    android:textColor="#fff"
                    android:textSize="12sp" />
            </LinearLayout>
        </RelativeLayout>

        <!-- List of Actions (pages) -->
        <ListView
            android:id="@+id/navList"
            android:layout_
            android:layout_
            android:layout_below="@+id/profileBox"
            android:choiceMode="singleChoice"
            android:background="@color/bright_foreground_disabled_material_light" />

    </LinearLayout>

</android.support.v4.widget.DrawerLayout>

【问题讨论】:

没有XML,但是你有一个drawer_item.xml? :) @cricket_007 这必须是我项目中唯一的“静态”元素:) 我明白了。关于您的问题,我不认为布局重力与RelativeLayout 配合得很好。由于您似乎不需要任何相对的东西,我建议为 drawerPane @cricket_007 是的,但我不能接受在 xml 上写这个可以让事情正常工作。这真的很烦人。为什么不存在设置layout_gravity的方法? 那么您需要一种方法来为 RelativeLayout 中的视图设置布局重力吗?这不是 RelativeLayout 的工作方式。你的最终目标是什么? 【参考方案1】:

不要在将视图添加到父组之前设置视图的布局参数,而是使用除了视图之外还接受 LayoutParam 参数的 addView 版本。

另外,FWIW,不建议使用 item id 的位置值。

【讨论】:

感谢您的回答,但我按照您所说的修改了代码,没有任何改变。请注意,如果我使用 xml,并使用“gravity”而不是“layout_gravity”,结果看起来是一样的【参考方案2】:

解决方案 感谢这个问题的答案!:

SOLUTION

您必须为抽屉将使用的每个视图使用 DrawerLayout.LayoutParams!

    抽屉面板 列表视图

这是最终代码:

package elektro_fr.newapplication;

public class Test2 extends AppCompatActivity

    ListView myList;
    DrawerLayout drawerLayout;

    LinearLayout drawerPane;
    RelativeLayout content;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        myList=new ListView(this);

        drawerLayout=new DrawerLayout(this);

        DrawerLayout.LayoutParams drawerLayout_params=new DrawerLayout.LayoutParams(My_AndroidTools.DisplayTools.getPixelsDimension(getResources(),180), DrawerLayout.LayoutParams.MATCH_PARENT);
        drawerLayout_params.gravity=Gravity.START;

        drawerLayout.setId(0);

        drawerPane=new LinearLayout(this);
        drawerPane.setGravity(Gravity.START);
        drawerPane.setClickable(true);

        myList=new ListView(this);

        myList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

        drawerPane.setLayoutParams(drawerLayout_params);

        drawerPane.addView(myList,drawerLayout_params);

        drawerPane.setOrientation(LinearLayout.VERTICAL);

        setContentView(drawerLayout,drawerLayout_params);

        content=new RelativeLayout(this);

        drawerLayout.addView(content,new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        drawerLayout.addView(drawerPane,drawerLayout_params);

        LinkedList<String> list=new LinkedList<>();

        list.add("Item #1");
        list.add("Item #2");
        list.add("Item #3");

        myList.setAdapter(new My_Adapter<String>(this,R.layout.drawer_item,list) 
            @Override
            protected void set(String item, View customView) 

                TextView title=(TextView)customView.findViewById(R.id.title);
                TextView subTitle=(TextView)customView.findViewById(R.id.subTitle);

                title.setText(item);
                subTitle.setText(item);
            
        );
    

【讨论】:

【参考方案3】:
@Override
protected void onCreate(Bundle savedInstanceState)

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_device_list);

    //=========================Adding Toolbar in android layout======================================
    Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
    setSupportActionBar(myToolbar);

    //=========================Toolbar End============================================================


    /***************************************************************************************
     * Navigation Drawer Layout
     *
     ***************************************************************************************/
    // drawer layout instance to toggle the menu icon to open
    // drawer and back button to close drawer
    drawerLayout = findViewById(R.id.draw_layout);
    actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.nav_open, R.string.nav_close);

    // pass the Open and Close toggle for the drawer layout listener
    // to toggle the button
    drawerLayout.addDrawerListener(actionBarDrawerToggle);
    actionBarDrawerToggle.syncState();

    mNavigationView =  findViewById(R.id.nav_view);
    mNavigationView.setNavigationItemSelectedListener(this);

    // to make the Navigation drawer icon always appear on the action bar
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
   /***************************************************************************************
    * Navigation Drawer Layout
    *
    ***************************************************************************************/



使用此链接: https://timxn.com/en/programmatically-add-navigation-drawer-android

【讨论】:

以上是关于以编程方式构建导航抽屉的主要内容,如果未能解决你的问题,请参考以下文章

Android以编程方式更改导航抽屉菜单项文本

Android:导航抽屉标题文本视图未以编程方式设置

在 Android 中禁用导航抽屉中的项目

导航抽屉:如何在启动时设置所选项目?

在导航抽屉项目单击时,导航抽屉中的新列表视图

如何使用标题 Scroll 使 android 导航抽屉可滚动