SeekBar.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. import React, { Component } from "react";
  2. import {
  3. Platform,
  4. StyleSheet,
  5. Text,
  6. View,
  7. Image,
  8. Button,
  9. PanResponder,
  10. ImageBackground,
  11. findNodeHandle,
  12. UIManager,
  13. DeviceEventEmitter
  14. } from "react-native";
  15. import BasePage from "../BasePage";
  16. const instructions = Platform.select({
  17. ios: "Press Cmd+R to reload,\n" + "Cmd+D or shake for dev menu",
  18. android:
  19. "Double tap R on your keyboard to reload,\n" +
  20. "Shake or press menu button for dev menu"
  21. });
  22. type Props = {};
  23. export default class SeekBar extends BasePage {
  24. constructor(props) {
  25. super(props);
  26. this.pressStatus = false;
  27. this.progress = 0;
  28. }
  29. config = {
  30. changeX: 0,
  31. changeY: 0,
  32. xDiff: 0,
  33. yDiff: 0
  34. };
  35. state = {
  36. max: 1,
  37. view_width: 0,
  38. icon_transform: [{ scale: 1 }],
  39. left: 0,
  40. top: 0,
  41. touch_down: false
  42. };
  43. render() {
  44. return (
  45. <View
  46. style={{
  47. height: 80,
  48. width: "100%",
  49. alignItems: "center",
  50. justifyContent: "center"
  51. }}
  52. >
  53. <View
  54. style={{
  55. height: 20,
  56. width: "98%"
  57. }}
  58. ref={c => {
  59. this.progressBar = c;
  60. }}
  61. onLayout={() => {
  62. const handle = findNodeHandle(this.progressBar);
  63. setTimeout(() => {
  64. UIManager.measure(handle, (x, y, width, height, pageX, pageY) => {
  65. // console.warn(x, y, width, height, pageX, pageY);
  66. this.setState({
  67. view_width: width
  68. });
  69. this.setProgress(this.progress);
  70. });
  71. }, 0);
  72. }}
  73. >
  74. <ImageBackground
  75. style={{
  76. height: 2,
  77. width: "100%",
  78. backgroundColor: "#DBDBDB",
  79. overflow: "hidden",
  80. borderRadius: 10,
  81. top: 10
  82. }}
  83. >
  84. <View
  85. style={{
  86. height: 2,
  87. width: this.state.left + 3,
  88. backgroundColor: "#FFA91C",
  89. overflow: "hidden",
  90. borderRadius: 10
  91. }}
  92. />
  93. </ImageBackground>
  94. <Image
  95. {...this._panResponder.panHandlers}
  96. style={{
  97. height: 14,
  98. width: 14,
  99. borderRadius: 10,
  100. backgroundColor: "#FFA91C",
  101. transform: this.state.icon_transform,
  102. left: this.state.left,
  103. top: 2
  104. }}
  105. />
  106. </View>
  107. </View>
  108. );
  109. }
  110. componentWillMount() {
  111. this._panResponder = PanResponder.create({
  112. onStartShouldSetPanResponder: (evt, gestureState) => true,
  113. onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
  114. onMoveShouldSetPanResponder: (evt, gestureState) => true,
  115. onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
  116. onPanResponderGrant: (evt, gestureState) => {
  117. this.pressStatus = true;
  118. this.config.changeY = evt.nativeEvent.pageY;
  119. this.config.changeX = evt.nativeEvent.pageX;
  120. },
  121. onPanResponderStart: (evt, gestureState) => {
  122. this.pressStatus = true;
  123. console.log("onPanResponderStart");
  124. this.setState({
  125. icon_transform: [{ scale: 1.5 }],
  126. touch_down: true
  127. });
  128. },
  129. onPanResponderMove: (evt, gestureState) => {
  130. this.config.yDiff = evt.nativeEvent.pageY - this.config.changeY;
  131. this.config.xDiff = evt.nativeEvent.pageX - this.config.changeX;
  132. this.state.left = this.state.left + this.config.xDiff;
  133. this.state.top = this.state.top + this.config.yDiff;
  134. this.config.changeY = evt.nativeEvent.pageY;
  135. this.config.changeX = evt.nativeEvent.pageX;
  136. if (
  137. this.state.left < 0 ||
  138. this.state.left > this.state.view_width - 14
  139. ) {
  140. if (this.state.left < 0) {
  141. this.state.left = 0;
  142. } else if (this.state.left > this.state.view_width - 14) {
  143. this.state.left = this.state.view_width - 14;
  144. }
  145. this.setState({
  146. left: this.state.left,
  147. top: this.state.top
  148. });
  149. } else {
  150. this.setState({
  151. left: this.state.left,
  152. top: this.state.top
  153. });
  154. console.log("onPanResponderMove:" + this.state.left);
  155. }
  156. },
  157. onPanResponderEnd: (evt, gestureState) => {
  158. this.pressStatus = true;
  159. console.log("onPanResponderEnd");
  160. },
  161. onPanResponderTerminationRequest: (evt, gestureState) => true,
  162. onPanResponderRelease: (evt, gestureState) => {
  163. if (this.pressStatus) {
  164. this.props.onPress && this.props.onPress();
  165. this.setState({
  166. icon_transform: [{ scale: 1 }],
  167. touch_down: false
  168. });
  169. }
  170. this.pressStatus = false;
  171. var sss = this.state.left / (this.state.view_width - 14);
  172. // alert(sss + "%");
  173. this.props.touchUpCallBack(this.state.max * sss);
  174. },
  175. onPanResponderTerminate: (evt, gestureState) => {
  176. // 另一个组件已经成为了新的响应者,所以当前手势将被取消。
  177. },
  178. onShouldBlockNativeResponder: (evt, gestureState) => {
  179. // 返回一个布尔值,决定当前组件是否应该阻止原生组件成为JS响应者
  180. // 默认返回true。目前暂时只支持android。
  181. //基于业务交互场景,如果这里使用js事件处理,会导致容器不能左右滑动。所以设置成false.
  182. return false;
  183. }
  184. });
  185. }
  186. getTouchDown() {
  187. return this.state.touch_down;
  188. }
  189. setMax(setmax) {
  190. this.setState({
  191. max: setmax
  192. });
  193. }
  194. getMax() {
  195. return this.state.max;
  196. }
  197. setProgress(progress) {
  198. if (this.state.view_width > 0) {
  199. this.progress = progress;
  200. if (this.state.touch_down) {
  201. } else {
  202. var left_percentage;
  203. if (this.state.max == 0) {
  204. left_percentage = progress / 1;
  205. } else {
  206. left_percentage = progress / this.state.max;
  207. }
  208. this.setState({
  209. left: (this.state.view_width - 14) * left_percentage,
  210. icon_transform: [{ scale: 1 }]
  211. });
  212. }
  213. }
  214. }
  215. }
  216. const styles = StyleSheet.create({});
  217. /**
  218. <SeekBar
  219. ref={view => (this.seekbar = view)}
  220. max={100}
  221. //必须带此方法,作为滑动之后抬起的回调
  222. touchUpCallBack={this.touch_up_callback.bind(this)}
  223. progress={this.state.curprogress}
  224. />
  225. state = {
  226. curprogress: 0,
  227. max: 100
  228. };
  229. touch_up_callback(progress) {
  230. //抬起之后,获取算出来的progress
  231. this.setState({
  232. curprogress: progress
  233. });
  234. }
  235. setProgressIcon() {
  236. //轮询设置值,超过max则停止
  237. setTimeout(() => {
  238. if (!this.seekbar.getTouchDown()) {
  239. this.setState({
  240. curprogress: this.state.curprogress + 1
  241. });
  242. }
  243. if (this.state.curprogress >= this.state.max) {
  244. alert("100了");
  245. } else {
  246. this.setProgressIcon();
  247. }
  248. this.seekbar.setProgress(this.state.curprogress);
  249. }, 1000);
  250. }
  251. */