田子悦 2 weeks ago
parent 46c49dd1d9
commit 391c5f1410

BIN
.DS_Store vendored

Binary file not shown.

BIN
android/.DS_Store vendored

Binary file not shown.

@ -1,2 +1,2 @@
#Mon Apr 21 08:14:16 CST 2025
#Fri Apr 25 19:53:19 CST 2025
gradle.version=8.5

@ -1,2 +1,2 @@
#Mon Apr 21 08:12:48 CST 2025
#Fri Apr 25 19:53:31 CST 2025
java.home=/Applications/Android Studio.app/Contents/jbr/Contents/Home

Binary file not shown.

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WizardSettings">
<option name="children">
<map>
<entry key="imageWizard">
<value>
<PersistentState />
</value>
</entry>
</map>
</option>
</component>
</project>

@ -1,607 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DeviceStreaming">
<option name="deviceSelectionList">
<list>
<PersistentDeviceSelectionData>
<option name="api" value="27" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="F01L" />
<option name="id" value="F01L" />
<option name="labId" value="google" />
<option name="manufacturer" value="FUJITSU" />
<option name="name" value="F-01L" />
<option name="screenDensity" value="360" />
<option name="screenX" value="720" />
<option name="screenY" value="1280" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="OnePlus" />
<option name="codename" value="OP5552L1" />
<option name="id" value="OP5552L1" />
<option name="labId" value="google" />
<option name="manufacturer" value="OnePlus" />
<option name="name" value="CPH2415" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2412" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="OPPO" />
<option name="codename" value="OP573DL1" />
<option name="id" value="OP573DL1" />
<option name="labId" value="google" />
<option name="manufacturer" value="OPPO" />
<option name="name" value="CPH2557" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="28" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="SH-01L" />
<option name="id" value="SH-01L" />
<option name="labId" value="google" />
<option name="manufacturer" value="SHARP" />
<option name="name" value="AQUOS sense2 SH-01L" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="Lenovo" />
<option name="codename" value="TB370FU" />
<option name="formFactor" value="Tablet" />
<option name="id" value="TB370FU" />
<option name="labId" value="google" />
<option name="manufacturer" value="Lenovo" />
<option name="name" value="Tab P12" />
<option name="screenDensity" value="340" />
<option name="screenX" value="1840" />
<option name="screenY" value="2944" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="a15" />
<option name="id" value="a15" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="A15" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="a35x" />
<option name="id" value="a35x" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="A35" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="samsung" />
<option name="codename" value="a51" />
<option name="id" value="a51" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy A51" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="akita" />
<option name="id" value="akita" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="motorola" />
<option name="codename" value="arcfox" />
<option name="id" value="arcfox" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="razr plus 2024" />
<option name="screenDensity" value="360" />
<option name="screenX" value="1080" />
<option name="screenY" value="1272" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="motorola" />
<option name="codename" value="austin" />
<option name="id" value="austin" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="moto g 5G (2022)" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="b0q" />
<option name="id" value="b0q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S22 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="32" />
<option name="brand" value="google" />
<option name="codename" value="bluejay" />
<option name="id" value="bluejay" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="caiman" />
<option name="id" value="caiman" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro" />
<option name="screenDensity" value="360" />
<option name="screenX" value="960" />
<option name="screenY" value="2142" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="comet" />
<option name="default" value="true" />
<option name="id" value="comet" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro Fold" />
<option name="screenDensity" value="390" />
<option name="screenX" value="2076" />
<option name="screenY" value="2152" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="29" />
<option name="brand" value="samsung" />
<option name="codename" value="crownqlteue" />
<option name="id" value="crownqlteue" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Note9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2220" />
<option name="screenY" value="1080" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="dm2q" />
<option name="id" value="dm2q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="S23 Plus" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="dm3q" />
<option name="id" value="dm3q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S23 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="e1q" />
<option name="default" value="true" />
<option name="id" value="e1q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S24" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="e3q" />
<option name="id" value="e3q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S24 Ultra" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1440" />
<option name="screenY" value="3120" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="eos" />
<option name="id" value="eos" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Eos" />
<option name="screenDensity" value="320" />
<option name="screenX" value="384" />
<option name="screenY" value="384" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix" />
<option name="id" value="felix" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="felix" />
<option name="id" value="felix" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix_camera" />
<option name="id" value="felix_camera" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold (Camera-enabled)" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="motorola" />
<option name="codename" value="fogona" />
<option name="id" value="fogona" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="moto g play - 2024" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="g0q" />
<option name="id" value="g0q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-S906U1" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="gta9pwifi" />
<option name="id" value="gta9pwifi" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-X210" />
<option name="screenDensity" value="240" />
<option name="screenX" value="1200" />
<option name="screenY" value="1920" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="gts7xllite" />
<option name="id" value="gts7xllite" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-T738U" />
<option name="screenDensity" value="340" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="gts8uwifi" />
<option name="formFactor" value="Tablet" />
<option name="id" value="gts8uwifi" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Tab S8 Ultra" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1848" />
<option name="screenY" value="2960" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="gts8wifi" />
<option name="formFactor" value="Tablet" />
<option name="id" value="gts8wifi" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Tab S8" />
<option name="screenDensity" value="274" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="gts9fe" />
<option name="id" value="gts9fe" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Tab S9 FE 5G" />
<option name="screenDensity" value="280" />
<option name="screenX" value="1440" />
<option name="screenY" value="2304" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="husky" />
<option name="id" value="husky" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8 Pro" />
<option name="screenDensity" value="390" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="motorola" />
<option name="codename" value="java" />
<option name="id" value="java" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="G20" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="komodo" />
<option name="id" value="komodo" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro XL" />
<option name="screenDensity" value="360" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="lynx" />
<option name="id" value="lynx" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="motorola" />
<option name="codename" value="maui" />
<option name="id" value="maui" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="moto g play - 2023" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="o1q" />
<option name="id" value="o1q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S21" />
<option name="screenDensity" value="421" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="google" />
<option name="codename" value="oriole" />
<option name="id" value="oriole" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="panther" />
<option name="id" value="panther" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="q5q" />
<option name="id" value="q5q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Z Fold5" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1812" />
<option name="screenY" value="2176" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="q6q" />
<option name="id" value="q6q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Z Fold6" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1856" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="r11" />
<option name="formFactor" value="Wear OS" />
<option name="id" value="r11" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Watch" />
<option name="screenDensity" value="320" />
<option name="screenX" value="384" />
<option name="screenY" value="384" />
<option name="type" value="WEAR_OS" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="r11q" />
<option name="id" value="r11q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-S711U" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="redfin" />
<option name="id" value="redfin" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 5" />
<option name="screenDensity" value="440" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="shiba" />
<option name="id" value="shiba" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="t2q" />
<option name="id" value="t2q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S21 Plus" />
<option name="screenDensity" value="394" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="tangorpro" />
<option name="formFactor" value="Tablet" />
<option name="id" value="tangorpro" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Tablet" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="tokay" />
<option name="default" value="true" />
<option name="id" value="tokay" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2424" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="35" />
<option name="brand" value="google" />
<option name="codename" value="tokay" />
<option name="default" value="true" />
<option name="id" value="tokay" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2424" />
</PersistentDeviceSelectionData>
</list>
</option>
</component>
</project>

@ -2,9 +2,6 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RenderSettings">
<option name="showDecorations" value="true" />
</component>
</project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -13,12 +13,23 @@
android:roundIcon="@drawable/ic_launcher"
android:supportsRtl="true"
android:theme="@style/Theme.PoseEstimation">
<activity android:name=".MainActivity">
<activity android:name=".SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity" />
<activity android:name=".GenderSelectionActivity" />
<activity android:name=".AgeSelectionActivity" />
<activity android:name=".Onboarding1Activity" />
<activity android:name=".OnboardingActivity" />
<activity
android:name=".WeightSelectionActivity"
android:exported="false" />
<activity
android:name=".HeightSelectionActivity"
android:exported="false" />
</application>
</manifest>

Binary file not shown.

Binary file not shown.

@ -0,0 +1,120 @@
package org.tensorflow.lite.examples.poseestimation
import android.content.Intent
import android.os.Bundle
import android.view.MotionEvent
import android.widget.ImageButton
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.button.MaterialButton
import kotlin.math.abs
class AgeSelectionActivity : AppCompatActivity() {
private lateinit var selectedAgeText: TextView
private lateinit var age1Above: TextView
private lateinit var age2Above: TextView
private lateinit var age1Below: TextView
private lateinit var age2Below: TextView
private lateinit var nextButton: MaterialButton
private lateinit var backButton: ImageButton
private var selectedGender: String? = null
private var currentAge = 25
private val minAge = 12
private val maxAge = 90
private var lastY: Float = 0f
private val scrollSensitivity = 15f // 调整这个值可以改变滑动灵敏度
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_age_selection)
selectedGender = intent.getStringExtra("selected_gender")
selectedAgeText = findViewById(R.id.selectedAgeText)
age1Above = findViewById(R.id.age1Above)
age2Above = findViewById(R.id.age2Above)
age1Below = findViewById(R.id.age1Below)
age2Below = findViewById(R.id.age2Below)
nextButton = findViewById(R.id.nextButton)
backButton = findViewById(R.id.backButton)
setupUI()
setupClickListeners()
}
private fun setupUI() {
updateAgeDisplay()
nextButton.isEnabled = true
}
private fun updateAgeDisplay() {
selectedAgeText.text = currentAge.toString()
// 更新上方年龄(显示较小的数字)
if (currentAge - 1 >= minAge) {
age1Above.text = (currentAge - 1).toString()
} else {
age1Above.text = ""
}
if (currentAge - 2 >= minAge) {
age2Above.text = (currentAge - 2).toString()
} else {
age2Above.text = ""
}
// 更新下方年龄(显示较大的数字)
if (currentAge + 1 <= maxAge) {
age1Below.text = (currentAge + 1).toString()
} else {
age1Below.text = ""
}
if (currentAge + 2 <= maxAge) {
age2Below.text = (currentAge + 2).toString()
} else {
age2Below.text = ""
}
}
private fun setupClickListeners() {
nextButton.setOnClickListener {
val intent = Intent(this, WeightSelectionActivity::class.java)
intent.putExtra("selected_gender", selectedGender)
intent.putExtra("selected_age", currentAge)
startActivity(intent)
finish()
}
backButton.setOnClickListener {
finish()
}
}
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
lastY = event.y
return true
}
MotionEvent.ACTION_MOVE -> {
val currentY = event.y
val deltaY = currentY - lastY
// 计算应该改变多少年龄
val change = -(deltaY / scrollSensitivity).toInt()
if (abs(change) > 0) {
// 更新年龄
val newAge = (currentAge + change).coerceIn(minAge, maxAge)
if (newAge != currentAge) {
currentAge = newAge
updateAgeDisplay()
lastY = currentY
}
}
return true
}
}
return super.onTouchEvent(event)
}
}

@ -0,0 +1,105 @@
package org.tensorflow.lite.examples.poseestimation
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.core.content.ContextCompat
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
class CustomWeightPicker @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private val paint = Paint().apply {
isAntiAlias = true
color = ContextCompat.getColor(context, R.color.purple_500)
}
private val path = Path()
private var lastX = 0f
private var scrollOffset = 0f
private var selectedWeight = 54
private val minWeight = 30
private val maxWeight = 200
private val scaleWidth = 40f // 每个刻度的宽度
private val scaleHeight = 20f // 刻度的高度
private val centerLineWidth = 2f
private var onWeightChangeListener: ((Int) -> Unit)? = null
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val centerX = width / 2f
val centerY = height / 2f
// 绘制刻度
val startX = centerX + scrollOffset
val startWeight = selectedWeight - (centerX / scaleWidth).toInt()
for (i in -10..10) {
val x = startX + i * scaleWidth
val weight = startWeight + i
if (weight in minWeight..maxWeight) {
// 绘制刻度线
canvas.drawLine(
x,
centerY - scaleHeight,
x,
centerY + scaleHeight,
paint
)
// 绘制刻度值
if (i % 2 == 0) {
canvas.drawText(
weight.toString(),
x - 10f,
centerY + scaleHeight + 20f,
paint
)
}
}
}
}
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
lastX = event.x
return true
}
MotionEvent.ACTION_MOVE -> {
val deltaX = event.x - lastX
scrollOffset += deltaX
// 计算新的体重值
val newWeight = selectedWeight - (deltaX / scaleWidth).toInt()
if (newWeight in minWeight..maxWeight) {
selectedWeight = newWeight
onWeightChangeListener?.invoke(selectedWeight)
}
lastX = event.x
invalidate()
return true
}
}
return super.onTouchEvent(event)
}
fun setOnWeightChangeListener(listener: (Int) -> Unit) {
onWeightChangeListener = listener
}
fun getSelectedWeight(): Int = selectedWeight
}

@ -0,0 +1,70 @@
package org.tensorflow.lite.examples.poseestimation
import android.content.Intent
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.cardview.widget.CardView
import com.google.android.material.button.MaterialButton
class GenderSelectionActivity : AppCompatActivity() {
private lateinit var maleButton: CardView
private lateinit var femaleButton: CardView
private lateinit var maleText: TextView
private lateinit var femaleText: TextView
private lateinit var nextButton: MaterialButton
private var selectedGender: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_gender_selection)
maleButton = findViewById(R.id.maleButton)
femaleButton = findViewById(R.id.femaleButton)
maleText = findViewById(R.id.maleText)
femaleText = findViewById(R.id.femaleText)
nextButton = findViewById(R.id.nextButton)
setupClickListeners()
}
private fun setupClickListeners() {
maleButton.setOnClickListener {
updateSelection("male")
}
femaleButton.setOnClickListener {
updateSelection("female")
}
nextButton.setOnClickListener {
// 跳转到年龄选择页面,并传递性别信息
val intent = Intent(this, AgeSelectionActivity::class.java)
intent.putExtra("selected_gender", selectedGender)
startActivity(intent)
}
}
private fun updateSelection(gender: String) {
selectedGender = gender
// 更新UI状态
when (gender) {
"male" -> {
maleButton.setCardBackgroundColor(getColor(android.R.color.holo_purple))
femaleButton.setCardBackgroundColor(getColor(android.R.color.darker_gray))
maleText.setTextColor(getColor(android.R.color.holo_purple))
femaleText.setTextColor(getColor(android.R.color.white))
}
"female" -> {
femaleButton.setCardBackgroundColor(getColor(android.R.color.holo_purple))
maleButton.setCardBackgroundColor(getColor(android.R.color.darker_gray))
femaleText.setTextColor(getColor(android.R.color.holo_purple))
maleText.setTextColor(getColor(android.R.color.white))
}
}
// 启用Next按钮
nextButton.isEnabled = true
}
}

@ -0,0 +1,129 @@
package org.tensorflow.lite.examples.poseestimation
import android.content.Intent
import android.os.Bundle
import android.view.MotionEvent
import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.button.MaterialButton
import kotlin.math.abs
class HeightSelectionActivity : AppCompatActivity() {
private lateinit var selectedHeightText: TextView
private lateinit var heightUnit: TextView
private lateinit var height1Above: TextView
private lateinit var height2Above: TextView
private lateinit var height1Below: TextView
private lateinit var height2Below: TextView
private lateinit var nextButton: MaterialButton
private lateinit var backButton: ImageButton
private var selectedGender: String? = null
private var selectedAge: Int = 0
private var selectedWeight: Int = 0
private var currentHeight = 167
private val minHeight = 100
private val maxHeight = 220
private var lastY: Float = 0f
private val scrollSensitivity = 15f // 调整这个值可以改变滑动灵敏度
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_height_selection)
selectedGender = intent.getStringExtra("selected_gender")
selectedAge = intent.getIntExtra("selected_age", 0)
selectedWeight = intent.getIntExtra("selected_weight", 0)
selectedHeightText = findViewById(R.id.selectedHeightText)
heightUnit = findViewById(R.id.heightUnit)
height1Above = findViewById(R.id.height1Above)
height2Above = findViewById(R.id.height2Above)
height1Below = findViewById(R.id.height1Below)
height2Below = findViewById(R.id.height2Below)
nextButton = findViewById(R.id.nextButton)
backButton = findViewById(R.id.backButton)
setupUI()
setupClickListeners()
}
private fun setupUI() {
updateHeightDisplay()
nextButton.isEnabled = true
}
private fun updateHeightDisplay() {
selectedHeightText.text = currentHeight.toString()
// 上方身高
if (currentHeight - 1 >= minHeight) {
height1Above.text = (currentHeight - 1).toString()
} else {
height1Above.text = ""
}
if (currentHeight - 2 >= minHeight) {
height2Above.text = (currentHeight - 2).toString()
} else {
height2Above.text = ""
}
// 下方身高
if (currentHeight + 1 <= maxHeight) {
height1Below.text = (currentHeight + 1).toString()
} else {
height1Below.text = ""
}
if (currentHeight + 2 <= maxHeight) {
height2Below.text = (currentHeight + 2).toString()
} else {
height2Below.text = ""
}
}
private fun setupClickListeners() {
nextButton.setOnClickListener {
val intent = Intent(this, MainActivity::class.java)
intent.putExtra("selected_gender", selectedGender)
intent.putExtra("selected_age", selectedAge)
intent.putExtra("selected_weight", selectedWeight)
intent.putExtra("selected_height", currentHeight)
startActivity(intent)
finish()
}
backButton.setOnClickListener {
val intent = Intent(this, WeightSelectionActivity::class.java)
intent.putExtra("selected_gender", selectedGender)
intent.putExtra("selected_age", selectedAge)
intent.putExtra("selected_weight", selectedWeight)
startActivity(intent)
finish()
}
}
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
lastY = event.y
return true
}
MotionEvent.ACTION_MOVE -> {
val currentY = event.y
val deltaY = currentY - lastY
val change = -(deltaY / scrollSensitivity).toInt()
if (abs(change) > 0) {
val newHeight = (currentHeight + change).coerceIn(minHeight, maxHeight)
if (newHeight != currentHeight) {
currentHeight = newHeight
updateHeightDisplay()
lastY = currentY
}
}
return true
}
}
return super.onTouchEvent(event)
}
}

@ -0,0 +1,16 @@
package org.tensorflow.lite.examples.poseestimation
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
class Onboarding1Fragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.activity_onboarding1, container, false)
}
}

@ -0,0 +1,16 @@
package org.tensorflow.lite.examples.poseestimation
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
class Onboarding2Fragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.activity_onboarding2, container, false)
}
}

@ -0,0 +1,29 @@
package org.tensorflow.lite.examples.poseestimation
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.fragment.app.Fragment
class Onboarding3Fragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.activity_onboarding3, container, false)
// 找到Start now按钮并设置点击事件
val startButton = view.findViewById<FrameLayout>(R.id.small_butto_container)
startButton.setOnClickListener {
// 跳转到性别选择页面
val intent = Intent(requireActivity(), GenderSelectionActivity::class.java)
startActivity(intent)
requireActivity().finish() // 结束当前的OnboardingActivity
}
return view
}
}

@ -0,0 +1,15 @@
package org.tensorflow.lite.examples.poseestimation
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager2.widget.ViewPager2
class OnboardingActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_onboarding)
val viewPager = findViewById<ViewPager2>(R.id.viewPager)
viewPager.adapter = OnboardingAdapter(this)
}
}

@ -0,0 +1,18 @@
package org.tensorflow.lite.examples.poseestimation
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
class OnboardingAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
override fun getItemCount(): Int = 3
override fun createFragment(position: Int): Fragment {
return when (position) {
0 -> Onboarding1Fragment()
1 -> Onboarding2Fragment()
2 -> Onboarding3Fragment()
else -> Onboarding1Fragment()
}
}
}

@ -0,0 +1,50 @@
package org.tensorflow.lite.examples.poseestimation
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.View
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
val textView = findViewById<TextView>(R.id.some_id)
val vector1 = findViewById<View>(R.id.vector1)
val vector2 = findViewById<View>(R.id.vector2)
// 获取屏幕高度
val screenHeight = resources.displayMetrics.heightPixels
val margin = screenHeight / 8
textView.post {
val textViewLocation = IntArray(2)
textView.getLocationOnScreen(textViewLocation)
val textViewTop = textViewLocation[1]
val textViewBottom = textViewTop + textView.height
// 设置vector1在TextView上方右对齐
val params1 = vector1.layoutParams as RelativeLayout.LayoutParams
params1.addRule(RelativeLayout.ALIGN_PARENT_RIGHT)
params1.topMargin = textViewTop - margin - vector1.layoutParams.height
vector1.layoutParams = params1
// 设置vector2在TextView下方左对齐
val params2 = vector2.layoutParams as RelativeLayout.LayoutParams
params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
params2.topMargin = textViewBottom + margin
vector2.layoutParams = params2
}
// 2秒后跳转到引导页
Handler(Looper.getMainLooper()).postDelayed({
startActivity(Intent(this, OnboardingActivity::class.java))
finish()
}, 2000)
}
}

@ -0,0 +1,128 @@
package org.tensorflow.lite.examples.poseestimation
import android.content.Intent
import android.os.Bundle
import android.view.MotionEvent
import android.widget.ImageButton
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.button.MaterialButton
import kotlin.math.abs
class WeightSelectionActivity : AppCompatActivity() {
private lateinit var selectedWeightText: TextView
private lateinit var weight1Above: TextView
private lateinit var weight2Above: TextView
private lateinit var weight1Below: TextView
private lateinit var weight2Below: TextView
private lateinit var nextButton: MaterialButton
private lateinit var backButton: ImageButton
private var selectedGender: String? = null
private var selectedAge: Int = 0
private var currentWeight = 54
private var lastY: Float = 0f
private val scrollSensitivity = 15f // 调整这个值可以改变滑动灵敏度
private val minWeight = 30
private val maxWeight = 200
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_weight_selection)
// 获取从上一个页面传递的数据
selectedGender = intent.getStringExtra("selected_gender")
selectedAge = intent.getIntExtra("selected_age", 0)
// 初始化视图
selectedWeightText = findViewById(R.id.selectedWeightText)
weight1Above = findViewById(R.id.weight1Above)
weight2Above = findViewById(R.id.weight2Above)
weight1Below = findViewById(R.id.weight1Below)
weight2Below = findViewById(R.id.weight2Below)
nextButton = findViewById(R.id.nextButton)
backButton = findViewById(R.id.backButton)
setupUI()
setupClickListeners()
}
private fun setupUI() {
updateWeightDisplay()
nextButton.isEnabled = true
}
private fun updateWeightDisplay() {
selectedWeightText.text = currentWeight.toString()
// 更新上方体重(显示较小的数字)
if (currentWeight - 1 >= minWeight) {
weight1Above.text = (currentWeight - 1).toString()
} else {
weight1Above.text = ""
}
if (currentWeight - 2 >= minWeight) {
weight2Above.text = (currentWeight - 2).toString()
} else {
weight2Above.text = ""
}
// 更新下方体重(显示较大的数字)
if (currentWeight + 1 <= maxWeight) {
weight1Below.text = (currentWeight + 1).toString()
} else {
weight1Below.text = ""
}
if (currentWeight + 2 <= maxWeight) {
weight2Below.text = (currentWeight + 2).toString()
} else {
weight2Below.text = ""
}
}
private fun setupClickListeners() {
nextButton.setOnClickListener {
val intent = Intent(this, HeightSelectionActivity::class.java)
intent.putExtra("selected_gender", selectedGender)
intent.putExtra("selected_age", selectedAge)
intent.putExtra("selected_weight", currentWeight)
startActivity(intent)
finish()
}
backButton.setOnClickListener {
val intent = Intent(this, AgeSelectionActivity::class.java)
intent.putExtra("selected_gender", selectedGender)
startActivity(intent)
finish()
}
}
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
lastY = event.y
return true
}
MotionEvent.ACTION_MOVE -> {
val currentY = event.y
val deltaY = currentY - lastY
// 计算应该改变多少体重
val change = -(deltaY / scrollSensitivity).toInt()
if (abs(change) > 0) {
// 更新体重
val newWeight = (currentWeight + change).coerceIn(minWeight, maxWeight)
if (newWeight != currentWeight) {
currentWeight = newWeight
updateWeightDisplay()
lastY = currentY
}
}
return true
}
}
return super.onTouchEvent(event)
}
}

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#333333" />
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 647 B

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFF"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 957 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

@ -0,0 +1,18 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="185dp"
android:height="50dp"
android:viewportWidth="185"
android:viewportHeight="50"
>
<group>
<clip-path
android:pathData="M25 0H160C173.807 0 185 11.1929 185 25C185 38.8071 173.807 50 160 50H25C11.1929 50 0 38.8071 0 25C0 11.1929 11.1929 0 25 0Z"
/>
<path
android:pathData="M0 0V50H185V0"
android:fillColor="#BF5AF2"
/>
</group>
</vector>

@ -0,0 +1,14 @@
<!-- drawable/vector.xml -->
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="269.5dp"
android:height="63.46dp"
android:viewportWidth="269.5"
android:viewportHeight="63.46">
<path
android:pathData="M269.5,0 L0,63.46"
android:strokeWidth="1"
android:strokeColor="#BF5AF2"
android:fillColor="@android:color/transparent"/>
</vector>

@ -0,0 +1 @@
// 该文件仅用于占位,实际字体文件请放在本目录下。

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<TextView
android:id="@+id/titleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="64dp"
android:text="How old are you?"
android:textColor="@android:color/white"
android:textSize="28sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/subtitleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="This helps us create your personalized plan"
android:textAlignment="center"
android:textColor="#808080"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/titleText" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/agePickerContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="32dp"
app:layout_constraintBottom_toTopOf="@id/nextButton"
app:layout_constraintTop_toBottomOf="@id/subtitleText">
<TextView
android:id="@+id/age2Above"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#404040"
android:textSize="60sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/age1Above"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/age1Above"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#808080"
android:textSize="80sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/selectedAgeText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/selectedAgeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="100sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/age1Below"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#808080"
android:textSize="80sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/selectedAgeText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/age2Below"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#404040"
android:textSize="60sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/age1Below"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<View
android:id="@+id/topDivider"
android:layout_width="200dp"
android:layout_height="4dp"
android:background="#BF5AF2"
app:layout_constraintBottom_toTopOf="@id/selectedAgeText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginBottom="0dp" />
<View
android:id="@+id/bottomDivider"
android:layout_width="200dp"
android:layout_height="4dp"
android:background="#BF5AF2"
app:layout_constraintTop_toBottomOf="@id/selectedAgeText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="0dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageButton
android:id="@+id/backButton"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="16dp"
android:layout_marginBottom="32dp"
android:background="@drawable/circle_button_background"
android:src="@drawable/ic_back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/nextButton"
android:layout_width="141dp"
android:layout_height="50dp"
android:layout_marginBottom="32dp"
android:text="Next"
android:textSize="17sp"
android:textAllCaps="false"
android:textColor="#FFFFFF"
app:backgroundTint="#BF5AF2"
app:cornerRadius="25dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<TextView
android:id="@+id/titleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="64dp"
android:text="Tell us about yourself!"
android:textColor="@android:color/white"
android:textSize="28sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/subtitleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="To give you a better experience we need\nto know your gender"
android:textAlignment="center"
android:textColor="#808080"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/titleText" />
<androidx.cardview.widget.CardView
android:id="@+id/maleButton"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_marginTop="64dp"
app:cardBackgroundColor="#333333"
app:cardCornerRadius="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/subtitleText">
<ImageView
android:id="@+id/maleIcon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:src="@drawable/male" />
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/maleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Male"
android:textColor="@android:color/white"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="@id/maleButton"
app:layout_constraintStart_toStartOf="@id/maleButton"
app:layout_constraintTop_toBottomOf="@id/maleButton" />
<androidx.cardview.widget.CardView
android:id="@+id/femaleButton"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_marginTop="32dp"
app:cardBackgroundColor="#333333"
app:cardCornerRadius="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/maleText">
<ImageView
android:id="@+id/femaleIcon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:src="@drawable/female" />
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/femaleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Female"
android:textColor="@android:color/white"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="@id/femaleButton"
app:layout_constraintStart_toStartOf="@id/femaleButton"
app:layout_constraintTop_toBottomOf="@id/femaleButton" />
<com.google.android.material.button.MaterialButton
android:id="@+id/nextButton"
android:layout_width="141dp"
android:layout_height="50dp"
android:layout_marginBottom="32dp"
android:enabled="false"
android:text="Next"
android:textSize="17sp"
android:textAllCaps="false"
android:textColor="#FFFFFF"
app:backgroundTint="#BF5AF2"
app:cornerRadius="25dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<!-- 标题 -->
<TextView
android:id="@+id/heightTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="80dp"
android:text="What's your height?"
android:textColor="@android:color/white"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- 副标题 -->
<TextView
android:id="@+id/heightSubtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="This helps us create your personalized plan"
android:textColor="#808080"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/heightTitle" />
<!-- 身高选择器容器 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/heightPickerContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="32dp"
app:layout_constraintBottom_toTopOf="@id/nextButton"
app:layout_constraintTop_toBottomOf="@id/heightSubtitle">
<TextView
android:id="@+id/height2Above"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#404040"
android:textSize="60sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/height1Above"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/height1Above"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#808080"
android:textSize="80sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/heightDisplayContainer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<!-- 当前身高和单位 -->
<LinearLayout
android:id="@+id/heightDisplayContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/selectedHeightText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="167"
android:textColor="@android:color/white"
android:textSize="100sp"
android:textStyle="bold" />
<TextView
android:id="@+id/heightUnit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="cm"
android:textColor="@android:color/white"
android:textSize="32sp"
android:textStyle="normal" />
</LinearLayout>
<TextView
android:id="@+id/height1Below"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#808080"
android:textSize="80sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/heightDisplayContainer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/height2Below"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#404040"
android:textSize="60sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/height1Below"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<View
android:id="@+id/topDivider"
android:layout_width="200dp"
android:layout_height="4dp"
android:background="#BF5AF2"
app:layout_constraintBottom_toTopOf="@id/heightDisplayContainer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginBottom="0dp" />
<View
android:id="@+id/bottomDivider"
android:layout_width="200dp"
android:layout_height="4dp"
android:background="#BF5AF2"
app:layout_constraintTop_toBottomOf="@id/heightDisplayContainer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="0dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- 底部按钮区域 -->
<ImageButton
android:id="@+id/backButton"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="16dp"
android:layout_marginBottom="32dp"
android:background="@drawable/circle_button_background"
android:src="@drawable/ic_back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/nextButton"
android:layout_width="141dp"
android:layout_height="50dp"
android:layout_marginBottom="32dp"
android:text="Next"
android:textSize="17sp"
android:textAllCaps="false"
android:textColor="#FFFFFF"
app:backgroundTint="#BF5AF2"
app:cornerRadius="25dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/onboarding1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1C1C1E">
<!-- 图片自适应宽度,顶部贴屏幕,比例不变 -->
<ImageView
android:id="@+id/onboarding1_man"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/onboarding1_man"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintDimensionRatio="417:515"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="1.0"/>
<!-- 指示器,底部居中 -->
<ImageView
android:id="@+id/indicator1"
android:layout_width="88dp"
android:layout_height="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="24dp"
android:src="@drawable/indicator1"
android:scaleType="fitXY" />
<!-- 文本,图片下方居中 -->
<TextView
android:id="@+id/meet_your_c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/onboarding1_man"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:textSize="28sp"
android:textColor="#FFFFFF"
android:text="@string/meet_your_c"
android:lineSpacingExtra="-4sp"
android:gravity="center"
android:layout_marginTop="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/onboarding2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1C1C1E">
<!-- 图片自适应宽度,顶部贴屏幕,比例不变 -->
<ImageView
android:id="@+id/onboarding2_woman"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/onboarding2_woman"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintDimensionRatio="417:515"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="1.0"/>
<!-- 指示器,底部居中 -->
<ImageView
android:id="@+id/indicator2"
android:layout_width="88dp"
android:layout_height="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="24dp"
android:src="@drawable/indicator2"
android:scaleType="fitXY" />
<!-- 文本,图片下方居中 -->
<TextView
android:id="@+id/create_a_wo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/onboarding2_woman"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:textSize="28sp"
android:textColor="#FFFFFF"
android:text="@string/create_a_wo"
android:lineSpacingExtra="-4sp"
android:gravity="center"
android:layout_marginTop="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/onboarding3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1C1C1E">
<!-- 图片自适应宽度,顶部贴屏幕,比例不变 -->
<ImageView
android:id="@+id/onboarding3_man"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/onboarding3_man"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintDimensionRatio="417:515"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="1.0"
android:contentDescription="@null"/>
<!-- 指示器,底部居中 -->
<ImageView
android:id="@+id/indicator3"
android:layout_width="88dp"
android:layout_height="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="24dp"
android:src="@drawable/indicator3"
android:scaleType="fitXY"
android:contentDescription="@null"/>
<!-- 文本,图片下方居中 -->
<TextView
android:id="@+id/action_is_t"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/onboarding3_man"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:textSize="28sp"
android:textColor="#FFFFFF"
android:text="@string/action_is_t"
android:lineSpacingExtra="-4sp"
android:gravity="center"
android:layout_marginTop="16dp" />
<!-- small_butto按钮和文字叠加 -->
<FrameLayout
android:id="@+id/small_butto_container"
android:layout_width="185dp"
android:layout_height="50dp"
app:layout_constraintTop_toBottomOf="@id/action_is_t"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="16dp">
<ImageView
android:id="@+id/small_butto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/small_butto"
android:contentDescription="@null"/>
<TextView
android:id="@+id/sign_up"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/sign_up"
android:textSize="17sp"
android:textColor="#FFFFFF"
android:gravity="center" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Auto layout, variables, and unit scale are not yet supported -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/splash"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1C1C1E">
<TextView
android:id="@+id/some_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:lineSpacingExtra="28sp"
android:text="@string/some_id"
android:textSize="48sp"
android:textColor="#BF5AF2"
android:translationY="-13.95sp" />
<View
android:id="@+id/vector1"
android:layout_width="268.5dp"
android:layout_height="62.46dp"
android:background="@drawable/vector" />
<View
android:id="@+id/vector2"
android:layout_width="268.5dp"
android:layout_height="62.46dp"
android:background="@drawable/vector" />
</RelativeLayout>

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<!-- 标题 -->
<TextView
android:id="@+id/weightTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="80dp"
android:text="What's your weight?"
android:textColor="@android:color/white"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- 副标题 -->
<TextView
android:id="@+id/weightSubtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="You can always change this later"
android:textColor="#808080"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/weightTitle" />
<!-- 体重选择器容器 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/weightPickerContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="32dp"
app:layout_constraintBottom_toTopOf="@id/nextButton"
app:layout_constraintTop_toBottomOf="@id/weightSubtitle">
<TextView
android:id="@+id/weight2Above"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#404040"
android:textSize="60sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/weight1Above"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/weight1Above"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#808080"
android:textSize="80sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/selectedWeightText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/selectedWeightText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="54"
android:textColor="@android:color/white"
android:textSize="100sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/weight1Below"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#808080"
android:textSize="80sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/selectedWeightText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/weight2Below"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#404040"
android:textSize="60sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/weight1Below"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<View
android:id="@+id/topDivider"
android:layout_width="200dp"
android:layout_height="4dp"
android:background="#BF5AF2"
app:layout_constraintBottom_toTopOf="@id/selectedWeightText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginBottom="0dp" />
<View
android:id="@+id/bottomDivider"
android:layout_width="200dp"
android:layout_height="4dp"
android:background="#BF5AF2"
app:layout_constraintTop_toBottomOf="@id/selectedWeightText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="0dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- 底部按钮区域 -->
<ImageButton
android:id="@+id/backButton"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="16dp"
android:layout_marginBottom="32dp"
android:background="@drawable/circle_button_background"
android:src="@drawable/ic_back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/nextButton"
android:layout_width="141dp"
android:layout_height="50dp"
android:layout_marginBottom="32dp"
android:text="Next"
android:textSize="17sp"
android:textAllCaps="false"
android:textColor="#FFFFFF"
app:backgroundTint="#BF5AF2"
app:cornerRadius="25dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -6,4 +6,6 @@
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="gray">#757575</color>
<color name="gray_light">#E0E0E0</color>
</resources>

@ -1,4 +1,5 @@
<resources>
<!--tenserflow-->
<string name="tfe_pe_app_name">TFL Pose Estimation</string>
<string name="tfe_pe_request_permission">This app needs camera permission.</string>
<string name="tfe_pe_tv_score">Score: %.2f</string>
@ -27,4 +28,12 @@
<item>BoundingBox</item>
<item>Keypoint</item>
</string-array>
<!--形动力-->
<string name="some_id">形动力</string>
<string name="meet_your_c">Meet your coach,\nstart your journey</string>
<string name="create_a_wo">Create a workout plan\nto stay fit</string>
<string name="action_is_t">Action is the\nkey to all success</string>
<string name="sign_up">Start Now</string>
<string name="next">Next</string>
</resources>

@ -1,5 +1,5 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<!-- tenserflow Base application theme. -->
<style name="Theme.PoseEstimation" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
@ -10,9 +10,16 @@
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<item name="android:statusBarColor">@android:color/black</item>
<!-- Customize your theme here. -->
<item name="android:textColor">@color/black</item>
<item name="android:textSize">16sp</item>
</style>
<style name="NumberPickerStyle">
<item name="android:textSize">40sp</item>
<item name="android:textColorPrimary">@android:color/white</item>
<item name="android:colorControlNormal">#BF5AF2</item>
<item name="android:textColor">@android:color/white</item>
<item name="android:solidColor">@android:color/black</item>
</style>
</resources>

@ -4,5 +4,5 @@
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Mon Apr 21 08:12:48 CST 2025
#Fri Apr 25 19:53:17 CST 2025
sdk.dir=/Users/ziyue/Library/Android/sdk

@ -0,0 +1,2 @@
#Mon Apr 21 08:14:16 CST 2025
gradle.version=8.5

@ -0,0 +1,2 @@
#Mon Apr 21 08:12:48 CST 2025
java.home=/Applications/Android Studio.app/Contents/jbr/Contents/Home

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

@ -0,0 +1 @@
TFLite Pose Estimation

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidProjectSystem">
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="21" />
</component>
</project>

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
</selectionStates>
</component>
</project>

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.9.21" />
</component>
</project>

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

@ -0,0 +1,9 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

@ -0,0 +1,73 @@
# TensorFlow Lite Pose Estimation Android Demo
### Overview
This is an app that continuously detects the body parts in the frames seen by
your device's camera. These instructions walk you through building and running
the demo on an Android device. Camera captures are discarded immediately after
use, nothing is stored or saved.
The app demonstrates how to use 4 models:
* Single pose models: The model can estimate the pose of only one person in the
input image. If the input image contains multiple persons, the detection result
can be largely incorrect.
* PoseNet
* MoveNet Lightning
* MoveNet Thunder
* Multi pose models: The model can estimate pose of multiple persons in the
input image.
* MoveNet MultiPose: Support up to 6 persons.
See this [blog post](https://blog.tensorflow.org/2021/05/next-generation-pose-detection-with-movenet-and-tensorflowjs.html)
for a comparison between these models.
![Demo Image](posenetimage.png)
## Build the demo using Android Studio
### Prerequisites
* If you don't have it already, install **[Android Studio](
https://developer.android.com/studio/index.html)** 4.2 or
above, following the instructions on the website.
* Android device and Android development environment with minimum API 21.
### Building
* Open Android Studio, and from the `Welcome` screen, select
`Open an existing Android Studio project`.
* From the `Open File or Project` window that appears, navigate to and select
the `lite/examples/pose_estimation/android` directory from wherever you
cloned the `tensorflow/examples` GitHub repo. Click `OK`.
* If it asks you to do a `Gradle Sync`, click `OK`.
* You may also need to install various platforms and tools, if you get errors
like `Failed to find target with hash string 'android-21'` and similar. Click
the `Run` button (the green arrow) or select `Run` > `Run 'android'` from the
top menu. You may need to rebuild the project using `Build` > `Rebuild Project`.
* If it asks you to use `Instant Run`, click `Proceed Without Instant Run`.
* Also, you need to have an Android device plugged in with developer options
enabled at this point. See **[here](
https://developer.android.com/studio/run/device)** for more details
on setting up developer devices.
### Model used
Downloading, extraction and placement in assets folder has been managed
automatically by `download.gradle`.
If you explicitly want to download the model, you can download it from here:
* [Posenet](https://storage.googleapis.com/download.tensorflow.org/models/tflite/posenet_mobilenet_v1_100_257x257_multi_kpt_stripped.tflite)
* [Movenet Lightning](https://kaggle.com/models/google/movenet/frameworks/tfLite/variations/singlepose-lightning)
* [Movenet Thunder](https://www.kaggle.com/models/google/movenet/frameworks/tfLite/variations/singlepose-thunder)
* [Movenet MultiPose](https://www.kaggle.com/models/google/movenet/frameworks/tfLite/variations/multipose-lightning-tflite-float16)
### Additional Note
_Please do not delete the assets folder content_. If you explicitly deleted the
files, then please choose `Build` > `Rebuild` from menu to re-download the
deleted model files into assets folder.

@ -0,0 +1 @@
/build

@ -0,0 +1,56 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "org.tensorflow.lite.examples.poseestimation"
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
namespace "org.tensorflow.lite.examples.poseestimation"
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
// Download tflite model
apply from:"download.gradle"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.activity:activity-ktx:1.2.3"
implementation 'androidx.fragment:fragment-ktx:1.3.5'
implementation 'org.tensorflow:tensorflow-lite:2.14.0'
implementation 'org.tensorflow:tensorflow-lite-gpu:2.5.0'
implementation 'org.tensorflow:tensorflow-lite-support:0.3.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation "com.google.truth:truth:1.1.3"
}

@ -0,0 +1,67 @@
task downloadPosenetModel(type: DownloadUrlTask) {
def modelPosenetDownloadUrl = "https://storage.googleapis.com/download.tensorflow.org/models/tflite/posenet_mobilenet_v1_100_257x257_multi_kpt_stripped.tflite"
doFirst {
println "Downloading ${modelPosenetDownloadUrl}"
}
sourceUrl = "${modelPosenetDownloadUrl}"
target = file("src/main/assets/posenet.tflite")
}
task downloadMovenetLightningModel(type: DownloadUrlTask) {
def modelMovenetLightningDownloadUrl = "https://tfhub.dev/google/lite-model/movenet/singlepose/lightning/tflite/float16/4?lite-format=tflite"
doFirst {
println "Downloading ${modelMovenetLightningDownloadUrl}"
}
sourceUrl = "${modelMovenetLightningDownloadUrl}"
target = file("src/main/assets/movenet_lightning.tflite")
}
task downloadMovenetThunderModel(type: DownloadUrlTask) {
def modelMovenetThunderDownloadUrl = "https://tfhub.dev/google/lite-model/movenet/singlepose/thunder/tflite/float16/4?lite-format=tflite"
doFirst {
println "Downloading ${modelMovenetThunderDownloadUrl}"
}
sourceUrl = "${modelMovenetThunderDownloadUrl}"
target = file("src/main/assets/movenet_thunder.tflite")
}
task downloadMovenetMultiPoseModel(type: DownloadUrlTask) {
def modelMovenetThunderDownloadUrl = "https://tfhub.dev/google/lite-model/movenet/multipose/lightning/tflite/float16/1?lite-format=tflite"
doFirst {
println "Downloading ${modelMovenetThunderDownloadUrl}"
}
sourceUrl = "${modelMovenetThunderDownloadUrl}"
target = file("src/main/assets/movenet_multipose_fp16.tflite")
}
task downloadPoseClassifierModel(type: DownloadUrlTask) {
def modelPoseClassifierDownloadUrl = "https://storage.googleapis.com/download.tensorflow.org/models/tflite/pose_classifier/yoga_classifier.tflite"
doFirst {
println "Downloading ${modelPoseClassifierDownloadUrl}"
}
sourceUrl = "${modelPoseClassifierDownloadUrl}"
target = file("src/main/assets/classifier.tflite")
}
task downloadModel {
dependsOn downloadPosenetModel
dependsOn downloadMovenetLightningModel
dependsOn downloadMovenetThunderModel
dependsOn downloadPoseClassifierModel
dependsOn downloadMovenetMultiPoseModel
}
class DownloadUrlTask extends DefaultTask {
@Input
String sourceUrl
@OutputFile
File target
@TaskAction
void download() {
ant.get(src: sourceUrl, dest: target)
}
}
preBuild.dependsOn downloadModel

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save