已合并
fix: include attachments in nested text touch targets #1879
fix: include attachments in nested text touch targets #1879
已合并
Patryk Fryda创建于 2025年12月8日
共 3 个文件变更+65-9
@@ -199,6 +199,7 @@ class ArkUITypographyBuilder final {
199 m_textAlign = fragment.textAttributes.alignment;199 m_textAlign = fragment.textAttributes.alignment;
200 m_isInitTextAlign = true;200 m_isInitTextAlign = true;
201 }201 }
202+ m_fragmentLengths.emplace_back(utf16Length(fragment.string));
202 if (!fragment.isAttachment()) {203 if (!fragment.isAttachment()) {
203 addTextFragment(fragment);204 addTextFragment(fragment);
204 } else {205 } else {
@@ -394,7 +395,6 @@ class ArkUITypographyBuilder final {
394 m_styledString.get(), textStyle.get());395 m_styledString.get(), textStyle.get());
395 OH_ArkUI_StyledString_AddText(396 OH_ArkUI_StyledString_AddText(
396 m_styledString.get(), fragment.string.c_str());397 m_styledString.get(), fragment.string.c_str());
397- m_fragmentLengths.emplace_back(utf16Length(fragment.string));
398 // Pop to clear style from stack, preventing attachments from inheriting it.398 // Pop to clear style from stack, preventing attachments from inheriting it.
399 // If this function grows more complex (early returns, error handling), consider399 // If this function grows more complex (early returns, error handling), consider
400 // using RAII to guarantee `PopTextStyle` is called.400 // using RAII to guarantee `PopTextStyle` is called.
@@ -353,13 +353,10 @@ TextComponentInstance::getTouchTargetChildren() {
353 353 
354 auto const& fragments = m_state->getData().attributedString.getFragments();354 auto const& fragments = m_state->getData().attributedString.getFragments();
355 355 
356- auto attachmentCount = 0;
357 std::vector<TouchTarget::Shared> result;356 std::vector<TouchTarget::Shared> result;
358 for (auto const& fragment : fragments) {357 for (auto const& fragment : fragments) {
359- if (!fragment.isAttachment()) {358+ result.push_back(
360- result.push_back(359+ m_fragmentTouchTargetByTag.at(fragment.parentShadowView.tag));
361- m_fragmentTouchTargetByTag.at(fragment.parentShadowView.tag));
362- }
363 }360 }
364 result.insert(result.end(), m_children.begin(), m_children.end());361 result.insert(result.end(), m_children.begin(), m_children.end());
365 return result;362 return result;
@@ -397,9 +394,6 @@ void TextComponentInstance::updateFragmentTouchTargets(
397 FragmentTouchTargetByTag touchTargetByTag;394 FragmentTouchTargetByTag touchTargetByTag;
398 size_t textFragmentCount = 0;395 size_t textFragmentCount = 0;
399 for (auto const& fragment : fragments) {396 for (auto const& fragment : fragments) {
400- if (fragment.isAttachment()) {
401- continue;
402- }
403 auto index = textFragmentCount;397 auto index = textFragmentCount;
404 auto eventEmitter =398 auto eventEmitter =
405 std::dynamic_pointer_cast<const facebook::react::TouchEventEmitter>(399 std::dynamic_pointer_cast<const facebook::react::TouchEventEmitter>(
@@ -356,6 +356,43 @@ export function TextNestedTest() {
356 expect(state).to.be.true;356 expect(state).to.be.true;
357 }}357 }}
358 />358 />
359+ <TestCase.Manual
360+ itShould="pass after pressing area above the attachment"
361+ initialState={false}
362+ arrange={({setState, reset}) => {
363+ return (
364+ <NestedTextAttachmentTest
365+ onPress={() => {
366+ alert('text pressed');
367+ setState(true);
368+ }}
369+ reset={reset}
370+ />
371+ );
372+ }}
373+ assert={({expect, state}) => {
374+ expect(state).to.be.true;
375+ }}
376+ />
377+ <TestCase.Manual
378+ itShould="pass after pressing the last character"
379+ initialState={false}
380+ arrange={({setState, reset}) => {
381+ return (
382+ <NestedTextAttachmentTest
383+ attachmentWidth={0}
384+ onPress={() => {
385+ alert('text pressed');
386+ setState(true);
387+ }}
388+ reset={reset}
389+ />
390+ );
391+ }}
392+ assert={({expect, state}) => {
393+ expect(state).to.be.true;
394+ }}
395+ />
359 <TestCase.Example itShould="attachment does not inherit backgroundColor">396 <TestCase.Example itShould="attachment does not inherit backgroundColor">
360 <Text>397 <Text>
361 <Text398 <Text
@@ -526,6 +563,31 @@ const TextPressNestedTest = () => {
526 );563 );
527};564};
528 565 
566+const NestedTextAttachmentTest = ({
567+ attachmentWidth = 80,
568+ onPress,
569+ reset,
570+}: {
571+ attachmentWidth: number;
572+ onPress: () => void;
573+ reset: () => void;
574+}) => {
575+ return (
576+ <View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
577+ <Text>
578+ <Text style={{color: 'blue'}} onPress={onPress}>
579+ Blue text
580+ <View
581+ style={{width: attachmentWidth, height: 1, backgroundColor: 'red'}}
582+ />
583+ Hello world
584+ </Text>
585+ </Text>
586+ <Button label="Reset" onPress={reset} />
587+ </View>
588+ );
589+};
590+ 
529const styles = StyleSheet.create({591const styles = StyleSheet.create({
530 smallContainer: {592 smallContainer: {
531 width: 200,593 width: 200,