基于react native的锚点

基于react native的锚点

效果示例图

示例代码

/* eslint-disable react-native/no-inline-styles */
import React, { useEffect, useRef, useState } from 'react';
import {
  Image,
  ImageBackground,
  ScrollView,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import HTML from 'react-native-render-html';
import { pxToPd, pxToPdT } from '../../common/js/device';
const desc =
  '<p>如违反《赛事须知》中的内容,可能使我受到警告、判负、丧失比赛资格/获奖资格以及禁赛等赛事处罚,亦可能被请离现场。如违反《赛事须知》中的内容,可能使我受到警告、判负、丧失比赛资格/获奖资格以及禁赛等赛事处罚,亦可能被请离现场。如违反《赛事须知》中的内容,可能使我受到警告、判负、丧失比赛资格/获奖资格以及禁赛等赛事处罚,亦可能被请离现场。</p>';

const tempData = [
  {
    id: 1,
    name: '工藤新一一级标题',
    data: [
      {
        id: 2,
        name: '二级标题002',
        content: desc,
      },
      {
        id: 3,
        name: '二级标题003',
        content: desc,
      },
      {
        id: 4,
        name: '二级标题004',
        content: desc,
      },
    ],
  },
  {
    id: 5,
    name: '毛利兰一级标题',
    data: [
      {
        id: 6,
        name: '二级标题006',
        content: desc,
      },
      {
        id: 7,
        name: '二级标题007',
        content: desc,
      },
      {
        id: 8,
        name: '二级标题008',
        content: desc,
      },
    ],
  },
  {
    id: 9,
    name: '流放了一级标题',
    data: [
      {
        id: 10,
        name: '二级标题0010',
        content: desc,
      },
      {
        id: 11,
        name: '二级标题0011',
        content: desc,
      },
      {
        id: 12,
        name: '二级标题0012',
        content: desc,
      },
    ],
  },
];

const TestCatalog = () => {
  const scrollViewRef = useRef(null);

  //列表数据
  const [dataList, setDataList] = useState([]);

  const viewRefs = useRef([]);
  const menuRef = useRef([]);

  const initFunction = () => {
    setDataList(() => tempData);
  };

  const goSkipHandle = row => {
    let tempArr = menuRef.current;
    tempArr.some(item => {
      if (item.id === row.id) {
        scrollViewRef.current.scrollTo({ y: item?.y - 100, animated: true });
      }
    });
  };

  const getPositionValue = (row, y) => {
    let tempMenu = [...menuRef.current];
    let tempItem = row;
    if (tempItem.y === undefined) {
      tempItem.y = y;
    }
    tempMenu.push(row);
    menuRef.current = tempMenu;
  };

  useEffect(() => {
    initFunction();
    return () => {};
  }, []);
  return (
    <>
      <View style={{ flex: 1 }}>
        <ScrollView ref={scrollViewRef}>
          {/* 列表内容 */}
          {dataList?.map((item, index) => (
            <View
              style={styles.ruleBlock}
              key={'ruleBlock-' + index}
              ref={ref => {
                viewRefs.current[item?.id] = ref;
              }}
              onLayout={() => {
                if (viewRefs.current[item?.id]) {
                  viewRefs.current[item?.id].measure(
                    (x, y, width, height, pageX, pageY) => {
                      console.log(x, y, width, height, pageX);
                      getPositionValue(item, pageY);
                    },
                  );
                }
              }}>
              {/* 一级标题 */}
              <View style={styles.ruleBlockTitle}>
                <ImageBackground
                  style={styles.ruleBlockTitleBg}
                  source={require('../../common/imgs/main_ruleDetail_titleBg.png')}>
                  <Text
                    style={styles.ruleBlockTitleTxt}
                    ellipsizeMode="middle"
                    numberOfLines={1}>
                    {item?.name}
                  </Text>
                </ImageBackground>
              </View>
              {/* 装饰图 */}
              <Image
                style={styles.ruleBlockDecorate}
                source={require('../../common/imgs/main_ruleDetail_tips.png')}
              />
              {/* 列表内容-start */}
              {item?.data?.map((subitem, subindex) => (
                <View
                  style={styles.ruleBlockSubCon}
                  key={'ruleBlockSubCon-' + subindex}>
                  {/* 二级标题 */}
                  <View
                    style={styles.ruleBlockSubTitle}
                    ref={ref => {
                      viewRefs.current[subitem?.id] = ref;
                    }}
                    onLayout={() => {
                      if (viewRefs.current[subitem?.id]) {
                        viewRefs.current[subitem?.id].measure(
                          (x, y, width, height, pageX, pageY) => {
                            console.log(x, y, width, height, pageX);
                            getPositionValue(subitem, pageY);
                          },
                        );
                      }
                    }}>
                    <Text style={styles.ruleBlockSubTitleTxt}>
                      {subitem?.name}
                    </Text>
                  </View>
                  {/* 内容 */}
                  <View style={{ width: '100%', height: pxToPd(24) }} />
                  <View style={styles.ruleBlockSubDesc}>
                    <HTML
                      contentWidth={100}
                      source={{
                        html: `<div>${subitem?.content}</div>`,
                      }}
                    />
                  </View>
                </View>
              ))}

              {/* 列表内容-end*/}

              <View style={{ width: '100%', height: pxToPd(40) }} />
            </View>
          ))}
        </ScrollView>
      </View>
      <View style={styles.modalWrap}>
        {dataList?.map(item => (
          <View>
            <TouchableOpacity onPress={() => goSkipHandle(item)}>
              <Text
                style={{
                  width: '100%',
                  height: pxToPd(60),
                  lineHeight: pxToPd(60),
                  textAlign: 'center',
                }}>
                {item?.name}
              </Text>
            </TouchableOpacity>
            {item?.data?.map(subitem => (
              <TouchableOpacity onPress={() => goSkipHandle(subitem)}>
                <Text
                  style={{
                    width: '100%',
                    height: pxToPd(60),
                    lineHeight: pxToPd(60),
                    textAlign: 'center',
                  }}>
                  {subitem?.name}
                </Text>
              </TouchableOpacity>
            ))}
          </View>
        ))}
      </View>
    </>
  );
};

const styles = StyleSheet.create({
  detailBg: {
    width: '100%',
    height: pxToPd(1624),
  },
  container: {
    flex: 1,
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
  },
  //内容
  ruleBlock: {
    width: '93.6%',
    marginLeft: '3.2%',
    borderRadius: pxToPd(40),
    backgroundColor: '#fff',
    minHeight: pxToPd(400),
    position: 'relative',
    marginBottom: pxToPd(97),
  },
  ruleBlockTitle: {
    width: pxToPd(533),
    height: pxToPd(86),
    marginLeft: -pxToPd(8),
    marginTop: -pxToPd(8),
  },
  ruleBlockTitleBg: {
    width: '100%',
    height: '100%',
  },
  ruleBlockTitleTxt: {
    height: pxToPd(86),
    width: pxToPd(500),
    lineHeight: pxToPd(86),
    fontSize: pxToPdT(32),
    fontWeight: 'bold',
    color: '#fff',
    marginLeft: pxToPd(19),
  },
  ruleBlockDecorate: {
    width: pxToPd(160),
    height: pxToPd(193),
    position: 'absolute',
    top: -pxToPd(14),
    right: -pxToPd(1),
  },
  ruleBlockSubCon: {
    width: '93.6%',
    marginLeft: '3.2%',
    marginTop: pxToPd(42),
  },
  ruleBlockSubTitle: {
    width: '100%',
  },
  ruleBlockSubTitleTxt: {
    width: '100%',
    fontSize: pxToPdT(30),
    fontWeight: 'normal',
    color: '#333',
    textAlign: 'center',
  },
  ruleBlockSubDesc: {
    width: '100%',
  },
  modalWrap: {
    borderRadius: pxToPd(24),
    width: pxToPd(300),
    position: 'absolute',
    top: 100,
    right: 20,
    backgroundColor: '#f5f5f5',
    flexDirection: 'column',
  },
});

export default TestCatalog;
相关推荐
晨春计18 分钟前
【git】
android·linux·git
标标大人1 小时前
c语言中的局部跳转以及全局跳转
android·c语言·开发语言
木鬼与槐2 小时前
MySQL高阶1783-大满贯数量
android·数据库·mysql
iofomo2 小时前
【Abyss】Android 平台应用级系统调用拦截框架
android·开发工具·移动端
AirDroid_cn5 小时前
在家找不到手机?除了语音助手,还可以用远程控制!
android·智能手机·远程控制·手机使用技巧·远程控制手机
Good_tea_h12 小时前
Android中如何处理运行时权限?
android
冬田里的一把火313 小时前
[Android][Reboot/Shutdown] 重启/关机 分析
android·gitee
大海..13 小时前
Android 系统开发人员的权限说明文档
android
技术无疆16 小时前
ButterKnife:Android视图绑定的简化专家
android·java·android studio·android-studio·androidx·butterknife·视图绑定
JohnsonXin17 小时前
【兼容性记录】video标签在 IOS 和 安卓中的问题
android·前端·css·ios·h5·兼容性