“This is the sixth day of my participation in the First Challenge 2022. For details: First Challenge 2022”

In this third blog post in the Custom View series, we will learn how to implement a custom drop-down box.Today’s program, we will achieve such an effect.The layout is very simple and we just start coding. Modify the code of the activity_main.xml file.


      
<RelativeLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.itcast.test0430.MainActivity">

    <EditText
        android:id="@+id/et_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ellipsize="middle"
        android:hint="Please enter the content..."
        android:paddingRight="40dp"
        android:singleLine="true" />

    <ImageView
        android:id="@+id/iv_down_arrow"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_alignRight="@id/et_input"
        android:layout_alignTop="@id/et_input"
        android:padding="5dp"
        android:src="@drawable/down_arrow" />
</RelativeLayout>
Copy the code

The layout code is very simple, just two controls. Next, modify the MainActivity code.

package com.itcast.test0430;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;

import java.util.ArrayList;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.et_input)
    EditText etInput;
    @BindView(R.id.iv_down_arrow)
    ImageView ivDownArrow;

    / * * * * /
    private PopupWindow popupWindow;
    private ListView listView;

    private ArrayList<String> msgs;
    private MyAdapter adapter;

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

        listView = new ListView(this);
        listView.setBackgroundColor(Color.WHITE);
        // Prepare data
        msgs = new ArrayList<>();
        for(int i = 0; i <500; i++) { msgs.add(i +"--aaaaaa---" + i);
        }
        adapter = new MyAdapter();
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<? > parent, View view,int position, long id) {
                //1
                String msg = msgs.get(position);
                //2, set to input box
                etInput.setText(msg);

                if(popupWindow ! =null && popupWindow.isShowing()){
                    popupWindow.dismiss();
                    popupWindow = null; }}}); }@OnClick(R.id.et_input)
    public void onViewClick(View view){
        if(popupWindow == null){
            popupWindow = new PopupWindow(this);
            popupWindow.setWidth(etInput.getWidth());
            popupWindow.setHeight(400);

            popupWindow.setContentView(listView);
            popupWindow.setFocusable(true);// Set the focus
        }

        popupWindow.showAsDropDown(etInput,0.0);
    }

    class MyAdapter extends BaseAdapter{

        @Override
        public int getCount(a) {
            return msgs.size();
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if(convertView == null){
                convertView = View.inflate(MainActivity.this,R.layout.item_main,null);
                viewHolder = new ViewHolder();
                viewHolder.tv_msg = convertView.findViewById(R.id.tv_msg);
                viewHolder.iv_delete = convertView.findViewById(R.id.iv_delete);
                convertView.setTag(viewHolder);
            }else{
                viewHolder = (ViewHolder) convertView.getTag();
            }
            // Get data based on location
            final String msg = msgs.get(position);
            viewHolder.tv_msg.setText(msg);

            // Set delete
            viewHolder.iv_delete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // delete from collection
                    msgs.remove(msg);
                    // Refresh the UI-- refresh the adapteradapter.notifyDataSetChanged(); }});returnconvertView; }}static class ViewHolder{ TextView tv_msg; ImageView iv_delete; }}Copy the code

The code for the item_main.xml file is as follows.


      
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:gravity="center_vertical"
    android:orientation="horizontal"
    android:padding="5dp">

    <ImageView
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_gravity="center_vertical"
        android:layout_margin="5dp"
        android:padding="3dp"
        android:src="@drawable/user" />

    <TextView
        android:id="@+id/tv_msg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_margin="5dp"
        android:layout_weight="1"
        android:gravity="center"
        android:padding="3dp"
        android:text="The Three Musketeers"
        android:textColor="# 000" />

    <ImageView
        android:id="@+id/iv_delete"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_gravity="center_vertical"
        android:layout_margin="5dp"
        android:padding="3dp"
        android:src="@drawable/delete" />
</LinearLayout>
Copy the code

The code here is also very simple, so I won’t explain too much, and there are comments everywhere. Only need to pay attention to is that, because our PopupWindow class is set up for 200 wide, and as long as it is in the code set control properties, its unit of px (pixels), the pixel is no adaptation function, so in order to make our program can run correctly on any resolution of the mobile phone, we should convert pixels to dp. A utility class is provided for converting between DP and PX.

package com.itcast.test0430;

import android.content.Context;

public class DensityUtil {
    /** * Convert dip units to px(pixels) */ based on the resolution of the phone
    public static int dipToPx(Context context,float dpValue){
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5 f);
    }

    /** * Convert from px(pixels) to dip */ based on the phone's resolution
    public static int pxToDip(Context context,float pxValue){
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue * scale + 0.5 f); }}Copy the code

So, we put popupwindow.setheight (400); Instead of

int height = DensityUtil.dipToPx(this.400);
popupWindow.setHeight(height);
Copy the code

Can. Now run the project to get a preview.In this way, our drop-down box is also implemented. Now that we have a utility class for converting between DP and PX, we can use it where screen adaptation is needed, including some of the projects we practiced earlier.

The source has been uploaded to GitHub