以编程方式设置图标会导致RuntimeException。造成这种情况的原因是什么?

时间:2016-02-23 12:58:46

标签: java android

所以我试图通过代码将一些菜单项添加到导航抽屉中,因此我正在进行一些测试。一切正常,除了我尝试为菜单项设置图标时遇到的RuntimeException错误。该错误让我感到困惑,因为它说它无法投射NavigationMenuSeperatorItem

代码段:

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    Menu menu = navigationView.getMenu();
    MenuItem it1 = menu.add(R.id.group1, 1, 2, "TEST DYNAMIC");
//        it1.setIcon(R.drawable.ic_menu_camera);

因此,it1.setIcon位被注释掉,一切正常。菜单项位于正确的位置,完全没有问题。只要我将setIcon位添加到代码中,应用程序就会在启动时崩溃。

我在这里做错了什么,或者发生了什么奇怪的事情?

完成mainActivity:

package com.example.tim.timapp;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Base64;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.example.fragments.MainFragments.MainFragment;
import com.example.fragments.MainFragments.SubFragments.VariableFragment;
import com.example.fragments.MainFragments.TimeLightFragment;
import com.example.fragments.MainFragments.ToggleLightFragment;
import com.example.fragments.MainFragments.WakeUpLightFragment;
import com.example.fragments.Settings.GeneralSettingsFragment;
import com.example.fragments.Settings.StuffManagerFragment;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    private static boolean isMainShown = false;
    private static boolean isSettingsShown = false;
    private static boolean doSavePopup = false;
    private static String backTitle = "";

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

        setContentView(R.layout.activity_main);
        isMainShown = true;
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        Menu menu = navigationView.getMenu();
        MenuItem it1 = menu.add(R.id.group1, 1, 2, "TEST DYNAMIC");
//        it1.setIcon(R.drawable.ic_menu_camera);

        FragmentManager fm = getFragmentManager();
        fm.beginTransaction().replace(R.id.content_frame, new MainFragment()).commit();
    }

    @Override
    public void onBackPressed() {
        Log.d("TEST", Boolean.toString(doSavePopup));
        FragmentManager fm = getFragmentManager();
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else if (isSettingsShown) {
            getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
            setTitle(backTitle);
            isSettingsShown = false;
        } else if (!isMainShown) {
            fm.beginTransaction().replace(R.id.content_frame, new MainFragment()).commit();
            setTitle("Home");
            isMainShown = true;
        } else if (doSavePopup) {
            new AlertDialog.Builder(MainActivity.this)
                    .setMessage(R.string.generalSettingsLeaving)
                    .setTitle("TEST")
                    .setCancelable(true)
                    .setPositiveButton(R.string.generalSettingsLeavingSave, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //TODO: Clicked Save, save.
                        }
                    })
                    .setNegativeButton(R.string.generalSettingsLeavingDiscard, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //TODO: Clicked Discard, discard.
                        }
                    }).create().show();
//            fm.beginTransaction().replace(R.id.content_frame, new MainFragment()).commit();
//            setTitle("Home");
            isMainShown = true;
            doSavePopup = false;
            //TODO: Tidy up here, from changing to a general doSavePopup thingy.
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        FragmentManager fm = getFragmentManager();
        isMainShown = false;
        isSettingsShown = true;

        //TODO Change from general-settings page to specific settings page.

        switch (item.getItemId()) {
            case 0:
                fm.beginTransaction().replace(R.id.content_frame, new GeneralSettingsFragment()).addToBackStack("backStack").commit();
                backTitle = getString(R.string.settings);
                setTitle(backTitle + " Settings");
                return true;
            case 1:
                fm.beginTransaction().replace(R.id.content_frame, new GeneralSettingsFragment()).addToBackStack("backStack").commit();
                backTitle = getString(R.string.navdrawer_timelight);
                setTitle(backTitle + " Settings");
                return true;
            case 2:
                fm.beginTransaction().replace(R.id.content_frame, new GeneralSettingsFragment()).addToBackStack("backStack").commit();
                backTitle = getString(R.string.navdrawer_togglelight);
                setTitle(backTitle + " Settings");
                return true;
            case 3:
                fm.beginTransaction().replace(R.id.content_frame, new GeneralSettingsFragment()).addToBackStack("backStack").commit();
                backTitle = getString(R.string.navdrawer_wakeuplight);
                setTitle(backTitle + " Settings");
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {

        FragmentManager fm = getFragmentManager();
        isMainShown = false;

        int id = item.getItemId();

        if (id == R.id.nav_wakeuplight) {
            fm.beginTransaction().replace(R.id.content_frame, new WakeUpLightFragment()).commit();
            setTitle(getString(R.string.navdrawer_wakeuplight));
            new JSONTask().execute("http://192.168.0.120:8080/json.htm?type=command&param=getuservariables", "WuL");
            doSavePopup = true;
        } else if (id == R.id.nav_togglelights) {
            fm.beginTransaction().replace(R.id.content_frame, new ToggleLightFragment()).commit();
            setTitle(getString(R.string.navdrawer_togglelight));
        } else if (id == R.id.nav_timelight) {
            fm.beginTransaction().replace(R.id.content_frame, new TimeLightFragment()).commit();
            setTitle(getString(R.string.navdrawer_timelight));
        } else if (id == R.id.nav_generalsettings) {
            fm.beginTransaction().replace(R.id.content_frame, new GeneralSettingsFragment()).commit();
            setTitle(getString(R.string.navdrawer_generalsettings));
//            isGeneralSettingsShown = true;
        } else if (id == R.id.nav_stuffmanager) {
            fm.beginTransaction().replace(R.id.content_frame, new StuffManagerFragment()).commit();
            setTitle(getString(R.string.navdrawer_stuffmanager));
        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    public class JSONTask extends AsyncTask<String, String, String> {

        final String basicAuth = "Basic " + Base64.encodeToString("pi:pass".getBytes(), Base64.NO_WRAP);

        ArrayList<String> GlobalkArray = new ArrayList<>();
        ArrayList<Integer> GlobalvArray = new ArrayList<>();

        @Override
        protected String doInBackground(String... params) {
            HttpURLConnection connection = null;
            BufferedReader reader = null;
            try {
                URL url = new URL(params[0]);
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestProperty("Authorization", basicAuth);
                connection.connect();

                InputStream stream = connection.getInputStream();

                reader = new BufferedReader(new InputStreamReader(stream));

                StringBuilder buffer = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    buffer.append(line);
                }

                try {
                    JSONObject jsonRootObject = new JSONObject(buffer.toString());

                    JSONArray jsonArray = jsonRootObject.optJSONArray("result");
                    ArrayList<String> kArray= new ArrayList<>();
                    ArrayList<Integer> vArray= new ArrayList<>();
                    for (int i = 0; i < jsonArray.length(); i++) {
                        JSONObject jsonObject = jsonArray.getJSONObject(i);

                        int idx = Integer.parseInt(jsonObject.optString("idx"));
                        String name = jsonObject.optString("Name");
                        int value = Integer.parseInt(jsonObject.optString("Value"));

                        kArray.add(i, name);
                        vArray.add(i, value);

                    }
                    int j = 0;
                    for (int i=0; i < kArray.size(); i++){
                        if ((kArray.get(i)).contains(params[1])){
                            GlobalkArray.add(j, kArray.get(i));
                            GlobalvArray.add(j, vArray.get(i));
                            j++;
                        } else {
                            Log.d("Array", "This value (" + kArray.get(i) + ") does not contain the parameter (" + params[1] + ")");
//                            Do nothing, filters out all variables that do NOT have the given parameter in it.
                        }
                    }
                } catch (JSONException e) {e.printStackTrace();}

                return "true";

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
                try {
                    if (reader != null) {
                        reader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute (String result){
            super.onPostExecute(result);
            FragmentManager fm = getFragmentManager();
            if (result != null) {
                for (int i=0; i < GlobalkArray.size(); i++) {
                    fm.beginTransaction().add(R.id.FragmentContainer, new VariableFragment(), "VariableFragment").commit();
                    fm.executePendingTransactions();
                    ((VariableFragment)getFragmentManager().findFragmentByTag("VariableFragment")).setTextView(GlobalkArray.get(i));
                    ((VariableFragment)getFragmentManager().findFragmentByTag("VariableFragment")).setEditText(GlobalvArray.get(i).toString());
                }
            } else {
                Log.e("OnPostExecute", "Result is null");
            }
        }
    }
}

日志:

02-23 13:41:59.730 13630-13630/com.example.tim.timapp I/art: Not late-enabling -Xcheck:jni (already on)
02-23 13:41:59.800 13630-13630/com.example.tim.timapp W/System: ClassLoader referenced unknown path: /data/app/com.example.tim.timapp-2/lib/x86_64
02-23 13:41:59.960 13630-13630/com.example.tim.timapp D/AndroidRuntime: Shutting down VM
02-23 13:41:59.960 13630-13630/com.example.tim.timapp E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.tim.timapp, PID: 13630
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.tim.timapp/com.example.tim.timapp.MainActivity}: java.lang.ClassCastException: android.support.design.internal.NavigationMenuPresenter$NavigationMenuSeparatorItem cannot be cast to android.support.design.internal.NavigationMenuPresenter$NavigationMenuTextItem
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.ClassCastException: android.support.design.internal.NavigationMenuPresenter$NavigationMenuSeparatorItem cannot be cast to android.support.design.internal.NavigationMenuPresenter$NavigationMenuTextItem
at android.support.design.internal.NavigationMenuPresenter$NavigationMenuAdapter.appendTransparentIconIfMissing(NavigationMenuPresenter.java:507)
at android.support.design.internal.NavigationMenuPresenter$NavigationMenuAdapter.prepareMenuItems(NavigationMenuPresenter.java:493)
at android.support.design.internal.NavigationMenuPresenter$NavigationMenuAdapter.update(NavigationMenuPresenter.java:426)
at android.support.design.internal.NavigationMenuPresenter.updateMenuView(NavigationMenuPresenter.java:113)
at android.support.v7.view.menu.MenuBuilder.dispatchPresenterUpdate(MenuBuilder.java:284)
at android.support.v7.view.menu.MenuBuilder.onItemsChanged(MenuBuilder.java:1030)
at android.support.v7.view.menu.MenuItemImpl.setIcon(MenuItemImpl.java:445)
at com.example.tim.timapp.MainActivity.onCreate(MainActivity.java:74)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
at android.app.ActivityThread.-wrap11(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
02-23 13:47:00.290 13630-13630/? I/Process: Sending signal. PID: 13630 SIG: 9

Activity_main_drawer.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:visible="true" android:orderInCategory="1" android:id="@+id/group1" >
        <item android:title="TEST SOLID"/>
    </group>

    <item android:title="@string/navdrawer_title1" android:orderInCategory="2">
        <menu>
            <item
                android:id="@+id/nav_wakeuplight"
                android:icon="@drawable/ic_menu_gallery"
                android:title="@string/navdrawer_wakeuplight" />
            <item
                android:id="@+id/nav_togglelights"
                android:icon="@drawable/ic_menu_gallery"
                android:title="@string/navdrawer_togglelight" />
            <item
                android:id="@+id/nav_timelight"
                android:icon="@drawable/ic_menu_gallery"
                android:title="@string/navdrawer_timelight" />
        </menu>
    </item>

    <item android:title="@string/navdrawer_title2" android:orderInCategory="3">
        <menu>
            <item
                android:id="@+id/nav_generalsettings"
                android:icon="@drawable/ic_menu_gallery"
                android:title="@string/navdrawer_generalsettings" />
            <item
                android:id="@+id/nav_stuffmanager"
                android:icon="@drawable/ic_menu_gallery"
                android:title="@string/navdrawer_stuffmanager" />
        </menu>
    </item>
</menu>

2 个答案:

答案 0 :(得分:1)

我得到了同样的错误。我在主导航菜单中使用了多个组。将ID添加到组中为我解决了这个问题。

auto haystack = std::wstring(L"\REGISTRY\MACHINE\SOFTWARE\WOW6432Node\Data");
auto needle = std::wstring(L"\WOW6432Node\Data");

也许尝试将ID添加到与组相同的层次结构级别的项目中。

答案 1 :(得分:0)

试试这样:

NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);

Menu menu = navigationView.getMenu();
menu.add(R.id.group1, itemId, 2, "TEST DYNAMIC");
menu.findItem(itemId).setIcon(R.drawable.ic_menu_camera);

我很困惑 menu.add()正在返回菜单项...