Android 优秀UI控件 ---- FlowingDrawer
1,前天在git上看到了一个不错的控件 ,最近两天项目也没有那么赶了,就抽时间来写写代码,锻炼一下手感,先看一下效果吧。
2 整体来看 ,主要是有两块来实现的,①主界面的RecyclerView ,②菜单栏的LeftDrawerLayout ,
先来将这个控件引到项目中 ,在build.gradle加入以下代码
1 2 | compile 'com.mxn.soul:flowingdrawer-core:1.2.2' compile 'com.nineoldandroids:library:2.4.0' |
主界面的布局activity.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | <?xml version= "1.0" encoding= "utf-8" ?> <com.mxn.soul.flowingdrawer_core.LeftDrawerLayout android:id= "@+id/lf_drawerlayout" xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:app= "http://schemas.android.com/apk/res-auto" android:layout_width= "match_parent" android:layout_height= "match_parent" android:clipChildren= "false" > <!-- android:clipChildren= "false" 这个属性是不限制子控件在其范围内--> <android.support.design.widget.CoordinatorLayout android:id= "@+id/coordinatorLayout" android:layout_width= "match_parent" android:layout_height= "match_parent" android:orientation= "vertical" > <android.support.v7.widget.RecyclerView android:id= "@+id/recyclerView" android:layout_width= "match_parent" android:layout_height= "match_parent" android:scrollbars= "none" app:layout_behavior= "@string/appbar_scrolling_view_behavior" /> <android.support.design.widget.AppBarLayout android:id= "@+id/appBarLayout" android:layout_width= "match_parent" android:layout_height= "wrap_content" > <include android:id= "@+id/toolbar" layout= "@layout/toolbar" /> </android.support.design.widget.AppBarLayout> </android.support.design.widget.CoordinatorLayout> <!--menu--> <RelativeLayout android:layout_width= "280dp" android:layout_height= "match_parent" android:layout_gravity= "start" android:clipChildren= "false" > <com.mxn.soul.flowingdrawer_core.FlowingView android:id= "@+id/flowingView" android:layout_width= "match_parent" android:layout_height= "match_parent" /> <!--FlowingView 是弹出的那多余的那一块--> <FrameLayout android:id= "@+id/frame_container_menu" android:layout_width= "match_parent" android:layout_height= "match_parent" android:layout_alignParentLeft= "true" android:layout_marginRight= "25dp" android:paddingRight= "10dp" /> </RelativeLayout> </com.mxn.soul.flowingdrawer_core.LeftDrawerLayout> |
toolbar.xml 代码
1 2 3 4 5 6 7 8 9 10 11 | <?xml version= "1.0" encoding= "utf-8" ?> <android.support.v7.widget.Toolbar android:id= "@+id/toolbar" xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:app= "http://schemas.android.com/apk/res-auto" android:layout_width= "match_parent" android:layout_height= "?attr/actionBarSize" android:background= "?attr/colorPrimary" app:elevation= "@dimen/default_elevation" app:layout_scrollFlags= "scroll|enterAlways" app:theme= "@style/ThemeOverlay.AppCompat.Dark.ActionBar" > </android.support.v7.widget.Toolbar> |
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | package wangjitao.com.flowingdrawerdemo; import android.content.Context; import android.support.v4.app.FragmentManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import com.mxn.soul.flowingdrawer_core.FlowingView; import com.mxn.soul.flowingdrawer_core.LeftDrawerLayout; public class MainActivity extends AppCompatActivity { private Context mContext = MainActivity. this ; private RecyclerView mRecyclerView ; private LeftDrawerLayout mLeftDrawerLayout ; private FlowingView mFlowingView ; private MyFeedAdapter mMyFeedAdapter ; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); setupToolbar(); initView(); } private void initView() { mLeftDrawerLayout = (LeftDrawerLayout) findViewById(R.id.lf_drawerlayout); //用于设置左边的drawlayout FragmentManager mFragmentManager = getSupportFragmentManager() ; MyMenuFragment mMenuFragment = (MyMenuFragment) mFragmentManager.findFragmentById(R.id.frame_container_menu); mFlowingView = (FlowingView) findViewById(R.id.flowingView); if (mMenuFragment == null ) { mFragmentManager.beginTransaction().add(R.id.frame_container_menu, mMenuFragment = new MyMenuFragment()).commit(); } mLeftDrawerLayout.setFluidView(mFlowingView); mLeftDrawerLayout.setMenuFragment(mMenuFragment); mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView); mRecyclerView.setLayoutManager( new LinearLayoutManager( this ) { @Override protected int getExtraLayoutSpace(RecyclerView.State state) { return 300 ; } }); mMyFeedAdapter = new MyFeedAdapter(mContext); mRecyclerView.setAdapter(mMyFeedAdapter); } private void setupToolbar() { Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); toolbar.setNavigationIcon(R.mipmap.ic_menu_white); toolbar.setNavigationOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mLeftDrawerLayout.toggle(); } }); } @Override public void onBackPressed() { if (mLeftDrawerLayout.isShownMenu()){ mLeftDrawerLayout.closeDrawer(); } else { super .onBackPressed(); } } } |
再看看我们关键的自定义的FragmentLayout
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | package wangjitao.com.flowingdrawerdemo; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.design.widget.NavigationView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.Toast; import com.mxn.soul.flowingdrawer_core.MenuFragment; import com.squareup.picasso.Picasso; public class MyMenuFragment extends MenuFragment { private ImageView ivMenuUserProfilePhoto; @Override public void onCreate( @Nullable Bundle savedInstanceState) { super .onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_menu, container, false ); NavigationView mNavigationView = (NavigationView) view.findViewById(R.id.vNavigation) ; ivMenuUserProfilePhoto = (ImageView) mNavigationView.getHeaderView( 0 ).findViewById(R.id .ivMenuUserProfilePhoto); setupHeader(); return setupReveal(view) ; } private void setupHeader() { int avatarSize = getResources().getDimensionPixelSize(R.dimen.global_menu_avatar_size); String profilePhoto = getResources().getString(R.string.user_profile_photo); Picasso.with(getActivity()) .load(profilePhoto) .placeholder(R.drawable.img_circle_placeholder) .resize(avatarSize, avatarSize) .centerCrop() .transform( new CircleTransformation()) .into(ivMenuUserProfilePhoto); } public void onOpenMenu(){ } public void onCloseMenu(){ } } |
菜单栏中的布局文件fragment_menu.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <RelativeLayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:app= "http://schemas.android.com/apk/res-auto" android:layout_width= "match_parent" android:layout_height= "match_parent" > <android.support.design.widget.NavigationView android:id= "@+id/vNavigation" android:layout_width= "wrap_content" android:layout_height= "match_parent" android:layout_gravity= "start" android:background= "@android:color/transparent" app:headerLayout= "@layout/menu_header" app:itemIconTint= "#8b8b8b" app:itemTextColor= "#666666" app:menu= "@menu/drawer_menu" /> </RelativeLayout> |
menu_head.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | <?xml version= "1.0" encoding= "utf-8" ?> <FrameLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width= "match_parent" android:layout_height= "wrap_content" android:background= "@android:color/transparent" android:clickable= "true" > <LinearLayout android:id= "@+id/vGlobalMenuHeader" android:layout_width= "match_parent" android:layout_height= "wrap_content" > <ImageView android:id= "@+id/ivMenuUserProfilePhoto" android:layout_width= "@dimen/global_menu_avatar_size" android:layout_height= "@dimen/global_menu_avatar_size" android:layout_margin= "12dp" /> <TextView android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_gravity= "center" android:layout_weight= "1" android:text= "阿呆哥哥" android:textColor= "#2d5d82" android:textSize= "16sp" android:textStyle= "bold" /> <ImageButton android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_gravity= "center_vertical" android:layout_margin= "16dp" android:background= "@android:color/transparent" android:src= "@mipmap/ic_global_menu_search" /> </LinearLayout> <View android:layout_width= "match_parent" android:layout_height= "1dp" android:layout_gravity= "bottom" android:background= "#dddddd" /> </FrameLayout> |
看一下menu_head的截图
drawer_menu.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <menu xmlns:android= "http://schemas.android.com/apk/res/android" > <group android:id= "@+id/menu_group_1" > <item android:id= "@+id/menu_feed" android:icon= "@mipmap/ic_global_menu_feed" android:title= "My Feed" /> <item android:id= "@+id/menu_direct" android:icon= "@mipmap/ic_global_menu_direct" android:title= "Instagram Direct" /> <item android:id= "@+id/menu_news" android:icon= "@mipmap/ic_global_menu_news" android:title= "News" /> <item android:id= "@+id/menu_popular" android:icon= "@mipmap/ic_global_menu_popular" android:title= "Popular" /> <item android:id= "@+id/menu_photos_nearby" android:icon= "@mipmap/ic_global_menu_nearby" android:title= "Photos Nearby" /> <item android:id= "@+id/menu_photo_you_liked" android:icon= "@mipmap/ic_global_menu_likes" android:title= "Photos You've Liked" /> </group> <group android:id= "@+id/menu_group_2" > <item android:id= "@+id/menu_settings" android:title= "Settings" /> <item android:id= "@+id/menu_about" android:title= "About" /> </group> </menu> |
到这里基本上的模型就出来了,看效果 :
加上制作用户头像的圆形制作的CircleTransformation.class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | package wangjitao.com.flowingdrawerdemo; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import com.squareup.picasso.Transformation; public class CircleTransformation implements Transformation { private static final int STROKE_WIDTH = 6 ; @Override public Bitmap transform(Bitmap source) { int size = Math.min(source.getWidth(), source.getHeight()); int x = (source.getWidth() - size) / 2 ; int y = (source.getHeight() - size) / 2 ; Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size); if (squaredBitmap != source) { source.recycle(); } Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig()); Canvas canvas = new Canvas(bitmap); Paint avatarPaint = new Paint(); BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP); avatarPaint.setShader(shader); Paint outlinePaint = new Paint(); outlinePaint.setColor(Color.WHITE); outlinePaint.setStyle(Paint.Style.STROKE); outlinePaint.setStrokeWidth(STROKE_WIDTH); outlinePaint.setAntiAlias( true ); float r = size / 2f; canvas.drawCircle(r, r, r, avatarPaint); canvas.drawCircle(r, r, r - STROKE_WIDTH / 2 , outlinePaint); squaredBitmap.recycle(); return bitmap; } @Override public String key() { return "circleTransformation()" ; } } |
再加上RecyclerView的Adapter,基本上就成功了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | package wangjitao.com.flowingdrawerdemo; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextSwitcher; import android.widget.TextView; /** * Created by wangjitao on 2016/4/14. */ public class MyFeedAdapter extends RecyclerView.Adapter<MyFeedAdapter.MyFeedViewHolder> { private Context context; private int likeCount = 123 ; public MyFeedAdapter(Context context) { this .context = context; } @Override public MyFeedViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(context).inflate(R.layout.item_recyclerview, parent, false ); return new MyFeedViewHolder(view); } @Override public void onBindViewHolder( final MyFeedViewHolder holder, int position) { if (position % 2 == 0 ) { holder.ivFeedCenter.setImageResource(R.mipmap.img_feed_sakura); holder.ivFeedBottom.setImageResource(R.mipmap.img_feed_bottom_1); } else { holder.ivFeedCenter.setImageResource(R.mipmap.img_feed_water); holder.ivFeedBottom.setImageResource(R.mipmap.img_feed_bottom_2); } holder.btnComments.setTag(position); holder.btnMore.setTag(position); holder.ivFeedCenter.setTag(holder); holder.btnLike.setTag(holder); holder.iv_likes.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { holder.tv_likes_count.setText((++likeCount)+ " likes" ); } }); } @Override public int getItemCount() { return 10 ; } class MyFeedViewHolder extends RecyclerView.ViewHolder { ImageView ivFeedCenter; ImageView ivFeedBottom; ImageButton btnComments; ImageButton btnLike; ImageButton btnMore; TextSwitcher tsLikesCounter; ImageView ivUserProfile; FrameLayout vImageRoot; ImageView iv_likes; TextView tv_likes_count ; public MyFeedViewHolder(View view) { super (view); ivFeedCenter = (ImageView) view.findViewById(R.id.ivFeedCenter); ivFeedBottom = (ImageView) view.findViewById(R.id.ivFeedBottom); btnComments = (ImageButton) view.findViewById(R.id.btnComments); btnLike = (ImageButton) view.findViewById(R.id.btnLike); btnMore = (ImageButton) view.findViewById(R.id.btnMore); tsLikesCounter = (TextSwitcher) view.findViewById(R.id.tsLikesCounter); ivUserProfile = (ImageView) view.findViewById(R.id.ivUserProfile); vImageRoot = (FrameLayout) view.findViewById(R.id.vImageRoot); iv_likes = (ImageView) view.findViewById(R.id.iv_likes); tv_likes_count = (TextView) view.findViewById(R.id.tv_likes_count); } } } |
项目下载地址:点击下载(嘿嘿嘿)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步