这篇文章是实现Material 风格的INSTAGRAM 系列文章第第四部分。今天,我们将为新闻的item创建一个从“motre”按钮打开的上下文菜单。大约是视频18 到 20 秒之间的内容。
下面是今天所要达到的效果(分别是Lollipop以及Lollipop之前的效果):
视频暂略
先热身
在我们开始菜单的实现之前,我们先重构以下代码。
Riyaz在评论中指出MainActivity
和CommentsActivity
中的Toolbar是完全一样的,因此可以单独新建一个布局,使用<include />
标签来导入以达到重用的效果。
重构之后大概长这样。这个新建的布局文件在res/layout/view_feed_toolbar.xml
中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/tools" android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:elevation="@dimen/default_elevation" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <ImageView android:id="@+id/ivLogo" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:scaleType="center" android:src="@drawable/img_toolbar_logo" /> </android.support.v7.widget.Toolbar> |
现在我们只需在activity_main.xml
和activity_comments.xml
中如下使用它就可以了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!--...--> <include android:id="@+id/toolbar" layout="@layout/view_feed_toolbar" /> <!--...--> </RelativeLayout> |
值得一提的是我们可以在<include />
标签中重写一些属性(重写将会覆盖被包含文件中根视图的相关属性),就如上面已经重写了的android:id
属性。(顺便说下这里Toolbar需要放在RelativeLayout
中,ps:真啰嗦啊,说了几次了。)
这里是 提交 的重构代码。
上下文菜单
准备工作
在开始代码之前我们先做一些准备工作,下面是期望的效果截图:
首先,在item_feed.xml
中添加一个按钮,并处理其onClick()
事件。这不难,只要将以前的一些代码拷贝过来,再添加一个三个圆点的图片(我用的是从官方Material Design图标包中弄来的 这个图标 )。这里是 提交 的这些更改的代码。
上下文菜单(Context menu)的布局
让我们从view的布局开始吧,我们再一次使用<merge />
标签,然后在xml和java代码中构建
res/layout/view_context_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 |
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android"> <Button android:id="@+id/btnReport" style="@style/ContextMenuButton" android:text="REPORT" android:textColor="@color/btn_context_menu_text_red" /> <Button android:id="@+id/btnSharePhoto" style="@style/ContextMenuButton" android:text="SHARE PHOTO" /> <Button android:id="@+id/btnCopyShareUrl" style="@style/ContextMenuButton" android:text="COPY SHARE URL" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#eeeeee" /> <Button android:id="@+id/btnCancel" style="@style/ContextMenuButton" android:text="CANCEL" /> </merge> |
其实就是四个共用如下样式的按钮:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8"?> <!-- styles.xml--> <resources> <!--...--> <style name="ContextMenuButton"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:background">@drawable/btn_context_menu</item> <item name="android:gravity">left|center_vertical</item> <item name="android:paddingLeft">20dp</item> <item name="android:paddingRight">20dp</item> <item name="android:textColor">?attr/colorPrimary</item> <item name="android:textSize">14sp</item> </style> </resources> |
很简单吧,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 |
public class FeedContextMenu extends LinearLayout { private static final int CONTEXT_MENU_WIDTH = Utils.dpToPx(240); private int feedItem = -1; private OnFeedContextMenuItemClickListener onItemClickListener; public FeedContextMenu(Context context) { super(context); init(); } private void init() { LayoutInflater.from(getContext()).inflate(R.layout.view_context_menu, this, true); setBackgroundResource(R.drawable.bg_container_shadow); setOrientation(VERTICAL); setLayoutParams(new LayoutParams(CONTEXT_MENU_WIDTH, ViewGroup.LayoutParams.WRAP_CONTENT)); } public void bindToItem(int feedItem) { this.feedItem = feedItem; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); ButterKnife.inject(this); } public void dismiss() { ((ViewGroup) getParent()).removeView(FeedContextMenu.this); } @OnClick(R.id.btnReport) public void onReportClick() { |