Menu shows when it shouldn't as I set it false - java

I've encountered another problem with my app. When the cat dies, I hit the "results screen" (it isn't a new activity but I hide all current elements and show a new text view indicating the death cause), and I want to hide the menu items, but for some reason it's not responding to isHeDead().
Basically the problem seems to be that it doesn't see "return false" inside onCreateOptionsMenu because for some reason isHeDead() isn't working there, even though the method works everywhere else.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(fab_menu, menu);
while (!isHeDead()){
return true;
}
return false;
}
public Boolean isHeDead() {
TextView t = (TextView) findViewById(R.id.textDiedOf);
TextView textName = (TextView) findViewById(R.id.CatsTitleStats);
TextView textAge = (TextView) findViewById(R.id.CatsAgeStat);
TextView textStats1 = (TextView) findViewById(R.id.CatsStats);
TextView textStats2 = (TextView) findViewById(R.id.CatsStats2);
ImageView image = (ImageView) findViewById(R.id.imageViewCat);
if (cat.getAge() >= 20) {
textName.setVisibility(View.GONE);
textAge.setVisibility(View.GONE);
textStats1.setVisibility(View.GONE);
textStats2.setVisibility(View.GONE);
image.setVisibility(View.GONE);
t.setText("Sorry! " + getIntent().getStringExtra(KEY_NAME_EXTRA) + " died of old age.");
return true;
} else if (cat.getAnger() >= 10) {
textName.setVisibility(GONE);
textAge.setVisibility(View.GONE);
textStats1.setVisibility(View.GONE);
textStats2.setVisibility(View.GONE);
image.setVisibility(View.GONE);
t.setText("Sorry! " + getIntent().getStringExtra(KEY_NAME_EXTRA) + " died of madness.");
return true;
} ///etc...
}
User options (not sure if this has anything to do with the menu problem but still).
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
/// FEED ///
case R.id.action_feed:
int qualityRandom = (int) (Math.random() * 10);
if (qualityRandom == 5) {
cat.happy(-2);
cat.healthy(-30);
cat.angry(2);
cat.thirsty(2);
ageStat();
Stats1();
Stats2();
if (isHeDead()) {
break;
} else {
Toast.makeText(CatStatus.this, "Food was in a poor state...", Toast.LENGTH_SHORT).show();
break;
}
} else {
cat.happy(1);
cat.healthy(10);
cat.hungry(-3);
cat.angry(-1);
ageStat();
Stats1();
Stats2();
Toast.makeText(CatStatus.this, "Yummy!", Toast.LENGTH_SHORT).show();
break;
}
/// DRINK ///
case R.id.action_drink: ///etc...

When you hit results screen, if you are not going to a new activity, onCreateOptionsMenu is not being called!
You need to keep a reference to your menu:
private Menu myMenu;
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(fab_menu, menu);
this.myMenu = menu;
while (!isHeDead()){
return true;
}
return false;
}
And then, you can call inside your isHeDead() method like this:
menu.setGroupVisible(R.id.main_menu_group, false);
or:
menu.clear();
It depends on what you want.
Check this answer:
Hide/Show Action Bar Option Menu Item for different fragments

onCreateOptionsMenu is called only one time when the app launch activity

Related

mend.findItem explanation and confusion

I'm new to android development and kinda to Java as well.
I'm learning how to add buttons to actionbar - everything is working, but I don't understand few things.
//Showing small icons at actionbar
#Override
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
menuItem = menu.findItem(R.id.recBin); // Finds the button in Actionbar and gets the ID
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.recBin: // Actions for delete button
dbHandler.remove(getID());
displayTaskList();
menuItem.setVisible(false); // Hide the button
break;
case R.id.editBtn: // Actions for editbutton
Toast.makeText(MainActivity.this,
"EDIT", Toast.LENGTH_LONG).show();
break;
case R.id.closeBtn:
Toast.makeText(MainActivity.this,
"CLOSE", Toast.LENGTH_LONG).show();
break;
default:
break;
}
return true;
}
This line: menuItem = menu.findItem(R.id.recBin); Is for what exactly? I took it off and my app crashed, so I understand that it's mandatory. What I don't understand is what icons ID should I put at bold space? It has to be from "menu" right, but does it matter which id I take? For instance, if I took R.id.closeBtn instead of recBin? As long as it's an id from menu, it works?
P.S. I hope this isn't a terrible question [probably is] and I'm sorry if so.
Solution:
Turns out you can simply get ID's. Stupid and simple.
private MenuItem item1, item2, item3;
//Showing small icons at actionbar
#Override
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
item1 = menu.findItem(R.id.recBin); // Rec button
item2 = menu.findItem(R.id.editBtn); // Edit button
item3 = menu.findItem(R.id.closeBtn); // Close button
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.recBin: // Actions for delete button
dbHandler.remove(getID());
displayTaskList();
item1.setVisible(false); item2.setVisible(false); item3.setVisible(false); // Hiding all buttons
break;
case R.id.editBtn: // Actions for editbutton
item1.setVisible(false); item2.setVisible(false); item3.setVisible(false); // Hiding all buttons
break;
case R.id.closeBtn:
item1.setVisible(false); item2.setVisible(false); item3.setVisible(false); // Hiding all buttons
break;
default:
break;
}
return true;
}
It's a reference to MenuItem, but it would be easier if you do:
case R.id.recBin: // Actions for delete button
dbHandler.remove(getID());
displayTaskList();
item.setVisible(false); // Hide the button
break;
You can safely remove the reference afterwards

Android TextView actionbar works inconsistently

I have an app about studying sacred Indian texts usually consisting of a verse and a commentary to this verse.
To open it up I use DisplayText activity which has an ActionBar popping up when user selects some text from either a verse or its commentary.
My problem is that it works inconsistently - on my Samsung Galaxy Note 2 it works OK, but on sony xperia Z2 once I try to touch the action button it exits the action bar and nothing happens.
Samsung's Android version is 4.4.2 and Sony's version 4.4.4
Please check out this very short video for Sony device and also how it works for samsung device
Please note that there are no error messages being shown in the LogCat view.
I would appreciate any suggestions on how I could possibly fix this problem
Also any ways to get a work around would be much appreciated as well.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Log.v("DEBUG", "DisplaTEXT onCreate - Starting Activity");
try
{
m_context=this;
mtxtTransl2View.setCustomSelectionActionModeCallback(new CustomTextSelectCallback(mtxtTransl2View, false));
mtxtComment.setCustomSelectionActionModeCallback(new CustomTextSelectCallback(mtxtComment, true));
}
catch(Exception e)
{
e.printStackTrace();
}
}
#SuppressLint("NewApi")
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
class CustomTextSelectCallback implements ActionMode.Callback {
public CustomTextSelectCallback(TextView tv, boolean b) {
mTextView=tv;
mbPurport=b;
}
//flag that selection is made in the purport, otherwise it is in shloka or translit
private TextView mTextView;
private boolean mbPurport;
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
//Log.d(TAG, "onCreateActionMode");
//if(mbPurport)
{
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.text_selection_menu, menu);
MenuItem item = menu.findItem(R.id.cab_menu_fb);
ShareActionProvider actionProvider = (ShareActionProvider)item.getActionProvider();
actionProvider.setShareIntent(createShareIntent());
actionProvider.setOnShareTargetSelectedListener(new OnShareTargetSelectedListener(){
public boolean onShareTargetSelected(ShareActionProvider source, Intent intent)
{
try
{
getShareSubject("Share Subject","Please describe why would you like to share this (optional):");
}
catch(Throwable e)
{
String err="Error11: " + e.getMessage();
Toast.makeText(getApplicationContext(), err, Toast.LENGTH_LONG).show();
}
if(mShareSubj.equals(SUBJ_CANCEL)) return false;
int start = mTextView.getSelectionStart();
int end = mTextView.getSelectionEnd();
int tvID=mTextView.getId();
String sPlaceType = (tvID==R.id.textTransl2) ? "t":"p";
mTextURL=mTextURL+"?t="+sPlaceType+"&s="+start+"&e="+end;
mANText=mTextView.getText().subSequence(start, end).toString();
if ("com.facebook.katana".equals(intent.getComponent().getPackageName()) )
{
//mfacebooksharer.shareStatus(subject, text);
// Toast.makeText(this, "Facebook sharing", Toast.LENGTH_LONG).show();
shareOnFacebook();
return false;
}
else
{
if(!MyApp.mC.hasFlag(Cookies.FL_Sharing, m_context))
return true;
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(android.content.Intent.EXTRA_TEXT, getShareBody(intent));
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, mShareSubj);
getApplicationContext().startActivity(intent);
return true;
}
}
});
}
return true;
}
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
//Log.d(TAG, String.format("onActionItemClicked item=%s/%d", item.toString(), item.getItemId()));
int start = mTextView.getSelectionStart();
int end = mTextView.getSelectionEnd();
long note_id=-1;
mANPlace=UserDataSQLHelper.NOTE_PLACE_TEXT;
mANText=mTextView.getText().subSequence(start, end).toString();
if(mbPurport)
mANPlace=UserDataSQLHelper.NOTE_PLACE_COMM;
mANStartPos=start;
mANEndPos=end;
mScrollPos = mScrollT.getScrollY();
switch(item.getItemId()) {
case R.id.cab_menu_fav:
if(!MyApp.mC.hasFlag(Cookies.FL_TextHighlight, m_context)) return false;
note_id=MyApp.mUserDB.addNote(m_dbtype, m_dblang, mCurrBookID, mCurrSong, mCurrChapterNum, mCurrTextNum, mRowID, UserDataSQLHelper.NOTE_TYPE_HIGHL, mANPlace, start, end, mScrollPos,
mANText, "", "");
break;
case R.id.cab_menu_comment:
if(!MyApp.mC.hasFlag(Cookies.FL_TextHighlightAddCommentsQuestions, m_context)) return false;
Intent intent = new Intent(getApplicationContext(), NoteEditor.class);
intent.putExtra("NOTEEDIT_ACTION", NoteEditor.ACTION_ADD);
intent.putExtra("NOTEEDIT_TITLE", "Add Question or Note");
startActivityForResult(intent, SUBACT_ADDEDITNOTE);
break;
}
if (note_id!=-1){
ReloadText();
AddTags(note_id);
}
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
}
Text selection menu xml code is here:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/cab_menu_fb"
android:orderInCategory="10"
android:showAsAction="always"
android:icon="#drawable/cab_facebook"
android:actionProviderClass="android.widget.ShareActionProvider"
android:title="#string/cab_menu_fb"/>
<item
android:id="#+id/cab_menu_fav"
android:orderInCategory="20"
android:showAsAction="ifRoom"
android:icon="#drawable/cab_highl"
android:title="#string/cab_menu_fav"/>
<item
android:id="#+id/cab_menu_comment"
android:orderInCategory="30"
android:showAsAction="ifRoom"
android:icon="#drawable/cab_comment"
android:title="#string/cab_menu_comment"/>
</menu>

Changing a Menu Item Icon during run time

How can I change an Menu Item icon during run time according to an If statement ? This is the code that I have and it results in a crash.
public boolean onPrepareOptionsMenu(Menu Item) {
if (favorite == true){
itema = (MenuItem) findViewById(R.id.action_search);
itema.setIcon(R.drawable.ic_action_importants);
}
return true;
}
You are calling the Activity's findViewById, you should have more luck by calling Menu findItem.
public boolean onPrepareOptionsMenu(Menu menu)
{
MenuItem myMenuItem = menu.findItem(R.id.myMenuItemId);
myMenuItem.setIcon(R.drawable.ic_myAction);
return true;
}

How to use onClickListener and onMenuSelectListener in mainactivity?

Hello im trying to use onclicklistener along with onmenuselectlistener in my mainactivity class and the program runs but selecting the popup menu opions dont work they wont set the text to want it want anyone have any idea's? I know i did not implement onMenuSelectListener and maybe thats my problem if it is is there any other way to makes this work?
Here is my code:
public class MainActivity extends Activity implements OnClickListener {
// init variables
Handler uiHandler;
EditText cl;
TextView info;
Button enter;
Button line;
Button arc;
DrawingUtils callDU = new DrawingUtils();
DrawingTools callDT = new DrawingTools();
EditTools callET = new EditTools();
Conversion callConversion = new Conversion();
GLSurfaceView mGLSurface;
String Tag = "Debug";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLSurface = new GLSurfaceView(this);
mGLSurface.setRenderer(new BasicRenderer());
setContentView(R.layout.canvas);
FrameLayout v = (FrameLayout) findViewById(R.id.canvas);
v.addView(mGLSurface);
// init views and buttons
info = (TextView) findViewById(R.id.info);
enter = (Button) findViewById(R.id.enter);
line = (Button) findViewById(R.id.line);
arc = (Button) findViewById(R.id.arc);
cl = (EditText) findViewById(R.id.cl);
/*
* Handler for Main Thread uiHandler = new Handler() { public void
* handleMessage(Message msg) { switch (msg.what) {
*
* } Bundle bundle = msg.getData(); String string1 =
* bundle.getString("P1Key"); String string2 =
* bundle.getString("P2Key"); info.setText(string1);
* info.setText(string2); } };
*/
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.enter:
break;
case R.id.line:
break;
case R.id.arc:
break;
}
};
public void CreatePopupMenu(View v) {
PopupMenu mypopupmenu = new PopupMenu(this, v);
MenuInflater inflater = mypopupmenu.getMenuInflater();
inflater.inflate(R.menu.filemenu, mypopupmenu.getMenu());
mypopupmenu.show();
}
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.newCanas:
info.setText("New");
Log.d(Tag, "New was clicked");
break;
case R.id.open:
break;
case R.id.save:
break;
}
return super.onMenuItemSelected(featureId, item);
}
}
It doesn't look like you're attaching onClickListeners to anything. What that means is you're saying "whenever the onClick event is fired with me as the target, perform this action". But then you're never making yourself a target. Try adding the following code to your onCreate.
arc.setOnClickListener(this);
line.setOnClickListener(this);
enter.setOnClickListener(this);
The same thing happens with the PopupMenu it appears. Try adding mypopupmenu.addOnMenuItemSelectListener(this) right after you inflate the layout for your menu.
Jonathan is right. You should add .setOnClickListener(this); to each of the buttons added after you create them.
For the menu items though, you have to do the following:
1) Create a layout with the items on your menu and store it in your res/menu/ directory.
Example:
main.xml
<item
android:id="#+id/action_settings"
android:orderInCategory="100"
android:showAsAction="never"
android:title="#string/action_settings"/>
</menu>
2) Override the method called: onCreateOptionsMenu() to populate the items in the menu.
Example:
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
3) Override the method onOptionsItemSelected() to do whatever you want with a switch like you were doing with the actionListeners.
4) Additionally, you could also override the method onPrepareOptionsMenu() which is the same as the previous one, but it is called every time the menu opens.
Good luck

How to change menu item text dynamically in Android

I'm trying to change the title of a menu item from outside of the onOptionsItemSelected(MenuItem item) method.
I already do the following;
public boolean onOptionsItemSelected(MenuItem item) {
try {
switch(item.getItemId()) {
case R.id.bedSwitch:
if(item.getTitle().equals("Set to 'In bed'")) {
item.setTitle("Set to 'Out of bed'");
inBed = false;
} else {
item.setTitle("Set to 'In bed'");
inBed = true;
}
break;
}
} catch(Exception e) {
Log.i("Sleep Recorder", e.toString());
}
return true;
}
however I'd like to be able to modify the title of a particular menu item outside of this method.
I would suggest keeping a reference within the activity to the Menu object you receive in onCreateOptionsMenu and then using that to retrieve the MenuItem that requires the change as and when you need it. For example, you could do something along the lines of the following:
public class YourActivity extends Activity {
private Menu menu;
private String inBedMenuTitle = "Set to 'In bed'";
private String outOfBedMenuTitle = "Set to 'Out of bed'";
private boolean inBed = false;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
// Create your menu...
this.menu = menu;
return true;
}
private void updateMenuTitles() {
MenuItem bedMenuItem = menu.findItem(R.id.bedSwitch);
if (inBed) {
bedMenuItem.setTitle(outOfBedMenuTitle);
} else {
bedMenuItem.setTitle(inBedMenuTitle);
}
}
}
Alternatively, you can override onPrepareOptionsMenu to update the menu items each time the menu is displayed.
As JxDarkAngel suggested, calling this from anywhere in your Activity,
invalidateOptionsMenu();
and then overriding:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.bedSwitch);
if (item.getTitle().equals("Set to 'In bed'")) {
item.setTitle("Set to 'Out of bed'");
inBed = false;
} else {
item.setTitle("Set to 'In bed'");
inBed = true;
}
return super.onPrepareOptionsMenu(menu);
}
is a much better choice. I used the answer from https://stackoverflow.com/a/17496503/568197
you can do this create a global "Menu" object then assign it in onCreateOptionMenu
public class ExampleActivity extends AppCompatActivity
Menu menu;
then assign here
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
this.menu = menu;
return true;
}
Then later use assigned Menu object to get required items
menu.findItem(R.id.bedSwitch).setTitle("Your Text");
Create a setOptionsTitle() method and set a field in your class. Such as:
String bedStatus = "Set to 'Out of Bed'";
...
public void setOptionsTitle(String status)
{
bedStatus = status;
}
Now when the menu gets populated, change the title to whatever your status is:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(bedStatus);
// Return true so that the menu gets displayed.
return true;
}
You better use the override onPrepareOptionsMenu
menu.Clear ();
if (TabActual == TabSelec.Anuncio)
{
menu.Add(10, 11, 0, "Crear anuncio");
menu.Add(10, 12, 1, "Modificar anuncio");
menu.Add(10, 13, 2, "Eliminar anuncio");
menu.Add(10, 14, 3, "Actualizar");
}
if (TabActual == TabSelec.Fotos)
{
menu.Add(20, 21, 0, "Subir foto");
menu.Add(20, 22, 1, "Actualizar");
}
if (TabActual == TabSelec.Comentarios)
{
menu.Add(30, 31, 0, "Actualizar");
}
Here an example
I use this code to costum my bottom navigation item
BottomNavigationView navigation = this.findViewById(R.id.my_bottom_navigation);
Menu menu = navigation.getMenu();
menu.findItem(R.id.nav_wall_see).setTitle("Hello");
Declare your menu field.
private Menu menu;
Following is onCreateOptionsMenu() method
public boolean onCreateOptionsMenu(Menu menu) {
this.menu = menu;
try {
getMenuInflater().inflate(R.menu.menu_main,menu);
} catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "onCreateOptionsMenu: error: "+e.getMessage());
}
return super.onCreateOptionsMenu(menu);
}
Following will be your name setter activity. Either through a button click or through conditional code
public void setMenuName(){
menu.findItem(R.id.menuItemId).setTitle(/*Set your desired menu title here*/);
}
This worked for me.
You can do it like this, and no need to dedicate variable:
Toolbar toolbar = findViewById(R.id.toolbar);
Menu menu = toolbar.getMenu();
MenuItem menuItem = menu.findItem(R.id.some_action);
menuItem.setTitle("New title");
Or a little simplified:
MenuItem menuItem = ((Toolbar)findViewById(R.id.toolbar)).getMenu().findItem(R.id.some_action);
menuItem.setTitle("New title");
It works only - after the menu created.
You can Change Menu Item text using below Code: -
fun showPopup(v: View) {
popup = PopupMenu(context, v)
val inflater = popup?.menuInflater
popup?.setOnMenuItemClickListener(this)
inflater?.inflate(R.menu.menu_main, popup?.menu)
val menu: Menu = popup!!.menu
val item = menu.findItem(R.id.name)
if (item.title.equals("Name")) {
item.title = "Safal Bhatia"
}
}
It seems to me that you want to change the contents of menu inside a local method, and this method is called at any time, whenever an event is occurred, or in the activity UI thread.
Why don't you take the instance of Menu in the global variable in onPrepareOptionsMenu when this is overridden and use in this method of yours. Be sure that this method is called whenever an event is occurred (like button click), or in the activity UI thread, handler or async-task post-execute.
You should know in advance the index of this menu item you want to change. After clearing the menu, you need to inflate the menu XML and update your item's name or icon.
For people that need the title set statically.
This can be done in the AndroidManifest.xml
<activity
android:name=".ActivityName"
android:label="Title Text" >
</activity>
I needed to change the menu icon for the fragment. I altered Charles’s answer to this question a bit for the fragment:
private Menu top_menu;
//...
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
//...
rootview = inflater.inflate(R.layout.first_content,null);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_menu, menu);
this.top_menu = menu;
}
// my procedure
private void updateIconMenu() {
if(top_menu!= null) {
MenuItem nav_undo = top_menu.findItem(R.id.action_undo);
nav_undo.setIcon( R.drawable.back);
}
}
I hit this problem too. In my case I wanted to set the string to
reflect additional information using getString.
As stated above you need to find the correct menuItem in the menu and set it in the onPrepareOptionsMenu method. The solutions above didn't handle the case where the item was in a sub menu and for this you need to search the submenu for the item. I wrote a little Kotlin recursive function to allow me to this for multiple items. Code below...
override fun onPrepareOptionsMenu(menu: Menu) {
...
menu.menuSetText(R.id.add_new_card,
getString(R.string.add_card, currentDeck.deckName))
...
}
private fun Menu.getMenuItem(idx: Int, itemId: Int): MenuItem? {
Log.d(TAG, "getMenuItem: $idx of ${this.size()}")
if (idx >= size()) return null
val item = getItem(idx)
if (item.hasSubMenu()) {
val mi = item.subMenu.getMenuItem(0, itemId)
// mi non-null means we found item.
if (mi != null)
return mi
}
if (item != null && item.itemId == itemId)
return item
return getMenuItem(idx + 1, itemId)
}
fun Menu.menuSetText(itemId: Int, title: String) {
val menuItem = getMenuItem(0, itemId)
if (menuItem != null)
menuItem.title = title
else
Log.e(TAG,
"menuSetText to \"$title\": Failed to find ${
"itemId:0x%08x".format(itemId)}"
)
}

Categories

Resources