setTouchEnabled()用于触摸的正确使用方法。

cocos2dx 不要直接在 onEnter 里面 addTargetedDelegate (或 addStandardDelegate)

 今天看别人 cocos2d 代码的时候发现个怪现象, 整个工程里面 没有 setTouchEnabled(true) 这样的代码, 但是程序跑起来的时候却可以响应 触屏事件。于是下断点跟踪啊跟踪,发现 m_bIsTouchEnabled 这个变量确实是 false。。 那么这个layer 到底是怎么响应触摸事件的呢?
 存在即合理,空穴不来风。经过别人提醒, 意识到原因在这里:

 virtual void onEnter(){
  CCLayer::onEnter();
  d->getTouchDispatcher()->addTargetedDelegate(this, 0, false);
 }


 类内覆写了 onEnter 函数,并且 addTargetedDelegate , 居然就可以不用 setTouchEnabled 了。 很有意思的样子, 那么不得不看一下 setTouchEnabled 是怎么工作的了。转到 CCLayer.cpp line:151,看到函数实现:

/// isTouchEnabled setter
void CCLayer::setTouchEnabled(bool enabled)
{
    if (m_bIsTouchEnabled != enabled)
    {
        m_bIsTouchEnabled = enabled;
        if (m_bIsRunning)
        {
            if (enabled)
            {
                this->registerWithTouchDispatcher();
            }
            else
            {
                // have problems?
                CCDirector* pDirector = CCDirector::sharedDirector();
                pDirector->getTouchDispatcher()->removeDelegate(this);
            }
        }
    }
}


这个setTouchEnabled 函数做两件事情: 
1. 赋值 m_bIsTouchEnabled = enabled
2. if(m_bIsRunning){ if (enabled) this->registerWithTouchDispatcher(); else removeDelegate(this); }
注意: 这里首先判断 if( m_bIsRunning),就是说,如果在初始化 函数init 里面设定 setTouchEnabled(true), 这时候还没 run起来,所以并不会执行这一段。否则这里 register一次, onEnter 里面默认再 register一次程序就会出问题了

那么 registerWithTouchDispatcher() 干什么事情呢?
跳转到定义可以看到:

void CCLayer::registerWithTouchDispatcher()
{
    CCDirector* pDirector = CCDirector::sharedDirector();
    if (m_pScriptHandlerEntry)
    {
        if (m_pScriptHandlerEntry->isMultiTouches())
        {
            pDirector->getTouchDispatcher()->addStandardDelegate(this, 0);
            LUALOG("[LUA] Add multi-touches event handler: %d", m_pScriptHandlerEntry->getHandler());
        }
        else
        {
            pDirector->getTouchDispatcher()->addTargetedDelegate(this,
                                                                       m_pScriptHandlerEntry->getPriority(),
                                                                       m_pScriptHandlerEntry->getSwallowsTouches());
            LUALOG("[LUA] Add touch event handler: %d", m_pScriptHandlerEntry->getHandler());
        }
        return;
    }
    pDirector->getTouchDispatcher()->addStandardDelegate(this,0);
}


除去if (m_pScriptHandlerEntry) 那一段不管(似乎是用来控制 script 代码的行为,我也不大懂), 函数主要做的事情就是一句话:

pDirector->getTouchDispatcher()->addStandardDelegate(this,0);



就是说,默认情况下, CCLayer 注册的是 standardDelegate。

理顺一下, 我们的代码应该:
1. init 函数里面设置 setTouchEnabled(true);
2. 类内覆写函数 registerWithTouchDispatcher, 设置 addStandardDelegate 或者 targetedDelegate,
这样,当初始化时调用 setTouchEnabled(true) 的时候,首先会设置 m_bIsTouchEnabled 为 true, 由于 m_bIsRunning==false, 这时还不会 registerWithTouchDispatcher。 然后程序run起来, 调用 onEnter 函数的时候,这里会(见 CCLayer.cpp line:233):

    if (m_bIsTouchEnabled)
    {
        this->registerWithTouchDispatcher();
    }


如果没有 setTouchEnabled, 没有覆写 registerWithTouchDispatcher,而是直接覆写的 onEnter函数,像本文一开始提到的:

 virtual void onEnter(){
  CCLayer::onEnter();
  d->getTouchDispatcher()->addTargetedDelegate(this, 0, false);
 }


会怎样?会节省代码吗?不会。因为 m_bIsTouchEnabled==false, 所以 onExit 的时候, CCLayer::onExit() 并不会 removeDelegate, 所以我们还需要手动再覆写 onExit 函数,像这样:

void TestLayer::onExit()
{
    CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
    CCLayer::onExit();
}


同时, 因为 m_bIsTouchEnabled==false, 当你注意到这里的时候你总会陷入逻辑混乱: 没有 enable touch 这个类居然也可以响应触摸!! 就像我看人家代码一样郁闷。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用LineChart绘制折线图的基本步骤如下: 1. 添加依赖:在项目的build.gradle文件中添加依赖: ```gradle implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' ``` 2. 在布局文件中添加LineChart控件: ```xml <com.github.mikephil.charting.charts.LineChart android:id="@+id/line_chart" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 3. 在Java代码中获取LineChart控件的实例,并设置数据: ```java LineChart lineChart = findViewById(R.id.line_chart); List<Entry> entries = new ArrayList<>(); entries.add(new Entry(0, 20)); entries.add(new Entry(1, 50)); entries.add(new Entry(2, 30)); entries.add(new Entry(3, 80)); entries.add(new Entry(4, 60)); LineDataSet dataSet = new LineDataSet(entries, "Label"); // 设置数据集 LineData lineData = new LineData(dataSet); // 设置LineData lineChart.setData(lineData); // 将数据设置到LineChart控件中 ``` 4. 设置LineChart的样式和交互效果: ```java // 设置LineChart的样式 dataSet.setColor(Color.RED); // 设置线条颜色 dataSet.setLineWidth(2f); // 设置线条宽度 dataSet.setCircleColor(Color.BLUE); // 设置圆点颜色 dataSet.setCircleRadius(5f); // 设置圆点半径 dataSet.setDrawValues(false); // 设置是否显示每个点的值 // 设置LineChart的交互效果 lineChart.setTouchEnabled(true); // 开启触摸事件 lineChart.setDragEnabled(true); // 开启拖拽事件 lineChart.setScaleEnabled(true); // 开启缩放事件 lineChart.setPinchZoom(true); // 开启双指缩放事件 lineChart.setHighlightPerDragEnabled(true); // 开启拖拽时高亮选中 ``` 以上是LineChart的基本使用方法,你可以根据自己的需求进一步定制和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值