美文网首页
Android自定义view(二):简单的自定义viewgrou

Android自定义view(二):简单的自定义viewgrou

作者: 南风知我咦 | 来源:发表于2023-03-24 17:35 被阅读0次

申明

自定义view简单流程

  • 流程不复杂,特别如果是效果简单就很快。

流程

  • 这个也不复杂哈,我写了个ViewGroup
  • 这个相比view自定义还简单一点,它复杂地方是极端子view的位置;以及大小,来判断ViewGroup的大小。

/**
 * 简单的自定义viewgroup
 * 这个viewGroup呢,是一个存放三个方块,然后三个方块会不断从顶部移动到底部。方块大小固定,就用TextView吧,黑底,里面有简单的文字。
 */
public class SimpleSelfLayout extends ViewGroup {
}

设置LayoutParams

  • 这个就是直接抄的了,没什么想法
   //这个是设置LayoutParams的
    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

onMeasure

  • 这里我没有做任何操作哈
  • 这个方法主要是计算childView的测量值以及模式,以及设置自己的宽和高:
   //这个是设置整个容器的大小的
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //暂时默认大小好了
        //正常情况呢,需要遍历子view的大小,来判断容易的大小的。
        //EXACTLY:表示设置了精确的值,一般当childView设置其宽、高为精确值、match_parent时,ViewGroup会将其设置为EXACTLY;
        //
        //AT_MOST:表示子布局被限制在一个最大值内,一般当childView设置其宽、高为wrap_content时,ViewGroup会将其设置为AT_MOST;
        //
        //UNSPECIFIED:表示子布局想要多大就多大,一般出现在AadapterView的item的heightMode中、ScrollView的childView的heightMode中;此种模式比较少见。
        //这三种测了模式都会影响容易的大小。
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(getWidth(), getHeight());
    }

onLayout

  • 这里就是用来设置子view的位置的地方哈。
   @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        firstOnLayout(changed, l, t, r, b);
    }
 int[][] locations;

    private void firstOnLayout(boolean changed, int l, int t, int r, int b) {
        locations = new int[getChildCount()][4];//存放每个子view的坐标数据left,top,right,bottom
        //设置子view的位置。
        int count = getChildCount();//子view的数量
        int width = 0;
        int height = 0;
        MarginLayoutParams params;
        int maxWidth = 0;
        //开始遍历子view
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            maxWidth += child.getMeasuredWidth();
        }
        int lastWidth = getWidth() - maxWidth;//剩余的空间,这个空间需要平均分配,让空间间距一样。
        int avgWidth = lastWidth / (count + 1);
        if (avgWidth < 0) avgWidth = 0;
        int cLeft = 0, cTop = 0, cRight = 0, cBottom = 0;
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            width = child.getMeasuredWidth();
            height = child.getMeasuredHeight();
            params = (MarginLayoutParams) child.getLayoutParams();

            cLeft = cRight + params.leftMargin + avgWidth;//左边距加上剩余的距离 i个子view需要分成i+1份
            cRight = cLeft + params.rightMargin + width;

            cTop = params.topMargin;
            cBottom = height + cTop;
            //设置子view的位置
            locations[i][0] = cLeft;
            locations[i][1] = cTop;
            locations[i][2] = cRight;
            locations[i][3] = cBottom;
            Log.d("坐标", "cLeft = " + cLeft);
            Log.d("坐标", "cTop = " + cTop);
            Log.d("坐标", "cRight = " + cRight);
            Log.d("坐标", "cBottom = " + cBottom);
            child.layout(cLeft, cTop, cRight, cBottom);
        }
        letMove();
    }

使用

  • 就在xml文件里使用了
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <com.southwind.selfview.selfview.SimpleSelfLayout
        android:id="@+id/simpel_group"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="80dp"
            android:layout_height="50dp"
            android:background="@color/teal_700"
            android:textColor="@color/white"
            android:gravity="center"
            android:text="1" />

        <TextView
            android:layout_width="80dp"
            android:layout_height="50dp"
            android:background="@color/teal_200"
            android:textColor="@color/white"
            android:gravity="center"
            android:text="2" />

        <TextView
            android:layout_width="80dp"
            android:layout_height="50dp"
            android:background="@color/purple_500"
            android:textColor="@color/white"
            android:gravity="center"
            android:text="3" />
    </com.southwind.selfview.selfview.SimpleSelfLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

移动效果

  • 这里我不知道开启线程循环会不会有啥坏影响,但是我确实找不到其他方法了
  • 这个效果可以继续分一下,比如不同速率,分别启动等。最终形态就是金币于,下面有一个人在接着,然后算分数。
    private void letMove() {
        MoveRunnable runnable = new MoveRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
    }

    public void stop(){
        startMove = false;
    }

   private void setCurrentPlace() {
        int top = locations[0][1] + moveHeight;
        if (top > getHeight()) {
            moveHeight = 0;
        }
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            child.layout(locations[i][0], locations[0][1] + moveHeight, locations[i][2], locations[0][3] + moveHeight);
        }
    }
    private boolean startMove = true;
    private class MoveRunnable implements Runnable {
        @Override
        public void run() {
            while (startMove) {
                moveHeight += 2;
                setCurrentPlace();
                try {
                    Thread.sleep(35);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

问题

  • 设置LayoutParams的时,竟然有两个方法,我一开使用的第二个,一直会出问题,不知道为什么。
  • 位置计算真的头疼,算错了就会变得奇奇怪怪的。
  • 跑了几分钟也没怎么样,看来这样子循环应该问题不大。
 //这个是设置LayoutParams的
    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected LayoutParams generateLayoutParams(LayoutParams p) {
        return super.generateLayoutParams(p);
    }
效果图
简单的自定义ViewGroup.gif

相关文章

网友评论

      本文标题:Android自定义view(二):简单的自定义viewgrou

      本文链接:https://www.haomeiwen.com/subject/grawrdtx.html