Creating a Navigation Drawer中使用的Navigation Drawer的android:minSdkVersion="14",现在Android API Version 小于14的还有30%左右呢。Android个版本的占有量可参考 Platform Version。


Android Platform Version


我们的应用为了适配不同的版本,需要降低minSdkVersion,作者一般适配SDK到API 7。这一篇博文也是把Creating a Navigation Drawer的例子适配到API 7 。例子中降低API最主要的修改Action Bar,Action Bar是API 11才出现的,适配到API 7,我们使用了actionbarsherlock.


修改后的代码:

public class MainActivity extends SherlockFragmentActivity {    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        getSupportActionBar().setDisplayHomeAsUpEnabled(true);        getSupportActionBar().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 */                ) {                /** Called when a drawer has settled in a completely closed state. */              public void onDrawerClosed(View view) {              getSupportActionBar().setTitle(mTitle);              }                /** Called when a drawer has settled in a completely open state. */              public void onDrawerOpened(View drawerView) {              getSupportActionBar().setTitle(mDrawerTitle);              }                     };        mDrawerLayout.setDrawerListener(mDrawerToggle);        if (savedInstanceState == null) {            selectItem(0);        }    }        @Override    public boolean onCreateOptionsMenu(Menu menu) {        MenuInflater inflater = getSupportMenuInflater();        inflater.inflate(R.menu.main, menu);        return super.onCreateOptionsMenu(menu);    }    /* Called whenever we call invalidateOptionsMenu() */    @Override    public boolean onPrepareOptionsMenu(Menu menu) {        // If the nav drawer is open, hide action items related to the content view        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);        menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);        return super.onPrepareOptionsMenu(menu);    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {         // The action bar home/up action should open or close the drawer.         // ActionBarDrawerToggle will take care of this.//        if (mDrawerToggle.onOptionsItemSelected(item)) {//            return true;//        }        // Handle action buttons        switch(item.getItemId()) {        case android.R.id.home:         handleNavigationDrawerToggle();        return true;        case R.id.action_websearch:            // create intent to perform web search for this planet            Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);            intent.putExtra(SearchManager.QUERY, getSupportActionBar().getTitle());            // catch event that there's no activity to handle intent            if (intent.resolveActivity(getPackageManager()) != null) {                startActivity(intent);            } else {                Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show();            }            return true;        default:            return super.onOptionsItemSelected(item);        }    }    private void handleNavigationDrawerToggle() {        if (mDrawerLayout.isDrawerOpen(mDrawerList)) {        mDrawerLayout.closeDrawer(mDrawerList);        } else {        mDrawerLayout.openDrawer(mDrawerList);        }      }    /* 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 = getSupportFragmentManager();        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    public void setTitle(CharSequence title) {        mTitle = title;        getSupportActionBar().setTitle(mTitle);    }    /**     * When using the ActionBarDrawerToggle, you must call it during     * onPostCreate() and onConfigurationChanged()...     */    @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);    }    /**     * Fragment that appears in the "content_frame", shows a planet     */    public static class PlanetFragment extends Fragment {        public static final String ARG_PLANET_NUMBER = "planet_number";        public PlanetFragment() {            // Empty constructor required for fragment subclasses        }        @Override        public View onCreateView(LayoutInflater inflater, ViewGroup container,                Bundle savedInstanceState) {            View rootView = inflater.inflate(R.layout.fragment_planet, container, false);            int i = getArguments().getInt(ARG_PLANET_NUMBER);            String planet = getResources().getStringArray(R.array.planets_array)[i];            int imageId = getResources().getIdentifier(planet.toLowerCase(Locale.getDefault()),                            "drawable", getActivity().getPackageName());            ((ImageView) rootView.findViewById(R.id.image)).setImageResource(imageId);            getActivity().setTitle(planet);            return rootView;        }    }}

如果只修改JAVA代码,运行应用还是会出现异常:

08-13 13:26:15.909: E/AndroidRuntime(6832): FATAL EXCEPTION: main08-13 13:26:15.909: E/AndroidRuntime(6832): android.view.InflateException: Binary XML file line #2: Error inflating class <unknown>08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.LayoutInflater.createView(LayoutInflater.java:518)08-13 13:26:15.909: E/AndroidRuntime(6832):     at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:568)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.LayoutInflater.inflate(LayoutInflater.java:386)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.LayoutInflater.inflate(LayoutInflater.java:320)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:332)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.ArrayAdapter.getView(ArrayAdapter.java:323)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.AbsListView.obtainView(AbsListView.java:1495)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.ListView.measureHeightOfChildren(ListView.java:1216)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.ListView.onMeasure(ListView.java:1127)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.View.measure(View.java:8335)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.RelativeLayout.measureChild(RelativeLayout.java:566)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:381)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.View.measure(View.java:8335)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.View.measure(View.java:8335)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.LinearLayout.measureVertical(LinearLayout.java:531)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.LinearLayout.onMeasure(LinearLayout.java:309)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.View.measure(View.java:8335)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.View.measure(View.java:8335)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.ViewRoot.performTraversals(ViewRoot.java:843)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1892)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.os.Handler.dispatchMessage(Handler.java:99)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.os.Looper.loop(Looper.java:130)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.app.ActivityThread.main(ActivityThread.java:3835)08-13 13:26:15.909: E/AndroidRuntime(6832):     at java.lang.reflect.Method.invokeNative(Native Method)08-13 13:26:15.909: E/AndroidRuntime(6832):     at java.lang.reflect.Method.invoke(Method.java:507)08-13 13:26:15.909: E/AndroidRuntime(6832):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)08-13 13:26:15.909: E/AndroidRuntime(6832):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)08-13 13:26:15.909: E/AndroidRuntime(6832):     at dalvik.system.NativeStart.main(Native Method)08-13 13:26:15.909: E/AndroidRuntime(6832): Caused by: java.lang.reflect.InvocationTargetException08-13 13:26:15.909: E/AndroidRuntime(6832):     at java.lang.reflect.Constructor.constructNative(Native Method)08-13 13:26:15.909: E/AndroidRuntime(6832):     at java.lang.reflect.Constructor.newInstance(Constructor.java:415)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.LayoutInflater.createView(LayoutInflater.java:505)08-13 13:26:15.909: E/AndroidRuntime(6832):     ... 32 more08-13 13:26:15.909: E/AndroidRuntime(6832): Caused by: java.lang.UnsupportedOperationException: Can't convert to dimension: type=0x208-13 13:26:15.909: E/AndroidRuntime(6832):     at android.content.res.TypedArray.getDimensionPixelSize(TypedArray.java:463)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.view.View.<init>(View.java:1978)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.TextView.<init>(TextView.java:350)08-13 13:26:15.909: E/AndroidRuntime(6832):     at android.widget.TextView.<init>(TextView.java:343)08-13 13:26:15.909: E/AndroidRuntime(6832):     ... 35 more

这个异常是 drawer_list_item.xml文件的内容产生的,drawer_list_item.xml内容:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@android:id/text1"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:textAppearance="?android:attr/textAppearanceListItemSmall"    android:gravity="center_vertical"    android:paddingLeft="16dp"    android:paddingRight="16dp"    android:textColor="#fff"    android:background="?android:attr/activatedBackgroundIndicator"    android:minHeight="?android:attr/listPreferredItemHeightSmall"/>

而在API 14之前的版本中,下面的三个属性会报异常:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"      android:textAppearance="?android:attr/textAppearanceListItemSmall"      android:background="?android:attr/activatedBackgroundIndicator"      android:minHeight="?android:attr/listPreferredItemHeightSmall"/>

如果想适配更低的版本需要做如下的修改:

1)修改drawer_list_item.xml文件,使用自定义的属性

<?xml version="1.0" encoding="UTF-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@android:id/text1"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:background="?attr/myapp_activatedBackgroundIndicator"    android:gravity="center_vertical"    android:minHeight="?attr/myapp_listPreferredItemHeightSmall"    android:paddingLeft="16dp"    android:paddingRight="16dp"    android:textAppearance="?attr/myapp_textAppearanceListItemSmall" />

2)在 values/attrs.xml文件中声明自定义属性


<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="AppTheme">    <!-- Attributes below are needed to support the navigation drawer on Android 3.x. -->    <!-- A smaller, sleeker list item height. -->    <attr name="myapp_listPreferredItemHeightSmall" format="dimension" />    <!-- Drawable used as a background for activated items. -->    <attr name="myapp_activatedBackgroundIndicator" format="reference" />    <!-- The preferred TextAppearance for the primary text of small list items. -->    <attr name="myapp_textAppearanceListItemSmall" format="reference" /></declare-styleable></resources>

3) values-11/styles.xml文件中添加

  <!--        Base application theme, dependent on API level. This theme is replaced        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.    -->    <style name="AppBaseTheme" parent="Theme.Sherlock.Light.DarkActionBar">        <!--            Theme customizations available in newer API levels can go in            res/values-vXX/styles.xml, while customizations related to            backward-compatibility can go here.        -->        <!-- Implementation of attributes needed for the navigation drawer as the default implementation is based on API-14. -->        <item name="myapp_listPreferredItemHeightSmall">48dip</item>        <item name="myapp_textAppearanceListItemSmall">@style/MyappDrawerMenu</item>        <item name="myapp_activatedBackgroundIndicator">@android:color/transparent</item>    </style>    <style name="MyappDrawerMenu">        <item name="android:textSize">16sp</item>        <item name="android:textStyle">bold</item>        <item name="android:textColor">@android:color/black</item>    </style>

4) values-v14/styles.xml文件中添加

<!--        Base application theme for API 14+. This theme completely replaces        AppBaseTheme from BOTH res/values/styles.xml and        res/values-v11/styles.xml on API 14+ devices.    -->    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">         <!-- For API-14 and above the default implementation of the navigation drawer menu is used. Below APU-14 a custom implementation is used. -->           <item name="myapp_listPreferredItemHeightSmall">?android:attr/listPreferredItemHeightSmall</item>           <item name="myapp_textAppearanceListItemSmall">?android:attr/textAppearanceListItemSmall</item>           <item name="myapp_activatedBackgroundIndicator">?android:attr/activatedBackgroundIndicator</item>       </style>


OK,经过上面步骤,运行成功,这样上一篇的例子就能很好的适配到API 7了。



/** * @author 张兴业 * http://blog.csdn.net/xyz_lmn * iOS入门群:83702688
* android开发进阶群:241395671 * 我的新浪微博:@张兴业TBOW */

代码下载:Demo


更多相关文章

  1. android 扫描SD卡与系统文件(转)
  2. 如何修改应用兼容Android(安卓)3.0系统
  3. android 长按power键弹出对话框
  4. Android(安卓)xml资源文件中@、@android:type、@*、?、@+含义和区
  5. 修复 XE8 for Android(安卓)方向传感器 headingX,Y,Z 不会动的问
  6. 修改EditText的光标颜色
  7. android 8.1.0 添加系统service
  8. android framework增加新的系统服务
  9. Android关于SD卡的读写操作及固定图片大小

随机推荐

  1. 给Android开发者的10个建议
  2. Andriod 的基本原理
  3. 【Android】如何判断一个fragment是否显
  4. android制作圆角图片和图片倒影
  5. 分享一个圆角自定义的漂亮AlertDialog
  6. Android 蓝牙4.0踩坑—扫描不到设备
  7. android 获取SIM卡的类型··
  8. 【30篇突击 android】源码统计 十二
  9. Android 倒计时操作
  10. Android之浮动小窗口