SeekBar.js 6.6 KB

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