Reputation: 300
i am beginner in android and implementing my first app!.
i use a Fragment for Navigation Drawer in my app, and i want it to open from right to left. in the fragment tag of the main xml file i set android:layout_gravity="right"
but when i run my app and touch the toggle button to open the navigation drawer, suddenly the app crashes! and i receive an error from logcat that is java.lang.IllegalArgumentException: No drawer view found with gravity LEFT
. what should i do to solve this problem?
thanks so much.
//NavDrawerItem.java
public class NavDrawerItem {
private boolean showNotify;
private String title;
public NavDrawerItem() {
}
public NavDrawerItem(boolean showNotify, String title) {
this.showNotify = showNotify;
this.title = title;
}
public boolean isShowNotify() {
return showNotify;
}
public void setShowNotify(boolean showNotify) {
this.showNotify = showNotify;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
nav_drawer_row.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true">
<TextView
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="30dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textSize="15dp"
android:textStyle="bold" />
</RelativeLayout>
fragment_navigation_drawer.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutDirection="rtl"
android:background="@android:color/white">
<RelativeLayout
android:id="@+id/nav_header_container"
android:layout_width="match_parent"
android:layout_height="140dp"
android:layout_alignParentTop="true"
android:background="@color/colorPrimary">
<ImageView
android:layout_width="70dp"
android:layout_height="70dp"
android:src="@drawable/ic_user"
android:scaleType="fitCenter"
android:layout_centerInParent="true" />
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:layout_marginRight="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/nav_header_container"
android:layout_marginTop="15dp" />
</RelativeLayout>
NavigationDrawerAdapter.java:
public class NavigationDrawerAdapter extends RecyclerView.Adapter<NavigationDrawerAdapter.MyViewHolder> {
List<NavDrawerItem> data = Collections.emptyList();
private LayoutInflater inflater;
private Context context;
public NavigationDrawerAdapter(Context context, List<NavDrawerItem> data) {
this.context = context;
inflater = LayoutInflater.from(context);
this.data = data;
}
public void delete(int position) {
data.remove(position);
notifyItemRemoved(position);
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.nav_drawer_row, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
NavDrawerItem current = data.get(position);
holder.title.setText(current.getTitle());
}
@Override
public int getItemCount() {
return data.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView title;
public MyViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
}
}
}
FragmentDrawer.java:
public class FragmentDrawer extends Fragment {
private static String TAG = FragmentDrawer.class.getSimpleName();
private RecyclerView recyclerView;
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
private NavigationDrawerAdapter adapter;
private View containerView;
private static String[] titles = null;
private FragmentDrawerListener drawerListener;
public FragmentDrawer() {
}
public void setDrawerListener(FragmentDrawerListener listener) {
this.drawerListener = listener;
}
public static List<NavDrawerItem> getData() {
List<NavDrawerItem> data = new ArrayList<>();
// preparing navigation drawer items
for (int i = 0; i < titles.length; i++) {
NavDrawerItem navItem = new NavDrawerItem();
navItem.setTitle(titles[i]);
data.add(navItem);
}
return data;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// drawer labels
titles = getActivity().getResources().getStringArray(R.array.nav_drawer_labels);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflating view layout
View layout = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
recyclerView = (RecyclerView) layout.findViewById(R.id.drawerList);
adapter = new NavigationDrawerAdapter(getActivity(), getData());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new ClickListener() {
@Override
public void onClick(View view, int position) {
drawerListener.onDrawerItemSelected(view, position);
mDrawerLayout.closeDrawer(containerView);
}
@Override
public void onLongClick(View view, int position) {
}
}));
return layout;
}
public void setUp(int fragmentId, DrawerLayout drawerLayout, final Toolbar toolbar) {
containerView = getActivity().findViewById(fragmentId);
mDrawerLayout = drawerLayout;
mDrawerToggle = new ActionBarDrawerToggle(getActivity(), drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getActivity().invalidateOptionsMenu();
}
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
getActivity().invalidateOptionsMenu();
}
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
toolbar.setAlpha(1 - slideOffset / 2);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerLayout.post(new Runnable() {
@Override
public void run() {
mDrawerToggle.syncState();
}
});
}
public static interface ClickListener {
public void onClick(View view, int position);
public void onLongClick(View view, int position);
}
static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildPosition(child));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
public interface FragmentDrawerListener {
public void onDrawerItemSelected(View view, int position);
}
}
activity_main.xml:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/container_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
</LinearLayout>
<FrameLayout
android:id="@+id/container_body"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
<fragment
android:id="@+id/fragment_navigation_drawer"
android:name="com.example.videolabpc.mytoolbar.FragmentDrawer"
android:layout_width="@dimen/nav_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
app:layout="@layout/fragment_navigation_drawer"
tools:layout="@layout/fragment_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>
MainActivity.java :
private FragmentDrawer drawerFragment;
drawerFragment = (FragmentDrawer) getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
the Logcat after crashing :
09-14 04:24:46.193 1539-1539/? E/SensorManager: sensor or listener is null
09-14 04:24:46.194 1539-1539/? E/SensorManager: registerListenerImpl() [Sensor: null, SensorEventListener: com.lge.lockscreen.model.ScreenTurnOffBySensor@5997807] by com.lge.lockscreen.model.ScreenTurnOffBySensor.registerProximitySensor():58
09-14 04:24:46.203 278-2219/? E/lge_audio_pcm_dump: lge_set_dump_config: exit dump_config : 0
09-14 04:24:48.544 278-1070/? E/audio_hw_primary: select_devices: enter and usecase(1)
09-14 04:24:48.545 278-1070/? E/audio_hw_primary: enable_snd_device: enter 2
09-14 04:24:51.913 278-1325/? E/audio_hw_primary: disable_snd_device: enter 2
09-14 04:25:14.826 5149-5149/com.teroject.teroject E/GMPM: GoogleService failed to initialize, status: 10, Missing an expected resource: 'R.string.google_app_id' for initializing Google services. Possible causes are missing google-services.json or com.google.gms.google-services gradle plugin.
09-14 04:25:14.826 5149-5149/com.teroject.teroject E/GMPM: Scheduler not set. Not logging error/warn.
09-14 04:25:14.881 5149-5181/com.teroject.teroject E/GMPM: Uploading is not possible. App measurement disabled
09-14 04:25:15.600 5149-5149/com.teroject.teroject E/OneSignal: You must initialize OneSignal before modifying tags! Omitting this tag operation.
09-14 04:25:16.658 272-994/? E/BandwidthController: [LG DATA] No such appUid: 10004
09-14 04:25:16.860 272-994/? E/BandwidthController: [LG DATA] No such appUid: 10187
09-14 04:25:16.901 5149-5149/com.teroject.teroject E/MediaProfilesEx-JNI: register_com_lge_media_MediaProfilesEx
09-14 04:25:16.903 5149-5149/com.teroject.teroject E/MediaRecorderEx-JNI: register_com_lge_media_MediaRecorderEx
09-14 04:25:16.905 5149-5149/com.teroject.teroject E/SurfaceControlEx: register_com_lge_view_SurfaceControlEx
09-14 04:25:16.912 5149-5149/com.teroject.teroject E/MediaPlayerEx-jni: register_com_lge_view_MediaPlayerEx
09-14 04:25:21.548 5149-5149/com.teroject.teroject E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.teroject.teroject, PID: 5149
java.lang.IllegalArgumentException: No drawer view found with gravity LEFT
at android.support.v4.widget.DrawerLayout.openDrawer(DrawerLayout.java:1618)
at android.support.v7.app.ActionBarDrawerToggle.toggle(ActionBarDrawerToggle.java:290)
at android.support.v7.app.ActionBarDrawerToggle.access$100(ActionBarDrawerToggle.java:64)
at android.support.v7.app.ActionBarDrawerToggle$1.onClick(ActionBarDrawerToggle.java:200)
at android.view.View.performClick(View.java:4764)
at android.view.View$PerformClick.run(View.java:19844)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5354)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
09-14 04:25:21.579 278-1070/? E/audio_hw_primary: select_devices: enter and usecase(1)
09-14 04:25:21.579 278-1070/? E/audio_hw_primary: enable_snd_device: enter 2
09-14 04:25:21.766 1001-1483/? E/ConnectivityService: RemoteException caught trying to send a callback msg for NetworkRequest [ id=8, legacyType=-1, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN] ]
09-14 04:25:22.510 2648-2648/? E/NetworkScheduler.SR: Invalid parameter app
09-14 04:25:22.510 2648-2648/? E/NetworkScheduler.SR: Invalid package name : Perhaps you didn't include a PendingIntent in the extras?
09-14 04:25:22.562 3927-4157/? E/Drive.UninstallOperation: Package still installed com.teroject.teroject
09-14 04:25:22.730 5547-5547/? E/Finsky: [1] com.google.android.finsky.wear.bo.a(838): onConnectionFailed: ConnectionResult{statusCode=API_UNAVAILABLE, resolution=null, message=null}
09-14 04:25:23.217 3927-5659/? E/IntentOperationSvc: Failed to instantiate Chimera operation impl, dropping operation
09-14 04:25:23.223 5547-5547/? E/Finsky: [1] com.google.android.finsky.wear.bo.a(838): onConnectionFailed: ConnectionResult{statusCode=API_UNAVAILABLE, resolution=null, message=null}
09-14 04:25:24.332 272-994/? E/BandwidthController: [LG DATA] No such appUid: 10187
09-14 04:25:24.585 2648-2648/? E/NetworkScheduler.SR: Invalid parameter app
09-14 04:25:24.585 2648-2648/? E/NetworkScheduler.SR: Invalid package name : Perhaps you didn't include a PendingIntent in the extras?
09-14 04:25:24.776 278-1325/? E/audio_hw_primary: disable_snd_device: enter 2
09-14 04:25:24.799 5860-5860/? E/App: [App][onCreate()] 4.40.21
09-14 04:25:26.507 272-994/? E/BandwidthController: [LG DATA] No such appUid: 10101
09-14 04:25:27.341 272-994/? E/BandwidthController: [LG DATA] No such appUid: 10100
09-14 04:25:29.554 5901-5936/? E/a: Failed to send crash attachment report /data/data/com.instagram.android/app_minidumps/307ff5ad80207d193ff0aa19e8633a8a.dmp
com.facebook.g.b.c: Error while sending report to Http Post Form.
at com.facebook.g.b.d.a(HttpPostSender.java:110)
at com.facebook.g.n.b(ErrorReporter.java:1436)
at com.facebook.g.n.a(ErrorReporter.java:1626)
at com.facebook.g.n.a(ErrorReporter.java:1483)
at com.facebook.g.n.a(ErrorReporter.java:118)
at com.facebook.g.i.a(ErrorReporter.java:348)
at com.facebook.g.i.run(ErrorReporter.java:360)
Caused by: java.net.SocketTimeoutException: failed to connect to www.facebook.com/10.10.34.36 (port 443) after 3000ms
at libcore.io.IoBridge.connectErrno(IoBridge.java:169)
at libcore.io.IoBridge.connect(IoBridge.java:122)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:183)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:456)
at java.net.Socket.connect(Socket.java:886)
at com.android.okhttp.internal.Platform.connectSocket(Platform.java:139)
at com.android.okhttp.Connection.connect(Connection.java:155)
at com.android.okhttp.Connection.connect(Connection.java:170)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:309)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:242)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:397)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:118)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:229)
at com.android.okhttp.internal.http.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218)
at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:25)
at com.facebook.g.c.f.a(HttpRequest.java:52)
at com.facebook.g.b.d.b(HttpPostSender.java:134)
at com.facebook.g.b.d.a(HttpPostSender.java:108)
at com.facebook.g.n.b(ErrorReporter.java:1436)
at com.facebook.g.n.a(ErrorReporter.java:1626)
at com.facebook.g.n.a(ErrorReporter.java:1483)
at com.facebook.g.n.a(ErrorReporter.java:118)
at com.facebook.g.i.a(ErrorReporter.java:348)
at com.facebook.g.i.run(ErrorReporter.java:360)
09-14 04:25:32.298 5901-5901/? E/ActivityThread: Failed to find provider info for com.facebook.katana.provider.AttributionIdProvider
09-14 04:25:32.311 5901-5954/? E/ActivityThread: Failed to find provider info for com.facebook.katana.provider.AttributionIdProvider
09-14 04:25:32.446 272-994/? E/BandwidthController: [LG DATA] No such appUid: 10101
09-14 04:25:32.727 272-994/? E/BandwidthController: [LG DATA] No such appUid: 10101
Upvotes: 0
Views: 829
Reputation: 3418
For me adding the following property:
android:layoutDirection="rtl"
to the DrawerLayout and NavigationView Solved the problem
Upvotes: 1
Reputation: 38595
The problem is ActionBarDrawerToggle
always expects the drawer to be on the side corresponding to Gravity.START
. In most locales this is on the left side, hence it tries to open the drawer with Gravity.LEFT
, but yours is on the other side so it throws an exception instead. Whether or not this seems like an intelligent design decision, it is what it is.
If you are following the Material Design guidelines, your drawer will cover the action bar when it opens (it might already be doing this). Specifically for this reason, I don't like using ActionBarDrawerToggle
and don't find it particularly useful; the animation of the menu icon to an arrow is obscured by the drawer, and the other functionality is easy enough to implement directly in the activity. In your case, the animation might actually be useful if your drawer on the other side doesn't cover the icon, but then again you might not want the icon to animate at all anyway.
In your onCreate()
method, all you need to do is
toolbar.setNavigationOnClickListener()
(or set an OnClickListener
on a view in your Toolbar
) and have this listener toggle the drawer using drawerLayout.openDrawer(Gravity.RIGHT)
and the equivalent closeDrawer()
method.drawerLayout.addDrawerListener()
to add a listener. When the drawer opens or closes, you can use this listener to change things like the toolbar's icon and/or its contentDescription (for accessibility), or to do anything else you like Upvotes: 1