关于Codename One Motion类使用及橡皮筋滚动实现的技术问询
Great question! Let's break this down step by step to solve your rubberband scroll goal and clarify the confusion around Codename One's Motion class methods.
1. 用Spring Motion实现原生风格橡皮筋效果
If you want to match iOS' rubberband scroll behavior, Motion.createSpringMotion() is the perfect tool—it simulates physical spring dynamics with damping, which naturally replicates the stretch-and-recoil feel of iOS' scroll.
Here's how the spring motion parameters work:
Motion.createSpringMotion(int duration, int start, int end, float springConstant, float damping)
duration: Total time for the motion (use a value that matches your scroll timeline, e.g., 500 for half a second)start: Initial position (e.g., the stretched offset beyond content bounds)end: Target position (e.g., the edge of your content, 0 for full rebound)springConstant: Stiffness of the "rubberband"—higher values mean faster rebounds (try0.2f)damping: Resistance to oscillation—higher values reduce bounce (try0.8ffor natural iOS-like behavior)
Add this to your test app to visualize the effect:
new Row() { @Override public Plotter getPlotter() { return new Plotter() { @Override protected Motion getMotion(int aStart, int aDestination) { // Simulate stretching to aDestination, then rebounding to aStart return Motion.createSpringMotion(aDestination, aDestination, aStart, 0.2f, 0.8f); } }; } @Override public Component getControls() { return new Label("Rubberband (Spring) Motion"); } },
2. Understanding Cubic Bezier Motion Parameters
You noticed the createCubicBezierMotion parameters seem different from other tools—here's the breakdown to clarify:
Motion.createCubicBezierMotion(int duration, int start, int end, float x1, float y1, float x2, float y2)
x1, y1: Coordinates of the first Bezier control point (time ratio, value ratio)x2, y2: Coordinates of the second Bezier control point
Key notes:
- Time ratios (
x1, x2) should stay between 0 and 1 (they map to progress through the motion duration) - Value ratios (
y1, y2) can go above 1 or below 0 to create the "stretch" effect for rubberband behavior
For example, to simulate the drag phase of rubberband scrolling (where pulling feels increasingly resistant):
// Early on (10% of duration), we've already stretched 150% of the target; then we slow down to reach the target Motion stretchDragMotion = Motion.createCubicBezierMotion(100, 0, 100, 0.1f, 1.5f, 0.3f, 1.0f);
Your test code's choice to set duration = aDestination is fine (you're using pixel position as your time axis), just ensure x1/x2 stay in the 0-1 range to avoid wonky curves.
3. Clarifying Ease Motion Confusions
EaseInOutMotion feels too linear
EaseInOut should produce an S-shaped curve (slow start, fast middle, slow end). If it looks linear in your test:
- You’re using the same value for
durationandend, which makes the time and value axes proportional—try increasingduration(e.g.,200instead of100) to exaggerate the curve. - Adjust your test code to use a larger difference between
startandendto make the S-shape more visible.
EaseIn/EaseOutMotion seem reversed
This is likely a coordinate system quirk! Codename One uses a top-left origin, so y-values increase downward. Here’s what’s actually happening:
- EaseInMotion: Starts slow (flat curve), speeds up (steep curve) — in your plot, this looks like a line that gets steeper as it moves right.
- EaseOutMotion: Starts fast (steep curve), slows down (flat curve) — looks like a line that flattens out as it moves right.
To fix the visual reversal, flip your y-axis in the paint method:
int yAxis = size - motion.getValue(); // Makes higher values move upward instead of downward
This will align the curve with your intuitive understanding of motion speed.
内容的提问来源于stack exchange,提问作者Stefan Eder

