Zero, Preface:

1. The companion of this article: visible data structure of the Android version of the table array implementation (data Structure) 2. I hope you can join me at Github to witness the birth and growth of DS4Android. Welcome to star 3. The exciting moment is coming. It’s time to draw. Pencils, scratch paper, drinks, peanuts are ready

First leave the map town building:

Routine operations on table structures

Expansion and reduction of arrays


First, draw the operation interface:

1. Customize View:ArrayView

Prepare a main brush and main path and determine some constants, then use the Analyze package to draw the wrapped grid and coordinate system for viewing

/** * Author: Zhang Feng Jiete Lie <br/> * Time: 2018/11/210021:8:01 <br/> * Email: [email protected]<br/> * Description: */ public class ArrayView<E> extends View {private Point mCoo = new Point(200, 150); // Private Picture mCooPicture; // Canvas element private grid Picture; // Canvas element private Path mPath; // Private Paint mPaint; Private static final int OFFSET_X = 10; Private static final int OFFSET_Y = 60; Private static final int OFFSET_OF_TXT_Y = 10; Private static final int BOX_RADIUS = 10; private static final int BOX_RADIUS = 10; Public ArrayView(Context Context) {this(Context, null); } public ArrayView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); // Initialize} private voidinit() {// Initialize the main paintbrush. MPaint = new Paint(paint.anti_alias_flag); mPaint.setColor(Color.BLUE); mPaint.setStrokeWidth(5); mPaint.setTextAlign(Paint.Align.CENTER); mPaint.setTextSize(50); // Initialize the main Path mPath = new Path(); MCooPicture = helpdraw.getCoo (), mCoo (), helpdraw.getCoo (), mCoo ())false); MGridPicture = helpdraw.getGrid (getContext()); } @override protected void onDraw(Canvas) {super.ondraw (Canvas); HelpDraw.draw(canvas, mGridPicture); canvas.save(); canvas.translate(mCoo.x, mCoo.y); //TODO draw canvas. Restore (); HelpDraw.draw(canvas, mCooPicture); }}Copy the code


2. Prepare the brushes to use in the back:
private void init() {// Initialize the main paintbrush. MPaint = new Paint(paint.anti_alias_flag); mPaint.setColor(Color.BLUE); mPaint.setStrokeWidth(5); mPaint.setTextAlign(Paint.Align.CENTER); mPaint.setTextSize(50); // Initialize the main Path mPath = new Path(); // Initialize the text brush mTxtPaint = new Paint(paint.anti_alias_flag); mTxtPaint.setColor(Color.WHITE); mTxtPaint.setTextAlign(Paint.Align.CENTER); mTxtPaint.setTextSize(40); MPathPaint = new Paint(paint.anti_alias_flag); mPathPaint.setColor(Color.GRAY); mPathPaint.setStyle(Paint.Style.STROKE); mCooPicture = HelpDraw.getCoo(getContext(), mCoo,false); mGridPicture = HelpDraw.getGrid(getContext()); // Initialize the ball button paintbrush mCtrlPaint = new Paint(paint.anti_alias_flag); mCtrlPaint.setColor(Color.RED); mCtrlPaint.setTextAlign(Paint.Align.CENTER); mCtrlPaint.setTextSize(30); }Copy the code
3. Prepare the ball’s message

You can also encapsulate this information into a bean, but in this case there are several arrays to record the information in order to confuse beans

Private static final Point[] CTRL_POS = new Point[]{CTRL_POS = new Point(-100, 100), 300),// update new Point(-100, 500),// update new Point(-100, 700),// Delete new Point(700, -70),// add new Point(700 + 300),// add new Point(700 + 300),// add new Point(700 + 300),// add new Point(700 + 300), // delete new Point(700 + 300 * 3, -70),// delete new Point(700 + 300 * 3, -70),// delete new Point(700 + 300 * 3, -70); Private static int[] CTRL_COLOR = new int[]{// Add 0xff1EF519,// Add 0xff2992F2,// Update 0xffB946F4,// Add 0xffF50C0C,// Delete 0xff1EF519,// fixed point add 0xffB946F4,// fixed value query 0xffF50C0C,// fixed point delete 0xffF46410,// clear}; Private static final String[] CTRL_TXT = new String[]{// Control button text"Add"/ / added"Update"/ / update"Search"/ / added"Delete"/ / delete"Fixed-point +",// add at a fixed pointThe value of "check",// Fixed value query"Fixed point -",// fixed point deletion"Empty",// clear button}; private static final int CTRL_RADIUS = 50; // The radius of the control buttonCopy the code

3. Draw a small ball:

Hard words not much —- a cycle, a wave away

/** * @param canvas */ private void ctrlView(canvas) {for(int i = 0; i < CTRL_POS.length; i++) { mCtrlPaint.setColor(CTRL_COLOR[i]); canvas.drawCircle(CTRL_POS[i].x, CTRL_POS[i].y, CTRL_RADIUS, mCtrlPaint); canvas.drawText(CTRL_TXT[i], CTRL_POS[i].x, CTRL_POS[i].y + OFFSET_OF_TXT_Y, mTxtPaint); }}Copy the code

This is… Finished? right And that’s it


Iii. Click event of the ball (region judgment)

1. I’m Judgeman.java, one of the king’s ten gods of world War II.
/** * The God of Judgment power I: First form: Area limit ---- Determine whether the radius of a point is within the r circle * * @param srcX target point X * @param srcY Target point Y * @param dstX active point X * @param dstY Active point Y * @Param R radius area * @return*/ public judgeCircleArea(judgeCircleArea)float srcX, float srcY, float dstX, float dstY, float r) {
    returndisPos2d(srcX, srcY, dstX, dstY) <= r; } / * * * god passive ability of the judge: the distance between the two functions * @ param srcX target X * @ param srcY target Y * @ param dstX active point X * @ param dstY active point Y * @returnFunction */ private staticfloat disPos2d(float srcX, float srcY, float dstX, float dstY) {
    return (float) Math.sqrt((srcX - dstX) * (srcX - dstX) + (srcY - dstY) * (srcY - dstY));
}
Copy the code


2. Write a callback listener interface:OnCtrlClickListener

The troops and horses have not moved, the food and grass first, the interface is easy to handle affairs

/** * Author: Zhang Feng Jiete Lie <br/> * Time: 2018/11/210021:10:17 <br/> * Email: [email protected]<br/> * Description: Public interface OnCtrlClickListener<T> {@param view */ void onAdd(T view); public interface OnCtrlClickListener<T> {@param view */ void onAdd(T view); @param view */ void onAddByIndex(T view); /** * callback to remove * @param view */ void onRemove(T view); Void onRemoveByIndex(T view); /** * callback * @param view */ void onRemoveByIndex(T view); /** ** @param view */ void onSet(T view); /** * callback @param view */ void onFind(T view); @param view */ void onFindByData(T view); /** * callback when clearing * @param view */ void onClear(T view); }Copy the code
3. Touch event to get the active point:

—-(Mark: IN the beginning, I am also an if, and then found that can be optimized, only to become elegant) may not be able to think of bits in one step, but can be implemented first, and then optimized, I like the feeling of this wave away. Note: DownX and downY are relative to the canvas frame, so they have to be offset

private OnCtrlClickListener<ArrayView<E>> mOnCtrlClickListener; // Listener public voidsetOnCtrlClickListener(OnCtrlClickListener<ArrayView<E>> onCtrlClickListener) { mOnCtrlClickListener = onCtrlClickListener;  } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) {case MotionEvent.ACTION_DOWN:
            float downX = event.getX() - mCoo.x;
            float downY = event.getY() - mCoo.y;
            for (int i = 0; i < CTRL_POS.length; i++) {
                ifCTRL_POS[I]. X, CTRL_POS[I]. Y, downX, downY, CTRL_RADIUS * 1.2f)) {if(mOnCtrlClickListener ! = null) { switch (i) {case0: / / on the insert mOnCtrlClickListener onAdd (this);break;
                            case1: / / update mOnCtrlClickListener. The onSet (this); contactTest();break;
                            case2: / / find mOnCtrlClickListener. OnFind (this);break;
                            caseSelectIndex = marrayboxes.size () -1; mAnimator.start();break;
                            case4: / / on the fixed-point add mOnCtrlClickListener onAddByIndex (this);break;
                            case5: / / fixed value query mOnCtrlClickListener. OnFindByData (this);break;
                            case6:// remove manimator.start ();break;
                            case7: / / empty mOnCtrlClickListener onClear (this);break; } CTRL_COLOR[i] = 0xff54E1F8; }}} updayeSelectIndex(downX, downY); / / update the selectIndexbreak;
        caseACTION_UP:// Restore the color CTRL_COLOR[0] = 0xff1EF519; CTRL_COLOR[1] = 0xff2992F2; CTRL_COLOR[2] = 0xffB946F4; CTRL_COLOR[3] = 0xffF50C0C; CTRL_COLOR[4] = 0xff1EF519; CTRL_COLOR[5] = 0xffB946F4; CTRL_COLOR[6] = 0xffF50C0C; CTRL_COLOR[7] = 0xffF46410;break; } invalidate(); // Remember to redrawreturn true;
}
Copy the code
4.Activity use interface:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ArrayView<String> view = new ArrayView<>(this); view.setOnCtrlClickListener(new OnCtrlClickListener<ArrayView<String>>() { @Override public void onAdd(ArrayView<String>  view) { Toast.makeText(MainActivity.this,"onAdd", Toast.LENGTH_SHORT).show();
            }
            @Override
            public void onAddByIndex(ArrayView<String> view) {
                Toast.makeText(MainActivity.this, "onAddByIndex", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onRemove(ArrayView<String> view) {
                Toast.makeText(MainActivity.this, "onRemove", Toast.LENGTH_SHORT).show();
            }
            @Override
            public void onRemoveByIndex(ArrayView<String> view) {
                Toast.makeText(MainActivity.this, "onRemoveByIndex", Toast.LENGTH_SHORT).show();
            }
            @Override
            public void onSet(ArrayView<String> view) {
                Toast.makeText(MainActivity.this, "onSet", Toast.LENGTH_SHORT).show();
            }
            @Override
            public void onFind(ArrayView<String> view) {
                Toast.makeText(MainActivity.this, "onFind", Toast.LENGTH_SHORT).show();
            }
            @Override
            public void onFindByData(ArrayView<String> view) {
                Toast.makeText(MainActivity.this, "onFindByData", Toast.LENGTH_SHORT).show();
            }
            @Override
            public void onClear(ArrayView<String> view) {
                Toast.makeText(MainActivity.this, "onFindByData", Toast.LENGTH_SHORT).show(); }});setContentView(view); }}Copy the code

OK, works perfectly, core is judgeCircleArea of god


Third, the text comes, draw the data structure:

1. Drawable object monomer: Use the parent class of the data structure monomer

It has three core attributes: coordinate, color, and speed

/** * Author: Zhang Feng Jiete Lie <br/> * Time: 2018/11/210021:8:50 <br/> * Email: [email protected]<br/> * Description: */ public class Viewable {publicfloatx; // The x coordinate of the monomer publicfloaty; Public int color = 0xff43A3FA; // Individual color publicfloatvX; // The horizontal speed of the monomer publicfloatvY; // The numeric speed of the monomer publicViewable() {
    }

    public Viewable(float x, floaty) { this.x = x; this.y = y; }}Copy the code
2. The drawing host object of the array table structure unit:

Array box: Has two additional properties: index and data

/** * Author: Zhang Feng Jiete Lie <br/> * Time: 2018/11/210021:8:46 <br/> * Email: [email protected]<br/> * Description: Public class ArrayBox<T> extends Viewable {public int index; Public T data; @override public Boolean equals(Object obj) {return ((ArrayBox) obj).data == data;
    }

    public ArrayBox(T data) {
        this.data = data;
    }

    public ArrayBox(float x, floaty) { super(x, y); }}Copy the code
3. Draw a blank rectangle with the length of the array
1) How to determine the point according to the index

Is a little draw a picture, see what relationship, find the general ok (code more clever, writing is ugly…) Then we test it with the array table structure from the previous section

2) Draw a blank rectangle with the length of the array

According to the above diagram, determine the rectangle coordinates of column x, row y, should not be difficult to draw note: draw the length of the array blank rectangle, the length of the array!! The length of the array!! Instead of the size of the collection, we should wrap the array in an array table structure. To demonstrate the expansion and reduction, the size of the array is still necessary

Private IChart<ArrayBox<E>> mArrayBoxes = new ArrayChart<>(); /** * Draw array length blank rectangle ** @param canvas */ private voidhelpView(Canvas canvas) {
    for(int i = 0; i < mArrayBoxes.capacity(); i++) { int y = i / 8; Int x = I % 8; // Column coordinates mPaint. SetStyle (paint.style.stroke); mPaint.setColor(0xff821AFA); canvas.drawRoundRect( (Cons.BOX_WIDTH + OFFSET_X) * x, (Cons.BOX_HEIGHT + OFFSET_Y) * y, (Cons.BOX_WIDTH + OFFSET_X) * x + Cons.BOX_WIDTH, (Cons.BOX_HEIGHT + OFFSET_Y) * y + Cons.BOX_HEIGHT, BOX_RADIUS, BOX_RADIUS, mPaint); mTxtPaint.setColor(0xff821AFA); canvas.drawText(i +"", (Cons.BOX_WIDTH + OFFSET_X) * x + Cons.BOX_WIDTH / 2, (Cons.BOX_HEIGHT + OFFSET_Y) * y + 3 * OFFSET_OF_TXT_Y, mTxtPaint); }}Copy the code

The initial length of the array is 10, right


4. Draw the table structure

Draw all the elements of a Marraybox according to its size. Drawing monomers is given in the preface, but the offset is added here, so it should be easy to understand.

@param canvas */ private void dataView(canvas canvas) {mPaint. SetColor (color.blue); mPaint.setStyle(Paint.Style.FILL); mPath.reset();for (int i = 0; i < mArrayBoxes.size(); i++) {
        ArrayBox box = mArrayBoxes.get(i);
        mPaint.setColor(box.color);
        canvas.drawRoundRect(
                box.x, box.y, box.x + Cons.BOX_WIDTH, box.y + Cons.BOX_HEIGHT,
                BOX_RADIUS, BOX_RADIUS, mPaint);
        mPath.moveTo(box.x, box.y);
        mPath.rCubicTo(Cons.BOX_WIDTH / 2, Cons.BOX_HEIGHT / 2,
                Cons.BOX_WIDTH / 2, Cons.BOX_HEIGHT / 2, Cons.BOX_WIDTH, 0);
        canvas.drawPath(mPath, mPathPaint);
        canvas.drawText(box.data + "", box.x + Cons.BOX_WIDTH / 2, box.y + Cons.BOX_HEIGHT / 2 + 3 * OFFSET_OF_TXT_Y, mTxtPaint); }}Copy the code
5. Update the point position of the drawing unit

The point is updated after each add or delete operation

/** * Update the point to draw the monomer */ private voidupdatePosOfData() {
    for(int i = 0; i < mArrayBoxes.size(); i++) { int y = i / 8; Int x = I % 8; ArrayBox box = marrayboxes.get (I); box.x = (Cons.BOX_WIDTH + OFFSET_X) * x; box.y = (Cons.BOX_HEIGHT + OFFSET_Y) * y; box.vY = 100; box.vX = 100; }}Copy the code
6. Dynamically update the selected value when clicking:
/** * updateSelectIndex() * @param downX * @param downY */ private void updateSelectIndex()float downX, float downY) {
    floatX = downX/(Cons.BOX_WIDTH + OFFSET_X) -0.5f;floatY = downY/(Cons.BOX_HEIGHT + OFFSET_Y) -0.5f;if(x > -0.5 && y > -0.5) {int indexOfData = math.round (y) * 8 + math.round (x); // Retrieve the index of the data at the pointif(indexOfData < mArrayBoxes.size()) { mArrayBoxes.get(indexOfData).color = ColUtils.randomRGB(); selectIndex = indexOfData; }}}Copy the code

Iv. Operation button drawing:

Note: The following actions are performed in the click callback in the Activity, calling the method in the View layer, separating the action from the view

1. Add operations:
Public void addData(E data) {ArrayBox<E> ArrayBox = new ArrayBox<>(0, 0); arrayBox.data = data; mArrayBoxes.add(arrayBox); updatePosOfData(); // Update the position}Copy the code

@param data */ public void addDataById(int index, E data) {@param data */ public void addDataById(int index, E data) {if(mArrayBoxes.size() > 0 && index < mArrayBoxes.size() && index >= 0) { ArrayBox<E> arrayBox = new ArrayBox<>(0, 0); arrayBox.data = data; mArrayBoxes.add(index, arrayBox); updatePosOfData(); }}Copy the code


2. Query and update operations
/** * View data operation interface method -- query operation according to id * @param index * @return
 */
public E findData(int index) {
    if (mArrayBoxes.size() > 0 && index < mArrayBoxes.size() && index >= 0) {
        return mArrayBoxes.get(index).data;
    }
    returnnull; } /** * Update data * @param index * @param data */ public voidsetData(int index, E data) {
    if(mArrayBoxes.size() > 0 && index < mArrayBoxes.size() && index >= 0) { mArrayBoxes.get(index).data = data; }}Copy the code

/** * view data operation interface method -- query operation based on data * @param data * @return
 */
public int[] findData(E data) {
    ArrayBox<E> arrayBox = new ArrayBox<>(0, 0);
    arrayBox.data = data;
    return mArrayBoxes.getIndex(arrayBox);
}
Copy the code


3. Delete operation:
1) The core method of deletion:
/** * View data manipulation interface method -- remove end */ public voidremoveData() {
    if(mArrayBoxes.size() > 0) { mArrayBoxes.remove(); updatePosOfData(); ** @param index */ public void removeData(int index) {if(marrayboxes.size () > 0 && index < Marrayboxes.size () && index >= 0) {// Update the following indexfor(int i = index; i < mArrayBoxes.size(); i++) { mArrayBoxes.get(i).index -= 1; } mArrayBoxes.remove(index); selectIndex = -1; updatePosOfData(); }}Copy the code
2) Delete has a remove animation, ValueAnimate to help
ValueAnimator mAnimator = valueAnimator.offloat (0, 1); // Initialize the time stream. mAnimator.setRepeatCount(-1); mAnimator.setDuration(2000); mAnimator.setRepeatMode(ValueAnimator.REVERSE); mAnimator.setInterpolator(new LinearInterpolator()); mAnimator.addUpdateListener(animation -> { updateBall(); Invalidate (); });Copy the code
3) Update Select updateBall
/** * Update the ball */ private voidupdateBall() {
    if (mArrayBoxes.size() <= 0 && selectIndex < 0) {
        return;
    }
    ArrayBox ball = mArrayBoxes.get(selectIndex);
    ball.x += ball.vX;
    ball.y += ball.vY;
    if(ball.y > 600) {// If it is greater than 600, remove itif(mOnCtrlClickListener ! = null) { mOnCtrlClickListener.onRemoveByIndex(this); // Remove listen from here!! mAnimator.pause(); // Pause ValueAnimator}}}Copy the code
// Click on listen to modify:caseSelectIndex = Marrayboxes.size () -1; mAnimator.start(); / / open the AnimatorCopy the code

4. Joint test:
private void contactTest() {
    IChart<ArrayBox<E>> contactArr = new ArrayChart<>();
    contactArr.add(new ArrayBox<E>((E) "toly1"));
    contactArr.add(new ArrayBox<E>((E) "toly2"));
    contactArr.add(new ArrayBox<E>((E) "toly3"));
    contactData(selectIndex, contactArr);
}

public void contactData(int index, IChart<ArrayBox<E>> chart) {
    mArrayBoxes.contact(index, chart);
    updatePosOfData();
}
Copy the code

Basically is this, the train of thought what all clear, details can see the source code


Further updates in this series link collection :(dynamic updates)

  • Visible data structures: the introduction to the Android version
  • Array Tables for Android (Data Structures)
  • Android Array Table (View Section)
  • Visible data structure Android version of the single linked list
  • Visible data structure Android version of the double Linked list
  • Visible data structure stack for Android version
  • Visible data structure of the Android version of the queue article
  • Visible data structure Android version of the binary search tree
  • More data structures – more on that later

Postscript: Jie wen standard

1. Growth record and Errata of this paper
Program source code The date of note
V0.1 – making 2018-11-23 Table Array implementation for Android (View section)
2. More about me
Pen name QQ WeChat hobby
Zhang Feng Jie te Li 1981462002 zdl1994328 language
My lot My Jane books I’m the nuggets Personal website
3. The statement

1—- this article is originally written by Zhang Feng Jetelie, please note 2—- all programming enthusiasts are welcome to communicate with each other 3—- personal ability is limited, if there is any error, you are welcome to criticize and point out, will be modest to correct 4—- See here, I thank you here for your love and support