网上开源项目地址:https://github.com/ikimuhendis/LDrawer
效果图:
build.gradle
compile 'com.ikimuhendis:ldrawer:0.1'
colors.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="ldrawer_color">#FFFFFF</color> <color name="actionbar_color">#bf360c</color> <color name="drawer_arrow_second_color">#303f9f</color> </resources>
styles.xml
<resources> <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar"> <item name="android:actionBarStyle">@style/ActionBar</item> </style> <style name="ActionBar" parent="android:Widget.ActionBar"> <item name="android:background">@color/actionbar_color</item> <item name="android:icon">@android:color/transparent</item> <item name="android:titleTextStyle">@style/ActionBar.TitleText</item> </style> <style name="ActionBar.TitleText" parent="android:TextAppearance.Holo.Widget.ActionBar.Title"> <item name="android:textColor">@android:color/white</item> <item name="android:textSize">18sp</item> </style> </resources>
项目依赖开发包v4 : android.support.v4.app.ActionBarDrawerToggle,自定义 DrawerArrowDrawable,ActionBarDrawerToggle
import android.app.ActionBar; import android.app.Activity; import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.util.Log; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import java.lang.reflect.Method; import ldrawer.lanyan.com.ldrawer.R; public class ActionBarDrawerToggle extends android.support.v4.app.ActionBarDrawerToggle { private static final String TAG = ActionBarDrawerToggle.class.getName(); protected Activity mActivity; protected DrawerLayout mDrawerLayout; protected int mOpenDrawerContentDescRes; protected int mCloseDrawerContentDescRes; protected DrawerArrowDrawable mDrawerImage; protected boolean animateEnabled; public ActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, int drawerImageRes, int openDrawerContentDescRes, int closeDrawerContentDescRes) { super(activity, drawerLayout, drawerImageRes, openDrawerContentDescRes, closeDrawerContentDescRes); } public ActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, DrawerArrowDrawable drawerImage, int openDrawerContentDescRes, int closeDrawerContentDescRes) { super(activity, drawerLayout, R.mipmap.ic_drawer, openDrawerContentDescRes, closeDrawerContentDescRes); mActivity = activity; mDrawerLayout = drawerLayout; mOpenDrawerContentDescRes = openDrawerContentDescRes; mCloseDrawerContentDescRes = closeDrawerContentDescRes; mDrawerImage = drawerImage; animateEnabled = true; } public void syncState() { if (mDrawerImage == null) { super.syncState(); return; } if (animateEnabled) { if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) { mDrawerImage.setProgress(1.f); } else { mDrawerImage.setProgress(0.f); } } setActionBarUpIndicator(); setActionBarDescription(); } public void setDrawerIndicatorEnabled(boolean enable) { if (mDrawerImage == null) { super.setDrawerIndicatorEnabled(enable); return; } setActionBarUpIndicator(); setActionBarDescription(); } public boolean isDrawerIndicatorEnabled() { if (mDrawerImage == null) { return super.isDrawerIndicatorEnabled(); } return true; } public void onConfigurationChanged(Configuration newConfig) { if (mDrawerImage == null) { super.onConfigurationChanged(newConfig); return; } syncState(); } public boolean onOptionsItemSelected(MenuItem item) { return super.onOptionsItemSelected(item); } @Override public void onDrawerSlide(View drawerView, float slideOffset) { if (mDrawerImage == null) { super.onDrawerSlide(drawerView, slideOffset); return; } if (animateEnabled) { mDrawerImage.setVerticalMirror(!mDrawerLayout.isDrawerOpen(GravityCompat.START)); mDrawerImage.setProgress(slideOffset); } } @Override public void onDrawerOpened(View drawerView) { if (mDrawerImage == null) { super.onDrawerOpened(drawerView); return; } if (animateEnabled) { mDrawerImage.setProgress(1.f); } setActionBarDescription(); } @Override public void onDrawerClosed(View drawerView) { if (mDrawerImage == null) { super.onDrawerClosed(drawerView); return; } if (animateEnabled) { mDrawerImage.setProgress(0.f); } setActionBarDescription(); } protected void setActionBarUpIndicator() { if (mActivity != null) { try { Method setHomeAsUpIndicator = ActionBar.class.getDeclaredMethod("setHomeAsUpIndicator", Drawable.class); setHomeAsUpIndicator.invoke(mActivity.getActionBar(), mDrawerImage); return; } catch (Exception e) { Log.e(TAG, "setActionBarUpIndicator error", e); } final View home = mActivity.findViewById(android.R.id.home); if (home == null) { return; } final ViewGroup parent = (ViewGroup) home.getParent(); final int childCount = parent.getChildCount(); if (childCount != 2) { return; } final View first = parent.getChildAt(0); final View second = parent.getChildAt(1); final View up = first.getId() == android.R.id.home ? second : first; if (up instanceof ImageView) { ImageView upV = (ImageView) up; upV.setImageDrawable(mDrawerImage); } } } protected void setActionBarDescription() { if (mActivity != null && mActivity.getActionBar() != null) { try { Method setHomeActionContentDescription = ActionBar.class.getDeclaredMethod( "setHomeActionContentDescription", Integer.TYPE); setHomeActionContentDescription.invoke(mActivity.getActionBar(), mDrawerLayout.isDrawerOpen(GravityCompat.START) ? mOpenDrawerContentDescRes : mCloseDrawerContentDescRes); if (Build.VERSION.SDK_INT <= 19) { mActivity.getActionBar().setSubtitle(mActivity.getActionBar().getSubtitle()); } } catch (Exception e) { Log.e(TAG, "setActionBarUpIndicator", e); } } } public void setAnimateEnabled(boolean enabled) { this.animateEnabled = enabled; } public boolean isAnimateEnabled() { return this.animateEnabled; } }
import android.content.Context; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; import ldrawer.lanyan.com.ldrawer.R; public abstract class DrawerArrowDrawable extends Drawable { private static final float ARROW_HEAD_ANGLE = (float) Math.toRadians(45.0D); protected float mBarGap; protected float mBarSize; protected float mBarThickness; protected float mMiddleArrowSize; protected final Paint mPaint = new Paint(); protected final Path mPath = new Path(); protected float mProgress; protected int mSize; protected float mVerticalMirror = 1f; protected float mTopBottomArrowSize; protected Context context; public DrawerArrowDrawable(Context context) { this.context = context; this.mPaint.setAntiAlias(true); this.mPaint.setColor(context.getResources().getColor(R.color.ldrawer_color)); this.mSize = context.getResources().getDimensionPixelSize(R.dimen.ldrawer_drawableSize); this.mBarSize = context.getResources().getDimensionPixelSize(R.dimen.ldrawer_barSize); this.mTopBottomArrowSize = context.getResources().getDimensionPixelSize(R.dimen.ldrawer_topBottomBarArrowSize); this.mBarThickness = context.getResources().getDimensionPixelSize(R.dimen.ldrawer_thickness); this.mBarGap = context.getResources().getDimensionPixelSize(R.dimen.ldrawer_gapBetweenBars); this.mMiddleArrowSize = context.getResources().getDimensionPixelSize(R.dimen.ldrawer_middleBarArrowSize); this.mPaint.setStyle(Paint.Style.STROKE); this.mPaint.setStrokeJoin(Paint.Join.ROUND); this.mPaint.setStrokeCap(Paint.Cap.SQUARE); this.mPaint.setStrokeWidth(this.mBarThickness); } protected float lerp(float paramFloat1, float paramFloat2, float paramFloat3) { return paramFloat1 + paramFloat3 * (paramFloat2 - paramFloat1); } public void draw(Canvas canvas) { Rect localRect = getBounds(); float f1 = lerp(this.mBarSize, this.mTopBottomArrowSize, this.mProgress); float f2 = lerp(this.mBarSize, this.mMiddleArrowSize, this.mProgress); float f3 = lerp(0.0F, this.mBarThickness / 2.0F, this.mProgress); float f4 = lerp(0.0F, ARROW_HEAD_ANGLE, this.mProgress); float f5 = 0.0F; float f6 = 180.0F; float f7 = lerp(f5, f6, this.mProgress); float f8 = lerp(this.mBarGap + this.mBarThickness, 0.0F, this.mProgress); this.mPath.rewind(); float f9 = -f2 / 2.0F; this.mPath.moveTo(f9 + f3, 0.0F); this.mPath.rLineTo(f2 - f3, 0.0F); float f10 = (float) Math.round(f1 * Math.cos(f4)); float f11 = (float) Math.round(f1 * Math.sin(f4)); this.mPath.moveTo(f9, f8); this.mPath.rLineTo(f10, f11); this.mPath.moveTo(f9, -f8); this.mPath.rLineTo(f10, -f11); this.mPath.moveTo(0.0F, 0.0F); this.mPath.close(); canvas.save(); if (!isLayoutRtl()) canvas.rotate(180.0F, localRect.centerX(), localRect.centerY()); canvas.rotate(f7 * mVerticalMirror, localRect.centerX(), localRect.centerY()); canvas.translate(localRect.centerX(), localRect.centerY()); canvas.drawPath(this.mPath, this.mPaint); canvas.restore(); } public int getIntrinsicHeight() { return this.mSize; } public int getIntrinsicWidth() { return this.mSize; } public void setAlpha(int alpha) { this.mPaint.setAlpha(alpha); } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } public abstract boolean isLayoutRtl(); public void setColorFilter(ColorFilter colorFilter) { this.mPaint.setColorFilter(colorFilter); } public void setVerticalMirror(boolean mVerticalMirror) { this.mVerticalMirror = mVerticalMirror ? 1 : -1; } public void setProgress(float paramFloat) { this.mProgress = paramFloat; invalidateSelf(); } public void setColor(int resourceId) { this.mPaint.setColor(context.getResources().getColor(resourceId)); } }
测试代码:
import android.app.ActionBar; import android.app.Activity; import android.content.Intent; import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.support.v4.widget.DrawerLayout; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.ListView; import com.ikimuhendis.ldrawer.ActionBarDrawerToggle; import com.ikimuhendis.ldrawer.DrawerArrowDrawable; public class SampleActivity extends Activity { private DrawerLayout mDrawerLayout; private ListView mDrawerList; private ActionBarDrawerToggle mDrawerToggle; private DrawerArrowDrawable drawerArrow; private boolean drawerArrowColor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sample); ActionBar ab = getActionBar(); ab.setDisplayHomeAsUpEnabled(true); ab.setHomeButtonEnabled(true); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerList = (ListView) findViewById(R.id.navdrawer); drawerArrow = new DrawerArrowDrawable(this) { @Override public boolean isLayoutRtl() { return false; } }; mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, drawerArrow, R.string.drawer_open, R.string.drawer_close) { public void onDrawerClosed(View view) { super.onDrawerClosed(view); invalidateOptionsMenu(); } public void onDrawerOpened(View drawerView) { super.onDrawerOpened(drawerView); invalidateOptionsMenu(); } }; mDrawerLayout.setDrawerListener(mDrawerToggle); mDrawerToggle.syncState(); String[] values = new String[]{ "Stop Animation (Back icon)", "Stop Animation (Home icon)", "Start Animation", "Change Color", "GitHub Page", "Share", "Rate" }; ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values); mDrawerList.setAdapter(adapter); mDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { switch (position) { case 0: mDrawerToggle.setAnimateEnabled(false); drawerArrow.setProgress(1f); break; case 1: mDrawerToggle.setAnimateEnabled(false); drawerArrow.setProgress(0f); break; case 2: mDrawerToggle.setAnimateEnabled(true); mDrawerToggle.syncState(); break; case 3: if (drawerArrowColor) { drawerArrowColor = false; drawerArrow.setColor(R.color.ldrawer_color); } else { drawerArrowColor = true; drawerArrow.setColor(R.color.drawer_arrow_second_color); } mDrawerToggle.syncState(); break; case 4: Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/IkiMuhendis/LDrawer")); startActivity(browserIntent); break; case 5: Intent share = new Intent(Intent.ACTION_SEND); share.setType("text/plain"); share.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); share.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name)); share.putExtra(Intent.EXTRA_TEXT, getString(R.string.app_description) + "n" + "GitHub Page : https://github.com/IkiMuhendis/LDrawern" + "Sample App : https://play.google.com/store/apps/details?id=" + getPackageName()); startActivity(Intent.createChooser(share, getString(R.string.app_name))); break; case 6: String appUrl = "https://play.google.com/store/apps/details?id=" + getPackageName(); Intent rateIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(appUrl)); startActivity(rateIntent); break; } } }); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { if (mDrawerLayout.isDrawerOpen(mDrawerList)) { mDrawerLayout.closeDrawer(mDrawerList); } else { mDrawerLayout.openDrawer(mDrawerList); } } return super.onOptionsItemSelected(item); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mDrawerToggle.syncState(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mDrawerToggle.onConfigurationChanged(newConfig); } }
布局文件:
<android.support.v4.widget.DrawerLayout android:id="@+id/drawer_layout" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="@string/app_description"/> </RelativeLayout> <!-- The navigation drawer --> <ListView android:id="@+id/navdrawer" android:layout_width="@dimen/navdrawer_width" android:layout_height="match_parent" android:layout_gravity="start" android:background="@android:color/white" android:choiceMode="singleChoice" android:divider="@android:color/transparent" android:dividerHeight="0dp" android:drawSelectorOnTop="false"> </ListView> </android.support.v4.widget.DrawerLayout>
注意:如果是自己导入已有项目,复制图片时可能复制到的文件夹不是drawable(而是 R.mipmap.ic_drawer),那么 R.drawable.ic_drawer会报错找不到R