Since there was no answer to my question I answer it myself. Beware that I am not an expert and therefore this might not fit Your purpose!
The default overscroll behaviour can be overridden by extending the Container class and overriding the pointer methods without calling their super methods.
Here is an example:
import com.codename1.ui.Component;
import com.codename1.ui.Container;
import com.codename1.ui.Form;
import com.codename1.ui.Graphics;
import com.codename1.ui.Label;
import com.codename1.ui.animations.Motion;
import com.codename1.ui.geom.Point;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.layouts.BoxLayout;
public class FormOverscroll extends Form {
FormOverscroll() {
super("FormOverscroll");
setScrollable(false);
setLayout(new BorderLayout());
Container container = new Container(BoxLayout.y()) {
boolean bounce = false;
Motion motion = null;
Point pointPressed = null;
long millisPoint = 0;
int scrollYPressed = 0, scrollYPrevious = 0;
{
// setTensileDragEnabled(false);
setScrollableY(true);
}
@Override
protected boolean isStickyDrag() {
return true;
}
@Override
public void pointerPressed(int x, int y) {
pointPressed = new Point(x, y);
scrollYPressed = scrollYPrevious = getScrollY();
millisPoint = System.currentTimeMillis();
motion = null;
bounce = false;
}
@Override
public void pointerDragged(int x, int y) {
if (null == pointPressed) {
return;
}
int yDist = y - pointPressed.getY();
int scrollY = scrollYPressed - yDist;
if (scrollY < 0) {
Motion motionRubberband = Motion.createCubicBezierMotion(0, scrollY, getHeight(), 0f, 1.2f, 0.5f, 0.6f);
motionRubberband.setStartTime(0);
motionRubberband.setCurrentMotionTime(Math.abs(scrollY));
scrollY = motionRubberband.getValue();
}
setScrollY(scrollY);
}
float getVelocity(int scrollY) {
long millisNow = System.currentTimeMillis();
long timediff = millisNow - millisPoint;
float diff = scrollYPrevious - scrollY;
float velocity = (diff / timediff) * -1f;
scrollYPrevious = scrollY;
millisPoint = millisNow;
return velocity;
}
@Override
public void pointerReleased(int x, int y) {
if (null == pointPressed) {
return;
}
int yDist = y - pointPressed.getY();
int scrollY = scrollYPressed - yDist;
float velocity = getVelocity(scrollY);
motion = Motion.createFrictionMotion(scrollY, Integer.MIN_VALUE, velocity, 0.0007f);
motion.start();
getComponentForm().registerAnimated(this);
pointPressed = null;
}
@Override
public boolean animate() {
boolean animate = super.animate();
if (null != motion) {
int scrollY = motion.getValue();
setScrollY(scrollY);
int target = 0;
if (scrollY < target && !bounce) {
createRubberbandMotion(scrollY, target);
bounce = true;
motion.start();
}
int maxScrollY = Math.max(target, getScrollDimension().getHeight() - getHeight());
if (scrollY > maxScrollY && !bounce) {
createRubberbandMotion(scrollY, maxScrollY);
bounce = true;
motion.start();
}
scrollYPrevious = scrollY;
if (motion.isFinished()) {
motion = null;
}
return true;
}
return animate;
}
private void createRubberbandMotion(int source, int target) {
motion = Motion.createCubicBezierMotion(source, target, 500, 0.0f, 1.0f, 1.2f, 1.0f);
}
@Override
public Component getComponentAt(int x, int y) {
return this;
}
@Override
public void paint(Graphics aGraphics) {
super.paint(aGraphics);
}
};
for (int index = 0; index < 100; index++) {
container.add(new Label("Zeile " + index));
}
add(BorderLayout.CENTER, container);
}
}