问题
Background
I have an action item that's not quite standard. It has its own layout, because I've failed to create a nice Drawable for it (written about it here).
Basically, it's just a TextView with a background that wraps its short text that it shows.
The problem
Sadly I can't find a way of fully mimic it to look like normal ones:
- The ripple effect (and probably the simple clicking effect on older versions too) doesn't have the same color and size.
- There isn't a toast for when I long click on it
- Maybe other things I haven't noticed?
Here are screenshots to demonstrate the differences:
The new, non standard, action item:
A native action item:
What I've tried
For the color of the ripple effect, I think I can use "colorControlHighlight", but I can't find out which color is the one used by default, correctly. I've looked inside the "values.xml" file of the support library, and noticed that it's "ripple_material_dark" color (or "ripple_material_light", in case the toolbar is supposed to be white) , but this seems a bit like a hack.
Not sure about the size, but looking at the layout inspector, I think the view has padding:
I've also noticed that the view class name of the toolbar is ActionMenuItemView
. I tried to look at its code (probably avaialble online too, here) , but didn't notice anything mentioned there about background. For padding I think it just tries to put the icon in the middle:
Anyway, this is the current code of the POC:
MainActivity.kt
class MainActivity : AppCompatActivity() {
lateinit var goToTodayView: View
lateinit var goToTodayTextView: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
goToTodayView = LayoutInflater.from(this).inflate(R.layout.go_to_today_action_item, toolbar, false)
goToTodayTextView = goToTodayView.goToTodayTextView
goToTodayTextView.setBackgroundDrawable(AppCompatResources.getDrawable(this, R.drawable.ic_backtodate))
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menu.add("goToToday").setActionView(goToTodayView).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
menu.add("asd").setIcon(R.drawable.abc_ic_menu_copy_mtrl_am_alpha).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) //for comparison
return super.onCreateOptionsMenu(menu)
}
}
go_to_today_action_item.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:background="?attr/selectableItemBackgroundBorderless" android:backgroundTint="#fff" android:clickable="true"
android:focusable="true">
<TextView
android:id="@+id/goToTodayTextView" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:gravity="center" android:text="1"
android:textColor="#fff" android:textSize="12dp" tools:background="@drawable/ic_backtodate" tools:layout_gravity="center"/>
</FrameLayout>
The questions
- How do I set the same background as a normal action item?
- How do I put the toast like a normal action item?
- Are there other things that are different between normal action item and one that I set with a layout?
- In other words, is it possible to fully mimic native action items? Maybe using the
ActionMenuItemView
class somehow? Maybe a very different solution from what I tried?
EDIT: for the background of the action items, I made it a bit like the original ones, but it's still not the same. Clicking effect seems a tiny bit different, and I haven't found how to show the toast of the action item upon long clicking on it. Here's the result:
Anyway, here's what I did:
go_to_today_action_item.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="?attr/actionBarSize" android:layout_height="?attr/actionBarSize" android:clickable="true"
android:focusable="true">
<ImageView
android:layout_width="@dimen/action_item_background_size"
android:layout_height="@dimen/action_item_background_size" android:layout_gravity="center"
android:background="@drawable/action_item_selector" android:duplicateParentState="true"/>
<TextView
android:id="@+id/goToTodayTextView" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:gravity="center" android:text="31" android:textColor="#fff"
android:textSize="12dp" tools:background="@drawable/ic_backtodate" tools:layout_gravity="center"/>
</FrameLayout>
drawable/action_item_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="@color/clicking_semi_white_ripple_color"/>
</shape>
</item>
<item android:drawable="@android:color/transparent"/>
</selector>
drawable-v21/action_item_selector.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/clicking_semi_white_ripple_color">
<item android:id="@android:id/mask">
<shape android:shape="oval">
<solid android:color="@android:color/white"/>
</shape>
</item>
</ripple>
colors.xml
<color name="clicking_semi_white_ripple_color">#33ffffff</color>
values/dimens.xml
<dimen name="action_item_background_size">48dp</dimen>
values-v21/dimens.xml
<dimen name="action_item_background_size">40dp</dimen>
回答1:
The following code will use your layout to populate a standard menu item for the date. As a standard menu item, it will exhibit all the characteristics that you are looking for and should be compatible with future changes to a menu item's behavior.
The basic concept is to inflate the layout with the boxed date and use its drawing cache to create a bitmap that is then used as the drawable for the menu item's icon.
MainActivity.kt
class MainActivity : AppCompatActivity() {
private var goToTodayView: View? = null
private var goToTodayTextView: TextView? = null
private val textDrawable: TextDrawable? = null
private var mOptionsMenu: Menu? = null
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById<View>(R.id.toolbar) as Toolbar)
testWithCustomViews()
}
private fun updateDateView() {
if (mOptionsMenu == null)
return
goToTodayView!!.invalidate()
goToTodayView!!.buildDrawingCache()
val bmp = Bitmap.createBitmap(goToTodayView!!.drawingCache)
val d = BitmapDrawable(resources, bmp)
mOptionsMenu!!.getItem(0).icon = d
}
private fun testWithCustomViews() {
val toolbar = findViewById<View>(R.id.toolbar) as Toolbar
goToTodayView = LayoutInflater.from(this).inflate(R.layout.go_to_today_action_item, toolbar, false)
goToTodayView!!.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED))
goToTodayView!!.layout(0, 0, goToTodayView!!.measuredWidth, goToTodayView!!.measuredHeight)
goToTodayTextView = goToTodayView!!.findViewById(R.id.goToTodayTextView)
goToTodayTextView!!.setBackgroundDrawable(AppCompatResources.getDrawable(this, R.drawable.ic_backtodate))
goToTodayView!!.isDrawingCacheEnabled = true
val handler = Handler()
val runnable = object : Runnable {
internal var i = 0
override fun run() {
if (isFinishing || isDestroyed)
return
goToTodayTextView!!.text = (i + 1).toString()
i = (i + 1) % 31
updateDateView()
handler.postDelayed(this, 1000)
}
}
runnable.run()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
mOptionsMenu = menu
menu.add("goToToday").setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
updateDateView()
menu.add("asd").setIcon(R.drawable.abc_ic_menu_copy_mtrl_am_alpha).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
return super.onCreateOptionsMenu(menu)
}
}
Since go_to_today_action_item.xml
now doesn't need the extra views to mimic standard menu item behavior, it can be stripped down. In fact, the menu item icon appears too small without adjustments. Change go_to_today_action_item.xml
to the following:
<TextView
android:id="@+id/goToTodayTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/ic_backtodate"
android:gravity="center"
android:text="31"
android:textColor="#fff"
android:textSize="12dp"
tools:layout_gravity="center" />
来源:https://stackoverflow.com/questions/47697998/how-to-fully-mimic-action-item-view-in-the-toolbar-for-a-customized-one