Issue
I'm trying to make an ActionBar Menu OverFlow. The type twitter does. Where The Name and The UserName shows on the first Item on the OverFlow. So, I did this, but it's not taking any effect, any help would be appreciated. There is my code:
MyActivity.java
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem menuItem = menu.findItem(R.id.username);
View usname = getLayoutInflater().inflate(R.layout.action_menu_overflow, null);
TextView uName = (TextView) usname.findViewById(R.id.profileName);
TextView slug = (TextView) usname.findViewById(R.id.slugName);
uName.setText("Users");
slug.setText("Tracer");
menuItem.setActionView(usname);
//MenuItemCompat.setActionView(menuItem, usname);
//menuItem.setTitle("Users");
return super.onPrepareOptionsMenu(menu);
}
Menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item
android:id="@+id/username"
android:title="@string/username"
app:showAsAction="never" />
<item
android:id="@+id/logout"
android:title="@string/logout"
app:showAsAction="never" />
</menu>
action_menu_overflow.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/slugLayout">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="New Text"
android:id="@+id/profileName" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:layout_marginLeft="15dp"
android:text="New Text"
android:id="@+id/slugName" />
</LinearLayout>
Solution
This cannot be achieved by use of PopUpMenu, which the normal android overflow menu uses since it is constrained to not easily be used with complex custom layout/adapter . However, this twitter-like overflow menu can easily be achieved by use of ListPopupWindow, which is made to be easily used with more complex layouts/adapters.
To make this simple ,you can have a function in your activity/fragment to setup the ListPopupWindow . This is an example:
public void onListPopUp(View anchor)
{
// This a sample dat to fill our ListView
ArrayList<Person> personItem = new ArrayList<Person>();
personItem.add(new Person(R.drawable.remove_placeholder_userpic, "Mamluki", "@DigitalSurgeonR"));
personItem.add(new Person(0, "Lists", "@Lists"));
personItem.add(new Person(0, "Drafts", "@Drafts"));
personItem.add(new Person(0, "Accounts", "@Accounts"));
// Initialise our adapter
ListPopupWindowAdapter mListPopUpAdapter = new ListPopupWindowAdapter(this, personItem);
//Initialise our ListPopupWindow instance
final ListPopupWindow pop = new ListPopupWindow(this);
// Configure ListPopupWindow properties
pop.setAdapter(mListPopUpAdapter);
// Set the view below/above which ListPopupWindow dropdowns
pop.setAnchorView(anchor);
// Setting this enables window to be dismissed by click outside ListPopupWindow
pop.setModal(true);
// Sets the width of the ListPopupWindow
pop.setContentWidth(150);
// Sets the Height of the ListPopupWindow
pop.setHeight(ListPopupWindow.WRAP_CONTENT);
// Set up a click listener for the ListView items
pop.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
// Dismiss the LisPopupWindow when a list item is clicked
pop.dismiss();
Toast.makeText(MainActivity.this, "Clicked ListPopUp item " + ((Person) adapterView.getItemAtPosition(position)).getName(), Toast.LENGTH_LONG).show();
}
});
pop.show();
}
This function can be called from the method override below -:
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.action_overflow:
// Works as long as list item is always visible and does not go into the menu overflow
final View menuItemView = findViewById(R.id.action_overflow);
onListPopUp(menuItemView);
Log.w(LOG_TAG, "You called me OverFlow");
return true;
default:
{
return super.onOptionsItemSelected(item);
}
}
}
Our adapter will extend the BaseAdapter and will have the following code snippet .
public class ListPopupWindowAdapter extends BaseAdapter {
// ----------------------------------------
// Variables
// ----------------------------------------
private Context context;
private ArrayList<Person> personItem;
// ----------------------------------------
// Methods
// ----------------------------------------
public ListPopupWindowAdapter(Context context, ArrayList<Person> personItem)
{
this.context = context;
this.personItem = personItem;
}
// ----------------------------------------
public View getView(int position, View convertView, ViewGroup parent) {
ImageView profilePic;
TextView name;
TextView userName;
boolean isWithPicture = (personItem.get(position).getProfilePic() != 0);
// Small List View , no need to recycle views
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Is this the row with the p.picture
if(isWithPicture)
{
//Layout for the top row with profile picture /Avatar
convertView = inflater.inflate(R.layout.toolbar_overflow_item_row, parent, false);
profilePic = (ImageView) convertView .findViewById(R.id.imageProfilePic);
profilePic.setImageResource(personItem.get(position).getProfilePic());
userName = (TextView) convertView .findViewById(R.id.textUsername);
userName.setText(personItem.get(position).getUserName());
}
else
{
//Layout for the other layout without an images
convertView = inflater.inflate(R.layout.toolbar_overflow_item_row_text, parent, false);
}
name = (TextView) convertView .findViewById(R.id.textViewName);
name.setText(personItem.get(position).getName());
return convertView ;
}
// ----------------------------------------
// Implemented
// ----------------------------------------
@Override
public Object getItem(int index)
{
return personItem.get(index);
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public int getCount()
{
return personItem.size();
}
}
We have two layouts . One for the listView top row item and another for the other rows.
toolbar_overfow_row_item.xml -top row item
<?xml version="1.0" encoding="utf-8"?> <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="6dp">
<ImageView
android:id="@+id/imageProfilePic"
android:layout_width="40dp"
android:layout_height="40dp"
android:visibility="visible"
android:src="@color/apptheme_accent_teal" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="16dp"
>
<TextView
android:id="@+id/textViewName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mamluki"
android:textColor="@android:color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/textUsername"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
android:paddingTop="6dp"
android:text="\@DigitalSurgeonR"
android:textColor="?android:attr/textColorSecondary"
android:textSize="13sp" />
</LinearLayout> </LinearLayout>
toolbar_overfow_row_item_text.xml -other row items
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="14dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="@+id/textViewName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mamluki"
android:textColor="@android:color/black"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
Additionally , to set the position of the ListPopupWindow
we can use methods:-
setVerticalOffset(int offset)
setHorizontalOffset(int offset)
The Horizontal & Vertical offset are 0 by default . Setting the vertical offset to setVerticalOffset(-36) makes the ListPopupWindow overlay the actionbar/toolbar . The more negative value pushes it further up . Alternatively you can set it as a Style in your styles.xml like below
<style name="AppThemeToolBar" parent="AppBaseThemeNoActionBar.Dark" >
<!-- Customize your theme here. -->
<!-- ListPopUpWindow styles -->
<item name="listPopupWindowStyle">@style/Widget.App.ListPopupWindow</item>
</style>
<!-- Widget styles -->
<style name="Widget" />
<style name="Widget.App" parent="Widget" />
<!-- Widget ListPopUpWindow Style-->
<style name="Widget.App.ListPopupWindow" parent="Widget.AppCompat.Light.ListPopupWindow">
<item name="android:dropDownVerticalOffset">-36px</item>
</style>
Answered By - Otieno Rowland
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.