thumbnail

Create android dropdown menu with PopupWindow


In this tutorial, I will show you how to create dropdown menu in android application using PopupWindow and RecyclerView with custom item layout.
First, we create popup menu layout with recyclerview.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
    android:background="@android:color/white"
    android:orientation="horizontal">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rvCategory"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />
</LinearLayout>

Then, We create popup menu custom class by extending PopupWindow.
public class CategoryDropdownMenu extends PopupWindow {
    private Context context;
    private RecyclerView rvCategory;
    private CategoryDropdownAdapter dropdownAdapter;

    public CategoryDropdownMenu(Context context){
        super(context);
        this.context = context;
        setupView();
    }

    public void setCategorySelectedListener(CategoryDropdownAdapter.CategorySelectedListener categorySelectedListener) {
        dropdownAdapter.setCategorySelectedListener(categorySelectedListener);
    }

    private void setupView() {
        View view = LayoutInflater.from(context).inflate(R.layout.popup_category, null);

        rvCategory = view.findViewById(R.id.rvCategory);
        rvCategory.setHasFixedSize(true);
        rvCategory.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false));
        rvCategory.addItemDecoration(new DividerItemDecoration(context, LinearLayoutManager.VERTICAL));

        dropdownAdapter = new CategoryDropdownAdapter(Category.generateCategoryList());
        rvCategory.setAdapter(dropdownAdapter);

        setContentView(view);
    }
}

Inflate view from popup_category.xml layout file
View view = LayoutInflater.from(context).inflate(R.layout.popup_category, null);

Find RecyclerView by id
rvCategory = view.findViewById(R.id.rvCategory);

Set recyclerview as fixed size, vertical linear layout and divider.
rvCategory.setHasFixedSize(true);
rvCategory.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false));
rvCategory.addItemDecoration(new DividerItemDecoration(context, LinearLayoutManager.VERTICAL));

Next step is create adapter and assign to recyclerview. Currently, we have not implemented Adapter class
dropdownAdapter = new CategoryDropdownAdapter(Category.generateCategoryList());
rvCategory.setAdapter(dropdownAdapter);

Set inflated view into PopupWindow
setContentView(view)

Create model class “Category” with 2 variables “icon” and “category name”. One static method to generate category list.
public class Category {
    public long id;
    public int iconRes;
    public String category;

    public Category(long id, int iconRes, String category){
        super();
        this.id = id;
        this.iconRes = iconRes;
        this.category = category;
    }

    public static List generateCategoryList(){
        List categories = new ArrayList<>();
        String[] programming = {"C++", "JAVA", "JAVASCRIPT", "C#", "Objective C", "SWIFT"};

        for(int i = 0; i < programming.length; i++){
            categories.add(new Category(i, R.drawable.ic_insert_emoticon_black_24dp, programming[i]));
        }
        return categories;
    }
}

Next step, Create recyclerview adapter class and implement 3 methods
- onCreateViewHolder = Create View Holder for each item
- onBindViewHolder = Bind data into view holder
- getItemCount = Return item count
public class CategoryDropdownAdapter extends RecyclerView.Adapter {

    private List categories;
    private CategorySelectedListener categorySelectedListener;

    public CategoryDropdownAdapter(List categories){
        super();
        this.categories = categories;
    }


    public void setCategorySelectedListener(CategoryDropdownAdapter.CategorySelectedListener categorySelectedListener) {
        this.categorySelectedListener = categorySelectedListener;
    }

    @NonNull
    @Override
    public CategoryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new CategoryViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_category, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull CategoryViewHolder holder, final int position) {
        final Category category = categories.get(position);
        holder.ivIcon.setImageResource(category.iconRes);
        holder.tvCategory.setText(category.category);

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(categorySelectedListener != null){
                    categorySelectedListener.onCategorySelected(position, category);
                }
            }
        });
    }

    @Override
    public int getItemCount() {
        return categories.size();
    }

    static class CategoryViewHolder extends RecyclerView.ViewHolder{
        AppCompatTextView tvCategory;
        AppCompatImageView ivIcon;

        public CategoryViewHolder(View itemView) {
            super(itemView);
            tvCategory = itemView.findViewById(R.id.tvCategory);
            ivIcon = itemView.findViewById(R.id.ivIcon);
        }
    }

    interface CategorySelectedListener {
        void onCategorySelected(int position, Category category);
    }
}

Main Activity has one TextView. When click the TextView, we call showCategoryMenu function and create PopupWindow.
public class MainActivity extends AppCompatActivity {
    AppCompatTextView tvPicker;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvPicker = findViewById(R.id.tvPicker);
        tvPicker.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showCategoryMenu();
            }
        });
    }

    private void showCategoryMenu(){
        final CategoryDropdownMenu menu = new CategoryDropdownMenu(this);
        menu.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
        menu.setWidth(getPxFromDp(200));
        menu.setOutsideTouchable(true);
        menu.setFocusable(true);
        menu.showAsDropDown(tvPicker);
        menu.setCategorySelectedListener(new CategoryDropdownAdapter.CategorySelectedListener() {
            @Override
            public void onCategorySelected(int position, Category category) {
                menu.dismiss();
                Toast.makeText(MainActivity.this, "Your favourite programming language : "+ category.category, Toast.LENGTH_SHORT).show();
            }
        });
    }

    //Convert DP to Pixel
    private int getPxFromDp(int dp){
        return (int) (dp * getResources().getDisplayMetrics().density);
    }
}


Download full source code
https://github.com/winkoko33/AndroidPopupWindowDropdown

If you like this post, Please share it. Thank you for reading. 

No Comments