Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java getChildDrawingOrder调用/使用不稳定?_Java_Android_Drawing - Fatal编程技术网

Java getChildDrawingOrder调用/使用不稳定?

Java getChildDrawingOrder调用/使用不稳定?,java,android,drawing,Java,Android,Drawing,我正在用简单的平铺创建一个等轴测地图,并扩展了RelativeLayout,以创建一个包含这些平铺的布局。实际上,只要我的方向与写入XML文件的瓷砖顺序相匹配,就可以使用RelativeLayoutas;我所覆盖的是构造函数,我只需调用super和setChildrenDrawingOrderEnabled(true)以及设置一些变量(网格的高度和宽度),然后getChildDrawingOrder本身 我的getChildDrawingOrder代码计算出给定子项的新索引,并将子项中的字符串设

我正在用简单的平铺创建一个等轴测地图,并扩展了
RelativeLayout
,以创建一个包含这些平铺的布局。实际上,只要我的方向与写入XML文件的瓷砖顺序相匹配,就可以使用
RelativeLayout
as;我所覆盖的是构造函数,我只需调用
super
setChildrenDrawingOrderEnabled(true)
以及设置一些变量(网格的高度和宽度),然后
getChildDrawingOrder
本身

我的
getChildDrawingOrder
代码计算出给定子项的新索引,并将子项中的字符串设置为
i->i'
,其中
i
是原始索引,
i'
是新索引。我用它来测试;孩子们被设置为在自己身上绘制这个字符串以及他们的坐标

不幸的是,它不能正常工作,或者说它工作不稳定。在我的测试用例中的九个tile中,有三个似乎根本没有调用
getChildDrawingOrder
:我上面提到的字符串是
null
。在其余的部分中,尽管得到了正确的索引,但至少有一个是无序绘制的

这是一张图片(在
顶部
方向):

请注意,(0,2)、(1,2)和(2,1)都列为
NULL
,因此似乎从未为它们调用过
getChildDrawingOrder
。还请注意,(1,0)绘制在(1,1)的顶部,即使其
i
(3)和
i'
(1)都小于(1,1)(分别为4和4)

以下是
getChildDrawingOrder
中的代码:

@Override
protected int getChildDrawingOrder(int childCount, int i)
{
    TileView ch = (TileView)getChildAt(i);
    ch.order = "Called"; // this string is drawn on my children
    int gx, gy; // the "true" x,y for the current rotation,
                // where 0,0 is the top corner
    switch (rotation)
    {
    case TOP:
        gx = ch.x();
        gy = ch.y();
        break;
    case LEFT:
        gx = (width()-1-ch.x());
        gy = ch.y();
        break;
    case RIGHT:
        gx = ch.x();
        gy = (length()-1-ch.y());
        break;
    case BOTTOM:
        gx = (width()-1-ch.x());
        gy = (length()-1-ch.y());
        break;
    default:
        gx = ch.x();
        gy = ch.y();
    }
    int row = gx+gy; // current row
    if ( row == 0 ) // row 0 is always just the top corner and 0
    {
        ch.order = new String(i+"->0"); // string set to i->i'
        return 0;
    }
    else
    {
        int mx = width()-1, // maximum x value
            my = length()-1, // maximum y value
            mrow = mx+my, // maximum row
            min = Math.min(mx, my), // minor axis length
            maj = Math.max(mx, my), // major axis length
            retn; // for storing the return value
        // inside the top corner
        if ( row <= min )
        {
            // Gauss's formula to get number of cells in previous rows
            // plus the number for which cell in this row this is.
            retn = row*(row+1)/2+gy;
        }
        // in the middle
        else if ( row <= maj )
        {
            // Gauss's formula to get number of cells in top corner
            // plus the number of cells in previous rows of the middle section
            // plus the number for which cell in this row this is.
            retn = min*(min+1)/2+min*(row-min)+gy;
        }
        // bottom corner
        else
        {
            retn = (min+1)*(min+2)/2 // cells in the top corner
                 + min*(maj-min) // cells in the middle
                 + (mrow-maj)*(mrow-maj+1)/2 // total cells in bottom triangle
                 - (mrow-row+1)*(mrow-row+2)/2 // less cells after this one
                 + gy // which cell in this row
                 - (row-maj) // to account for gy not starting at zero
                 ;
        }
        ch.order = new String(i+"->"+retn); // string set to i->i'
        return retn;
    }
}
@覆盖
受保护的int getChildDrawingOrder(int childCount,int i)
{
TileView ch=(TileView)getChildAt(i);
ch.order=“Called”;//这个字符串是在我的孩子身上画的
int gx,gy;//当前旋转的“真”x,y,
//其中0,0是顶角
开关(旋转)
{
案例顶部:
gx=ch.x();
gy=ch.y();
打破
案例左:
gx=(宽度()-1通道x());
gy=ch.y();
打破
案例权利:
gx=ch.x();
gy=(长度()-1通道y());
打破
箱底:
gx=(宽度()-1通道x());
gy=(长度()-1通道y());
打破
违约:
gx=ch.x();
gy=ch.y();
}
int row=gx+gy;//当前行
if(row==0)//第0行始终仅为上角,第0行
{
ch.order=新字符串(i+“->0”);//字符串设置为i->i'
返回0;
}
其他的
{
int mx=width()-1,//最大x值
my=length()-1,//最大y值
mrow=mx+my,//最大行数
min=Math.min(mx,my),//短轴长度
maj=Math.max(mx,my),//长轴长度
retn;//用于存储返回值
//在顶角内
如果(第一排)
返回retn;
}
}

有人能解释一下发生了什么吗?为什么没有为这三个tile调用
getChildDrawingOrder
?为什么是(1,0)以错误的顺序绘制,即使调用了
getChildDrawingOrder

好的,通过查看Android源代码来解决。我有
getChildDrawingOrder
的映射:传递的
I
是“我应该绘制哪个孩子?”而不是“我应该何时绘制孩子I?”
NULL
s的原因是,这些子对象是在传递自己的
i
之前绘制的

在测量过程中,我更改了代码以确定所有子项的顺序,并将其保存在一个
SparseIntArray
中,然后从
getChildDrawingOrder
返回。这很有效


顺便说一句,在
getChildDrawingOrder
函数中反向计算索引是个坏主意,除非您想依赖于子项声明的顺序。因为如果您不依赖于该顺序,您必须遍历子项列表以找到具有适当x和y值的子项,这意味着您必须浏览每个子项的子项列表。这是一个O(n²)操作(阅读:效率相当低)。数学也相当复杂。

下面是一个简单的示例,演示如何覆盖
getChildDrawingOrder

  • 作为一种调整哪个孩子按哪个顺序被画的方法(最后一个在上面)
  • 通过点击/点击事件更改订单
  • RelativeLayout类:

    public class AlternatingChildDrawingOrderRelativeLayout extends RelativeLayout {
    
        // the childDrawingOrder modifier
        private int childDrawingOrderModifier = 0;
    
        public AlternatingChildDrawingOrderRelativeLayout(Context context) {
            super(context);
            init(context);
        }
    
        void init(Context context) {
            setClickable(true);
            setChildrenDrawingOrderEnabled(true);
            setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // increment to adjust the child drawing order
                    childDrawingOrderModifier++;
                    // call invalidate to redraw with new order modifier
                    ViewCompat.postInvalidateOnAnimation(v);
                }
            });
        }
    
        @Override
        protected int getChildDrawingOrder(int childCount, int i) {
            // increment i with the modifier, then afford for out of bounds using modulus of the child count
            int returnValue = (i + childDrawingOrderModifier) % childCount;
            Log.v(VIEW_LOG_TAG, "getChildDrawingOrder returnValue=" + returnValue + " i=" + i);
            return returnValue;
        }
    
        public AlternatingChildDrawingOrderRelativeLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
    
        public AlternatingChildDrawingOrderRelativeLayout(Context context,
                                                          AttributeSet attrs,
                                                          int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context);
        }
    
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        public AlternatingChildDrawingOrderRelativeLayout(Context context,
                                                          AttributeSet attrs,
                                                          int defStyleAttr,
                                                          int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
            init(context);
        }
    
    }
    
    xml布局

    <?xml version="1.0" encoding="utf-8"?>
    <com.example.ui.AlternatingChildDrawingOrderRelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="300dp"
        android:layout_height="300dp">
    
        <View
            android:id="@+id/red"
            android:layout_width="125dp"
            android:layout_height="300dp"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:background="#f00"
            />
    
        <View
            android:id="@+id/green"
            android:layout_width="125dp"
            android:layout_height="300dp"
            android:layout_centerInParent="true"
            android:background="#0f0"/>
    
        <View
            android:id="@+id/blue"
            android:layout_width="125dp"
            android:layout_height="300dp"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:background="#00f"/>
    
    </com.example.ui.AlternatingChildDrawingOrderRelativeLayout>
    
    因此,从第一个到最后一个(或从下到上考虑),即:红色、绿色、蓝色。下面是调用的
    getChildDrawingOrder
    的日志转储

    V/View: getChildDrawingOrder returnValue=0 i=0
    V/View: getChildDrawingOrder returnValue=1 i=1
    V/View: getChildDrawingOrder returnValue=2 i=2
    
    在中间,我们第一次轻触后,顺序变为绿色、蓝色和红色

    V/View: getChildDrawingOrder returnValue=1 i=0
    V/View: getChildDrawingOrder returnValue=2 i=1
    V/View: getChildDrawingOrder returnValue=0 i=2
    
    右边显示了第二次点击后的外观,因为顺序变为:蓝色、红色、绿色

    V/View: getChildDrawingOrder returnValue=2 i=0
    V/View: getChildDrawingOrder returnValue=0 i=1
    V/View: getChildDrawingOrder returnValue=1 i=2
    
    在此之后的任何点击都会将其循环回原来的顺序,由于模数计算,蓝色最后一次被绘制


    HTHs!

    我觉得这需要更多的介绍。我已经远离Android开发多年了,所以我必须深入了解这段代码并理解它在做什么。如果不这样做,我甚至无法判断这是否是一个好答案。更多关于
    getChildDrawingOrder
    及其工作原理/使用方法的解释我想这会有帮助。我会添加一些图像来说明
    V/View: getChildDrawingOrder returnValue=2 i=0
    V/View: getChildDrawingOrder returnValue=0 i=1
    V/View: getChildDrawingOrder returnValue=1 i=2