当前位置: 首页 > 知识库问答 >
问题:

无法使用句柄创建导航抽屉

艾意蕴
2023-03-14

我知道这个问题已经在这里和这里被问过了,但我仍然无法创建带有手柄的导航抽屉。

我使用了下面提到的类::

DrawerHandle::

@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
public class DrawerHandle implements DrawerLayout.DrawerListener {
    public static final String TAG = "DrawerHandle";

    private ViewGroup mRootView;
    private DrawerLayout mDrawerLayout;
    private View mHandle;
    private View mDrawer;

    private float mVerticalOffset;
    private int mGravity;
    private WindowManager mWM;
    private Display mDisplay;
    private Point mScreenDimensions = new Point();

    private OnClickListener mHandleClickListener = new OnClickListener(){

        @Override
        public void onClick(View v) {
            if(!mDrawerLayout.isDrawerOpen(mGravity)) mDrawerLayout.openDrawer(mGravity);
            else mDrawerLayout.closeDrawer(mGravity);
        }

    };

    private OnTouchListener mHandleTouchListener = new OnTouchListener() {
        private static final int MAX_CLICK_DURATION = 200;
        private long startClickTime;
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    startClickTime = System.currentTimeMillis();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    if(System.currentTimeMillis() - startClickTime < MAX_CLICK_DURATION) {
                        v.performClick();
                        return true;
                    }
                }
            }
            MotionEvent copy = MotionEvent.obtain(event);
            copy.setEdgeFlags(ViewDragHelper.EDGE_ALL);
            copy.setLocation(event.getRawX() + (mGravity == Gravity.LEFT || mGravity == GravityCompat.START ? -mHandle.getWidth()/2 : mHandle.getWidth() / 2), event.getRawY());
            mDrawerLayout.onTouchEvent(copy);
            copy.recycle();
            return true;
        }
    };

    private int getDrawerViewGravity(View drawerView) {
        final int gravity = ((DrawerLayout.LayoutParams) drawerView.getLayoutParams()).gravity;
        return GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(drawerView));
    }

    private float getTranslation(float slideOffset){
        return (mGravity == GravityCompat.START || mGravity == Gravity.LEFT) ? slideOffset*mDrawer.getWidth() : -slideOffset*mDrawer.getWidth();
    }

    @SuppressLint("NewApi")
    private void updateScreenDimensions() {

        if (Build.VERSION.SDK_INT >= 13) {
            mDisplay.getSize(mScreenDimensions);
        } else {
            mScreenDimensions.x = mDisplay.getWidth();
            mScreenDimensions.y = mDisplay.getHeight();
        }
    }

    private DrawerHandle(DrawerLayout drawerLayout, View drawer, int handleLayout, float handleVerticalOffset) {
        mDrawer = drawer;
        mGravity = getDrawerViewGravity(mDrawer);
        mDrawerLayout = drawerLayout;
        mRootView = (ViewGroup)mDrawerLayout.getRootView();
        LayoutInflater inflater = (LayoutInflater) mDrawerLayout.getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE );
        mHandle = inflater.inflate(handleLayout, mRootView, false);
        mWM = (WindowManager) mDrawerLayout.getContext().getSystemService(Context.WINDOW_SERVICE);
        mDisplay = mWM.getDefaultDisplay();

        mHandle.setOnClickListener(mHandleClickListener);   
        mHandle.setOnTouchListener(mHandleTouchListener);
        mRootView.addView(mHandle, new FrameLayout.LayoutParams(mHandle.getLayoutParams().width, mHandle.getLayoutParams().height, mGravity));
        setVerticalOffset(handleVerticalOffset);
        mDrawerLayout.setDrawerListener(this);
    }

    public static DrawerHandle attach(View drawer, int handleLayout, float verticalOffset) {
        if (!(drawer.getParent() instanceof DrawerLayout)) throw new IllegalArgumentException("Argument drawer must be direct child of a DrawerLayout");
        return new DrawerHandle((DrawerLayout)drawer.getParent(), drawer, handleLayout, verticalOffset);
    }

    public static DrawerHandle attach(View drawer, int handleLayout) {
        return attach(drawer, handleLayout, 0);
    }

    @Override
    public void onDrawerClosed(View arg0) {
    }

    @Override
    public void onDrawerOpened(View arg0) {

    }

    @Override
    public void onDrawerSlide(View arg0, float slideOffset) {
        float translationX = getTranslation(slideOffset);
        mHandle.setTranslationX(translationX);
    }

    @Override
    public void onDrawerStateChanged(int arg0) {

    }

    public View getView(){
        return mHandle;
    }

    public View getDrawer() {
        return mDrawer;
    }

    public void setVerticalOffset(float offset) {
        updateScreenDimensions();
        mVerticalOffset = offset;
        mHandle.setY(mVerticalOffset*mScreenDimensions.y);
    }
}

我仍然无法得到想要的输出::

到目前为止我所做的:

主活动::

import java.util.Locale;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.SearchManager;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;


public class MainActivity extends Activity {
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;

    private CharSequence mDrawerTitle;
    private CharSequence mTitle;
    private String[] mPlanetTitles;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTitle = mDrawerTitle = getTitle();
        mPlanetTitles = getResources().getStringArray(R.array.planets_array);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        // set a custom shadow that overlays the main content when the drawer
        // opens
        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
                GravityCompat.START);
        // set up the drawer's list view with items and click listener
        mDrawerList.setAdapter(new ArrayAdapter<String>(this,
                R.layout.drawer_list_item, mPlanetTitles));
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

        // enable ActionBar app icon to behave as action to toggle nav drawer
        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);

        // ActionBarDrawerToggle ties together the the proper interactions
        // between the sliding drawer and the action bar app icon
        mDrawerToggle = new ActionBarDrawerToggle(this, // host Activity
                mDrawerLayout, // DrawerLayout object
                R.drawable.ic_drawer, // nav drawer image to replace 'Up' caret
                R.string.drawer_open, // "open drawer" description for
                                        // accessibility
                R.string.drawer_close // "close drawer" description for
                                        // accessibility
        ) {
            public void onDrawerClosed(View view) {
                getActionBar().setTitle(mTitle);
                invalidateOptionsMenu(); // creates call to
                                            // onPrepareOptionsMenu()
            }

            public void onDrawerOpened(View drawerView) {
                getActionBar().setTitle(mDrawerTitle);
                invalidateOptionsMenu(); // creates call to
                                            // onPrepareOptionsMenu()
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);
        float verticalOffset = 0.2f;
        View drawer = findViewById(R.id.content_frame);
        DrawerHandle.attach(drawer, R.layout.handle, verticalOffset);
        if (savedInstanceState == null) {
            selectItem(0);
        }

        mDrawerLayout.setDrawerListener(mDrawerToggle);
    }

    /* The click listner for ListView in the navigation drawer */
    private class DrawerItemClickListener implements
            ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            selectItem(position);
        }
    }

    private void selectItem(int position) {
        // update the main content by replacing fragments
        Fragment fragment = new PlanetFragment();
        Bundle args = new Bundle();
        args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
        fragment.setArguments(args);

        FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.content_frame, fragment).commit();

        // update selected item and title, then close the drawer
        mDrawerList.setItemChecked(position, true);
        setTitle(mPlanetTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // Pass any configuration change to the drawer toggls
        mDrawerToggle.onConfigurationChanged(newConfig);
    }
}

活动_main。xml

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#fff"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp" />

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

到目前为止,我得到了:

现在,当我点击抽屉把手图标时,我得到了以下错误。。。

Logcat::

java.lang.IllegalArgumentException: View android.widget.FrameLayout{5282c560 V.E..... ........ 0,0-768,1038 #7f09003d app:id/content_frame} is not a drawer
at android.support.v4.widget.DrawerLayout.isDrawerOpen(DrawerLayout.java:1157)
at android.support.v4.widget.DrawerLayout.isDrawerOpen(DrawerLayout.java:1174)
at learn2crack.slidingnavigationdrawer.DrawerHandle$1.onClick(DrawerHandle.java:81)
at android.view.View.performClick(View.java:4438)
at learn2crack.slidingnavigationdrawer.DrawerHandle$2.onTouch(DrawerHandle.java:99)

请让我知道你的宝贵建议。

任何链接/指导都将是有帮助的......

提前感谢。。。

共有2个答案

松刚豪
2023-03-14

在onClick-in-DrawerHandle类中尝试此操作

if (mDrawerlayout.isDrawerOpen(Gravity.START)) {
                    mDrawerlayout.closeDrawers();
                } else {
                    mDrawerlayout.openDrawer(Gravity.START);
                }
慕璞
2023-03-14

您需要将Drawer和其他UI代码放在DrawerLayout中。考虑这个例子:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >        

    <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >

        <com.fscz.views.BounceViewPager
            android:id="@+id/content_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" 
            android:layout_centerInParent="true"
            />

        <com.fscz.views.CirclePageIndicator
            android:id="@+id/content_indicator"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" 
            android:padding="10dp"
            android:layout_centerHorizontal="true"
            android:layout_alignParentBottom="true"
            android:layout_marginTop="100dp"
            style="@style/link"
            />

    </RelativeLayout>

<LinearLayout
        android:id="@+id/drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="right"
        android:orientation="vertical"
        android:padding="20dp"
        android:background="@color/black_transparent"
        >
        <TextView
            android:layout_width="240dp"
            android:layout_height="wrap_content"
            style="@style/text"
            android:text="@string/collections"
            android:paddingBottom="20dp"
            />
        <ListView 
            android:id="@+id/drawer_list"
            android:layout_width="240dp"
            android:layout_height="0dip"
            android:choiceMode="singleChoice"
            android:divider="@android:color/transparent"
            android:dividerHeight="0dp"
            android:layout_weight="1"
            />
</LinearLayout>

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

根元素是android。支持v4.widget。抽屉布局。内部有2个元素。相对论和线性布局。按照惯例,抽屉布局假设第一个元素是活动/片段/任何内容的实际布局。第二个元素是抽屉。不是抽屉把手,而是从侧面拖入的用户界面。您可以通过Java代码添加句柄。

所以简而言之您尝试将句柄添加到布局中-在我的示例中是RelativeLayout,在您的示例中是FrameLayout-而不是抽屉。在您的示例中,抽屉的id为:left\u drawer

 类似资料:
  • 当我右击应用程序时,在此处输入图像描述 当我尝试按照上述步骤创建名为“HomeActivity”的导航抽屉活动时。它只是在菜单目录和AndroidManifest中的“.HomeActivity”中创建一个xml文件。xml文件(给出错误)。但是家庭活动。java和activity_主页。xml和其他片段和导航活动未创建。 我已附上我的AndroidManifest。xml代码。注意:我目前使用的

  • 我在我的词典应用程序中使用了第一个刀柄,但是当我运行我的应用程序时,它会崩溃并显示此日志: 这是我的模块类:`@ Module @ InstallIn(singleton component::class)object word info Module { 这是我的主活动类,它初始化视图模型并尝试使用它: 这是我的观点模型: 问题出在哪里,怎么解决?

  • 要在OpenGL中使用无绑定图像,需要使用glGetImageHandleARB创建GLuint64句柄。然后,可以将此句柄设置为统一的image2D变量,并使用图像,就像使用旧方法绑定一样。没问题。使用纹理/采样器,还可以将(纹理)控制柄设置为普通统一的uint64_t变量,而不是sampler2D。然后,可以使用该句柄在运行时使用构造函数sampler2D(句柄)来“构造”采样器对象。 扩展描

  • 我试图遵循谷歌最新的良好实践,用导航组件实现单个活动应用程序。 然而,在阅读了整个导航留档后,我仍然认为有很多情况下,他们没有解决。 例如,我应该如何实现以下情况: 应用程序在闪屏中启动。然后在加载后进入新闻片段。 注意:闪屏应该从后台弹出,因为它不应该再出现了。 然而,部分中的一些片段可以导航到一个新区域,该区域应该有一个后退按钮(而不是抽屉)。

  • 我正在学习android和java的编程,需要一些关于android上“导航抽屉”的帮助。 我正在努力为抽屉项的单击侦听器添加一个switch语句,我使用的代码取自以下示例:http://hmkcode.com/android-creating-a-navigation-drawer/ 我应该如何准确地处理switch语句,以便从触摸其中一个项目开始新的活动? 非常感谢。 编辑 public vo

  • 有人能告诉我如何创建活动到这个主要活动,导航抽屉将看到在所有他们?我需要使用这个特定的MainActivity代码。我不需要使用碎片,只要3个简单的活动将添加到这个抽屉。 NavDrawer布局: