The renderings are a little rough

Recently, I wanted to implement a long press prompt “copy” function in the project. I wanted to be lazy and find an open source project on the Internet to use, but I was not satisfied with several projects, so I decided to implement one according to my own ideas.

How to use

Cui Hua, go to the code

PromptViewHelper pvHelper = new PromptViewHelper(mActivity);
pvHelper.setPromptViewManager(new ChatPromptViewManager(mActivity));
pvHelper.addPrompt(holder.itemView.findViewById(R.id.textview_content));Copy the code

It is very simple to use: first new a PromptViewHelper class, then set up a prompt View manager, and finally call the addPrompt method to add the view to which the prompt is to be added.

Train of thought

Through the use of QQ, wechat this function, feel that PopupWindow prompt box should be able to meet the needs.

So the general idea is:

  • Add a long press event to the View when it loads successfully
  • A PopupWindow is new when the user long presses and displays it, and the setting of clicking on the outer area can disappear

architecture

In order to make the upper layer call simple, convenient, I intend to put the prompt box View package into a class, this class includes: initial method, binding data, add events and so on; With this in mind, we define an abstract class and then let the concrete implementation class implement the corresponding methods. Let’s look at this abstract class first.

public static abstract class PromptViewManager { private View promptView; protected Activity activity; private String[] dataArray; private Location location; public OnItemClickListener onItemClickListener; public PromptViewManager(Activity activity, String[] dataArray, Location location) { this.activity = activity; this.dataArray = dataArray; this.location = location; init(); } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } public void init() { promptView = inflateView(); bindData(promptView, dataArray); } public abstract View inflateView(); public abstract void bindData(View view, String[] dataArray); public View getPromptView() { return promptView; } public Location getLocation() { return location; }}Copy the code

Notice that in an abstract class we have a Location object property, and what does that Location do, because we’re going to be thinking about the Location when we display the prompt View, and the Location is an enumeration object, and it contains some Location information;

public enum Location { TOP_LEFT(1), TOP_CENTER(2), TOP_RIGHT(3), BOTTOM_LEFT(4), BOTTOM_CENTER(5), BOTTOM_RIGHT(6); ICalculateLocation calculateLocation; Private Location(int type) {switch (type) {case 1: calculateLocation = ICalculateLocation implementation class break; Case 2: calculateLocation = ICalculateLocation implementation class break; TODO } }Copy the code

This enumeration object contains six positional display types, and then in the constructor it instantiates a ICalculateLocation object based on type. What is ICalculateLocation?

public interface ICalculateLocation {    
     int[] calculate(int[] srcViewLocation, View srcView, View promptView);
}Copy the code

It is an interface that provides a Calculate method to calculate the x and y coordinates of the prompt View. We implement this interface to calculate the coordinates of different locations.

At this point, the general framework is in place; First we define a PromtpViewManager manager to load the prompt View, bind the data, add the event, and then implement the different calculation classes by setting the Location enumeration, calculate the coordinates of the different locations, and then new a PopupWindow on display. Use PromtpViewManager to get the prompt View set to PopupWindow, and use PromtpViewManager to get the Location enumeration to calculate the coordinates of the class. Call the Calculate method to get the x and y coordinates. The PopupWindow prompt is then displayed using the PopupWindow showAtLocation method.

The specific implementation

Start by implementing a PromtpViewManager management class

public class ChatPromptViewManager extends PromptViewHelper.PromptViewManager { public ChatPromptViewManager(Activity activity, String[] dataArray, Location location) { super(activity, dataArray, location); } public ChatPromptViewManager(Activity Activity) {this(Activity, new String[]{" copy ", "paste "," forward "}, location.top_left); } public ChatPromptViewManager(Activity Activity, Location Location) {this(Activity, new String[]{" Copy ", "paste "," forward "}, location); } @Override public View inflateView() { return new PromptView(activity); } @Override public void bindData(View view, String[] dataArray) { if(view instanceof PromptView) { PromptView promptView = (PromptView) view; promptView.setContentArray(dataArray); promptView.setOnItemClickListener(new PromptView.OnItemClickListener() { @Override public void onItemClick(int position)  { if(onItemClickListener ! = null) onItemClickListener.onItemClick(position); }}); }}}Copy the code

Now that we’ve instantiated the View, bound the data, and added the events, we’re ready to calculate the coordinates that the View will display. I’ve implemented several methods here, post one of them, and if you have your own needs for location, you can implement a class copy method yourself.

public class TopCenterLocation implements ICalculateLocation {    
        @Override    
        public int[] calculate(int[] srcViewLocation, View srcView, View promptView) {        
             int[] location = new int[2];        
             int offset = (promptView.getWidth() - srcView.getWidth()) / 2;        
             location[0] = srcViewLocation[0] - offset;        
             location[1] = srcViewLocation[1] - promptView.getHeight();        
             return location;    
 }}Copy the code

So far all have been analyzed and finally attached code address: github.com/chenpengfei…