How to build a custom draw2d layoutmanager? - layout-manager

I would like to have a layout manager that can arrange two elements as follows:
one main element ABCDEF centered
one "postscript" element XYZ, positioned on the top right corner of the encapsulating figure
For example:
***********XYZ*
* ABCDEF *
***************
Can I use an existing layoutmanager for this? How do I build a custom layout manager that supports it?
Many thanks for your advice.

You can do that by using XYLayout.
There is a sample you can build on:
import org.eclipse.draw2d.AbstractLayout;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LayoutManager;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.Panel;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class HHH {
public static void main(String[] args) {
Display d = new Display();
Shell s = new Shell();
s.setLayout(new FillLayout());
FigureCanvas canvas = new FigureCanvas(s);
Figure content = new Figure();
content.setLayoutManager(new XYLayout());
PostScriptedFigure figure = new PostScriptedFigure();
content.add(figure, new Rectangle(100, 100, -1, -1));
figure.setMainFigure(new Label("The Main figure"));
figure.setPostScriptFigure(new Label("ps"));
figure.setBorder(new LineBorder());
canvas.setContents(content);
s.setSize(600, 500);
s.open();
while (!s.isDisposed()) {
if (!d.readAndDispatch()) {
d.sleep();
}
}
}
}
class PostScriptedFigure extends Panel {
private IFigure mainFigure, postScriptFigure;
private class PostScriptedLayoutManager extends AbstractLayout {
#Override
public void layout(IFigure container) {
final Rectangle clientArea = container.getClientArea();
final IFigure mainFigure = getMainFigure();
final IFigure postScriptFigure = getPostScriptFigure();
if (mainFigure != null) {
final Rectangle bounds = new PrecisionRectangle();
bounds.setSize(mainFigure.getPreferredSize(SWT.DEFAULT, SWT.DEFAULT));
final Rectangle mainClientArea = clientArea.getCopy();
if (postScriptFigure != null) {
mainClientArea.shrink(new Insets(postScriptFigure.getPreferredSize().height(), 0, 0, 0));
}
bounds.translate(mainClientArea.getCenter().getTranslated(bounds.getSize().getScaled(0.5f).getNegated()));
mainFigure.setBounds(bounds);
}
if (postScriptFigure != null) {
final Rectangle bounds = new PrecisionRectangle();
bounds.setSize(postScriptFigure.getPreferredSize(SWT.DEFAULT, SWT.DEFAULT));
bounds.translate(clientArea.getTopRight().getTranslated(bounds.getSize().getNegated().width(), 0));
postScriptFigure.setBounds(bounds);
}
// note that other potentionally added figures are ignored
}
#Override
protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
final Rectangle rect = new PrecisionRectangle();
final IFigure mainFigure = getMainFigure();
if (mainFigure != null) {
rect.setSize(mainFigure.getPreferredSize());
}
final IFigure postScriptFigure = getPostScriptFigure();
if (postScriptFigure != null) {
rect.resize(mainFigure != null ? 0 : postScriptFigure.getPreferredSize().width() , postScriptFigure.getPreferredSize().height());
}
// note that other potentionally added figures are ignored
final Dimension d = rect.getSize();
final Insets insets = container.getInsets();
return new Dimension(d.width + insets.getWidth(), d.height + insets.getHeight()).union(getBorderPreferredSize(container));
}
}
public PostScriptedFigure() {
super.setLayoutManager(new PostScriptedLayoutManager());
}
#Override
public void setLayoutManager(LayoutManager manager) {
// prevent from setting wrong layout manager
}
public IFigure getMainFigure() {
return mainFigure;
}
public void setMainFigure(IFigure mainFigure) {
if (getMainFigure() != null) {
remove(getMainFigure());
}
this.mainFigure = mainFigure;
add(mainFigure);
}
public IFigure getPostScriptFigure() {
return postScriptFigure;
}
public void setPostScriptFigure(IFigure postScriptFigure) {
if (getPostScriptFigure() != null) {
remove(getPostScriptFigure());
}
this.postScriptFigure = postScriptFigure;
add(postScriptFigure);
}
}

Related

TornadoFX TableView. Scrolling the large amount of rows leads to UI freezing

I have a windows desktop application on Kotlin and I'm using JDK Zulu11 with JavaFX and TornadoFX 2.0.0.
I faced the problem with scrolling of large amount of rows (~4mln) in the TableView.
I have something like a player and when it starts I just need to do autoscroll to the row corresponding to the player current position. So to make playing smooth I do it by calling scrollTo method every 50 milliseconds, 20 times per second.
I observed that approximately at 300000 UI starts freezing and at 500000 it is almost dead.
When I increase the delay from 50ms to 200ms or 500ms the situation is the same, UI gets freeze.
When I used JDK Zulu1.8 with JavaFX and TornadoFX 1.7.2 just for check all was perfect, all is playing very smooth and fast enough. With Oracle JDK 1.8 all is ok also.
But I need to migrate to JDK 11 because I have some important dependencies.
So the question is what is wrong with JDK 11(JavaFX) and TornadoFX 2.0.0 and how it can be fixed?
Thanks a lot for any help.
PS: Here is the minimal reproducible example, I just found some TableView example on javacodegeeks and modified it, so please chek with JDK1.8 and with OpenJDK11, I used Azul Zulu 11.
Also here is the video with demonstration.
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.layout.HBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.paint.Color;
import javafx.scene.control.Label;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.TableColumn;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.List;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
public class FxTableViewExample1 extends Application {
public static class Book {
private SimpleIntegerProperty index;
private SimpleStringProperty title;
private SimpleStringProperty author;
public Book () {
}
public Book (Integer i, String s1, String s2) {
index = new SimpleIntegerProperty(i);
title = new SimpleStringProperty(s1);
author = new SimpleStringProperty(s2);
}
public int getIndex() {
return index.get();
}
public void setIndex(int index) {
this.index.set(index);
}
public String getTitle() {
return title.get();
}
public void setTitle(String s) {
title.set(s);
}
public String getAuthor() {
return author.get();
}
public void setAuthor(String s) {
author.set(s);
}
#Override
public String toString() {
return (index.get() + ": " + title.get() + ", by " + author.get());
}
}
private static final Integer COUNT = 10000000;
private static final Integer DELTA = 5000;
private static final Integer PERIOD = 50;
public static final EventType<Event> ScrollEventType = new EventType<>("ScrollEvent");
public static final EventType<Event> StopEventType = new EventType<>("StopEvent");
public static class ScrollEvent extends Event {
public Integer position = 0;
public ScrollEvent(Integer position) {
super(ScrollEventType);
this.position = position;
}
}
public static class StopEvent extends Event {
public StopEvent() {
super(StopEventType);
}
}
private TableView<Book> table;
private ObservableList<Book> data;
private Text actionStatus;
private Button startButton;
private Button stopButton;
private Integer count = 0;
private SimpleIntegerProperty currentPositionProperty = new SimpleIntegerProperty(0);
private Timer timer = null;
public static void main(String [] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Table View Example 1");
// Books label
Label label = new Label("Books");
label.setTextFill(Color.DARKBLUE);
label.setFont(Font.font("Calibri", FontWeight.BOLD, 36));
HBox labelHb = new HBox();
labelHb.setAlignment(Pos.CENTER);
labelHb.getChildren().add(label);
// Table view, data, columns and properties
table = new TableView<>();
data = getInitialTableData();
table.setItems(data);
TableColumn<Book, Integer> indexCol = new TableColumn<>("Index");
indexCol.setCellValueFactory(new PropertyValueFactory<Book, Integer>("index"));
TableColumn<Book, String> titleCol = new TableColumn<Book, String>("Title");
titleCol.setCellValueFactory(new PropertyValueFactory<Book, String>("title"));
TableColumn<Book, String> authorCol = new TableColumn<Book, String>("Author");
authorCol.setCellValueFactory(new PropertyValueFactory<Book, String>("author"));
table.getColumns().setAll(indexCol, titleCol, authorCol);
table.setPrefWidth(450);
table.setPrefHeight(300);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
table.getSelectionModel().selectedIndexProperty().addListener(
new RowSelectChangeListener());
// Status message text
actionStatus = new Text();
actionStatus.setFill(Color.FIREBRICK);
startButton = new Button("Play");
stopButton = new Button("Stop");
stopButton.setDisable(true);
currentPositionProperty.addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
Platform.runLater(new Runnable() {
#Override
public void run() {
table.scrollTo(newValue.intValue());
table.getSelectionModel().select(newValue.intValue());
}
});
}
});
primaryStage.addEventHandler(ScrollEventType, new EventHandler<Event>() {
#Override
public void handle(Event event) {
if (event.getEventType() == ScrollEventType) {
currentPositionProperty.set(((ScrollEvent)event).position);
}
}
});
primaryStage.addEventHandler(StopEventType, new EventHandler<Event>() {
#Override
public void handle(Event event) {
if (timer != null) {
timer.cancel();
timer = null;
}
}
});
startButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
count = 0;
startButton.setDisable(true);
stopButton.setDisable(false);
if (timer == null) {
timer = new Timer(true);
timer.schedule(new TimerTask() {
#Override
public void run() {
count++;
int position = count * DELTA;
if (position >= COUNT) {
Event.fireEvent(primaryStage, new ScrollEvent(COUNT));
Event.fireEvent(primaryStage, new StopEvent());
} else {
Event.fireEvent(primaryStage, new ScrollEvent(position));
}
}
}, 0, PERIOD);
}
}
});
stopButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
startButton.setDisable(false);
stopButton.setDisable(true);
if (timer != null) {
timer.cancel();
timer = null;
}
}
});
HBox hbox = new HBox(20);
hbox.setPadding(new Insets(25, 25, 25, 25));
hbox.getChildren().addAll(startButton, stopButton);
// Vbox
VBox vbox = new VBox(20);
vbox.setPadding(new Insets(25, 25, 25, 25));
vbox.getChildren().addAll(labelHb, table, actionStatus, hbox);
// Scene
Scene scene = new Scene(vbox, 500, 475); // w x h
primaryStage.setScene(scene);
primaryStage.show();
// Select the first row
table.getSelectionModel().select(0);
Book book = table.getSelectionModel().getSelectedItem();
actionStatus.setText(book.toString());
} // start()
private class RowSelectChangeListener implements ChangeListener<Number> {
#Override
public void changed(ObservableValue<? extends Number> ov,
Number oldVal, Number newVal) {
int ix = newVal.intValue();
if ((ix < 0) || (ix >= data.size())) {
return; // invalid data
}
Book book = data.get(ix);
actionStatus.setText(book.toString());
}
}
private ObservableList<Book> getInitialTableData() {
List<Book> list = new ArrayList<>();
int i = 0;
while (i < COUNT) {
list.add(new Book(i++, "The Thief", "Fuminori Nakamura"));
list.add(new Book(i++, "Of Human Bondage", "Somerset Maugham"));
list.add(new Book(i++, "The Bluest Eye", "Toni Morrison"));
list.add(new Book(i++, "I Am Ok You Are Ok", "Thomas Harris"));
list.add(new Book(i++, "Magnificent Obsession", "Lloyd C Douglas"));
list.add(new Book(i++, "100 Years of Solitude", "Gabriel Garcia Marquez"));
list.add(new Book(i++, "What the Dog Saw", "Malcolm Gladwell"));
list.add(new Book(i++, "The Fakir", "Ruzbeh Bharucha"));
list.add(new Book(i++, "The Hobbit", "J.R.R. Tolkien"));
list.add(new Book(i++, "Strange Life of Ivan Osokin", "P.D. Ouspensky"));
list.add(new Book(i++, "The Hunt for Red October", "Tom Clancy"));
list.add(new Book(i++, "Coma", "Robin Cook"));
}
return FXCollections.observableList(list);
}
}
The problem was resolved by using OpenJDK11 and separate OpenJFX15 instead of Zulu JDK11+JFX.

Java OOP using Translate Transition and JavaFX

The Translate Transition does not output. It uses a method in the main class. I believe it is not working because it is used as an object. There has to be a different code to implement. It uses a method in a main and then puts it into a tester. However, I do not know how to use it because it uses a constructor/object as well. Then, the object turns and changes into a node which I changed it. I do not know how the Translate Transition method is attached to the object and displays it into the javafx console. Please help solve the problem for positive feedback as it shows.
import javafx.animation.TranslateTransition;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Shape;
import javafx.util.Duration;
public class AnxiousShapes {
private Shape shape;
private double delay ;
private int howFarToMoveX;
private int howFarToMoveY;
public AnxiousShapes(int type, int x, int y, int size, double delay, Color color, int hftmX, int hftmY) {
if (type == 0) {shape = new Circle(x, y, size, color);}
//these are the only lines you can change
//in this main class
//else if (type == 1){shape = new Rectangle(x,y,color);}
//else if (type == 2){shape = new Polygon();}
//else if (type == 3) {shape = new Circle(x, y, size, color);}
//else { System.out.println("Error in type");shape = new
//Circle(???????);}
this.delay = delay;
this.howFarToMoveX = hftmX;
this.howFarToMoveY = hftmY;
}
// getter and setters
public TranslateTransition calculateTt() {
TranslateTransition tt = new TranslateTransition(Duration.seconds(this.delay), this.shape);
tt.setToX(this.shape.getLayoutX() + howFarToMoveX);
tt.setToY(shape.getLayoutY() + howFarToMoveY);
// Let the animation run forever -- if the shape
// tries to move "off-screen" it will return to the beginning
tt.setCycleCount(TranslateTransition.INDEFINITE);
return tt;
}
#Override
public String toString() {
return "AnxiousShape [shape=" + shape + ", delay=" + delay + ", howFarToMoveX=" + howFarToMoveX
+ ", howFarToMoveY=" + howFarToMoveY + "]";
}
}
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.scene.Group;
import javafx.scene.Node;
import java.util.Random;
public class AnxiousShapesTester extends Application {
#Override
public void start(Stage stage) {
// adding the new things
Group root = new Group();
stage.setTitle("Welcome to JavaFX!");
// create the shape circle
AnxiousShapes circle1 = new AnxiousShapes(0, 200, 200, 50, 15,
Color.GREEN, 10 ,35);
root.getChildren().add(circle1.getShape());
// this does not work
// TranslateTransition trans = circle1.calculateTt();
// trans.setNode(root);
// trans.play();
// and I tried this and I already have the movement in constructor for
// delay and x and y but TranslateTransition
// asks for duration.millis(500)
TranslateTransition tt = new
TranslateTransition(Duration.millis(500), root);
tt.play();
Scene scene = new Scene(root, 600, 600, Color.WHITE);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
In a comment, you say, "this does not work." The problem is trans.setNode(root), which attempts to make root "The target node of this TranslateTransition." Your implementation of calculateTt() already specifies this.shape as the target node. Instead, add a suitable accessor to AnxiousShapes and use the transition as constructed; the following changes are illustrated below:
public Shape getShape() { return this.shape; }
…
AnxiousShapes circle1 = new AnxiousShapes(0, 100, 100, 100, 3, Color.GREEN, 400, 400);
root.getChildren().add(circle1.getShape());
TranslateTransition trans = circle1.calculateTt();
trans.play();

How to draw several lines slowly in constant velocity on canvas by Android?

I need capture the mark to draw a figure on canvas in Android, and the effect just like the follow gif:
Well, as far, I can draw a side with constant velocity by ValueAnimator. However, I just only can draw one side at one time, because I can't save the last side when drawing the next side. So, is there a good way to solve the problem?
Code for draw a line slowly by ValueAnimator:
GraphicsView.java
public class GraphicsView extends View {
private int stepX, stepY = 0;
private int startX, startY, stopX, stopY = 0;
private Paint paint = null;
public GraphicsView(Context context) {
super(context);
// Paint
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
startX = 40;
startY = 397;
stopX = 1040;
stopY = 397;
Init();
}
public void Init(){
ValueAnimator animatorX = ValueAnimator.ofFloat(startX, stopX);
ValueAnimator animatorY = ValueAnimator.ofFloat(startY, stopY);
animatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
stepX = Math.round((Float)valueAnimator.getAnimatedValue()); invalidate();
}
});
animatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
stepY = Math.round((Float)valueAnimator.getAnimatedValue()); invalidate();
}
});
AnimatorSet set = new AnimatorSet();
LinearInterpolator l = new LinearInterpolator();
set.setInterpolator(l);
set.setDuration(3000);
set.playTogether(animatorX, animatorY);
set.start();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(startX, startY, stepX, stepY, paint);
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Display display = null;
private GraphicsView view = null;
private ConstraintLayout layout = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
display = getWindowManager().getDefaultDisplay();
layout = (ConstraintLayout)findViewById(R.id.main_layout);
view = new GraphicsView(this);
view.setMinimumWidth(display.getWidth());
view.setMinimumHeight(display.getHeight());
layout.addView(view);
}
}
you can use the ObjectAnimator class to callback
to one of your class methods every time you'd like to draw a bit more of the path.
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.view.View;
import android.util.Log;
public class PathView extends View
{
Path path;
Paint paint;
float length;
public PathView(Context context)
{
super(context);
}
public PathView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public PathView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
}
public void init()
{
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
path = new Path();
path.moveTo(50, 50);
path.lineTo(50, 500);
path.lineTo(200, 500);
path.lineTo(200, 300);
path.lineTo(350, 300);
// Measure the path
PathMeasure measure = new PathMeasure(path, false);
length = measure.getLength();
float[] intervals = new float[]{length, length};
ObjectAnimator animator = ObjectAnimator.ofFloat(PathView.this, "phase", 1.0f, 0.0f);
animator.setDuration(3000);
animator.start();
}
//is called by animtor object
public void setPhase(float phase)
{
Log.d("pathview","setPhase called with:" + String.valueOf(phase));
paint.setPathEffect(createPathEffect(length, phase, 0.0f));
invalidate();//will calll onDraw
}
private static PathEffect createPathEffect(float pathLength, float phase, float offset)
{
return new DashPathEffect(new float[] { pathLength, pathLength },
Math.max(phase * pathLength, offset));
}
#Override
public void onDraw(Canvas c)
{
super.onDraw(c);
c.drawPath(path, paint);
}
}
Then, just call init() to begin the animation, like this (or if you'd like it to start as soon as the view is inflated, put the init() call inside the constructors):
PathView path_view = (PathView) root_view.findViewById(R.id.path);
path_view.init();
Also see this question here, and
Using Value Animator Example
Reference 1
Reference 2
Reference 3

How to remove all comments from docx file with docx4j?

I'd like to remove all the comments from a docx file using docx4j.
I can remove the actual comments with a piece of code like is shown below, but I think I also need to remove the comment references from the main document part as well (otherwise the document is corrupted), but I can't figure out how to do that.
CommentsPart cmtsPart = wordMLPackage.getMainDocumentPart().getCommentsPart();
org.docx4j.wml.Comments cmts = cpart.getJaxbElement();
List<Comments.Comment> coms = cmts.getComment();
coms.clear();
Any guidance appreciated!
I also posted this question on the docx4j forum: http://www.docx4java.org/forums/docx-java-f6/how-to-remove-all-comments-from-docx-file-t1329.html.
Thanks.
You can use TraversalUtil to find the relevant objects (CommentRangeStart, CommentRangeEnd, R.CommentReference), and then remove them.
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import org.docx4j.TraversalUtil;
import org.docx4j.TraversalUtil.CallbackImpl;
import org.docx4j.XmlUtils;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.Body;
import org.docx4j.wml.CommentRangeEnd;
import org.docx4j.wml.CommentRangeStart;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.R.CommentReference;
import org.jvnet.jaxb2_commons.ppp.Child;
public class Foo {
public static void main(String[] args) throws Exception {
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage
.load(new java.io.File(System.getProperty("user.dir") + "/Foo.docx"));
MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
org.docx4j.wml.Document wmlDocumentEl = (org.docx4j.wml.Document) documentPart
.getJaxbElement();
Body body = wmlDocumentEl.getBody();
CommentFinder cf = new CommentFinder();
new TraversalUtil(body, cf);
for (Child commentElement : cf.commentElements) {
System.out.println(commentElement.getClass().getName());
Object parent = commentElement.getParent();
List<Object> theList = ((ContentAccessor)parent).getContent();
boolean removeResult = remove(theList, commentElement );
System.out.println(removeResult);
}
}
private static boolean remove(List<Object> theList, Object bm) {
// Can't just remove the object from the parent,
// since in the parent, it may be wrapped in a JAXBElement
for (Object ox : theList) {
if (XmlUtils.unwrap(ox).equals(bm)) {
return theList.remove(ox);
}
}
return false;
}
static class CommentFinder extends CallbackImpl {
List<Child> commentElements = new ArrayList<Child>();
#Override
public List<Object> apply(Object o) {
if (o instanceof javax.xml.bind.JAXBElement
&& (((JAXBElement)o).getName().getLocalPart().equals("commentReference")
|| ((JAXBElement)o).getName().getLocalPart().equals("commentRangeStart")
|| ((JAXBElement)o).getName().getLocalPart().equals("commentRangeEnd")
)) {
System.out.println(((JAXBElement)o).getName().getLocalPart());
commentElements.add( (Child)XmlUtils.unwrap(o) );
} else
if (o instanceof CommentReference ||
o instanceof CommentRangeStart ||
o instanceof CommentRangeEnd) {
System.out.println(o.getClass().getName());
commentElements.add((Child)o);
}
return null;
}
#Override // to setParent
public void walkJAXBElements(Object parent) {
List children = getChildren(parent);
if (children != null) {
for (Object o : children) {
if (o instanceof javax.xml.bind.JAXBElement
&& (((JAXBElement)o).getName().getLocalPart().equals("commentReference")
|| ((JAXBElement)o).getName().getLocalPart().equals("commentRangeStart")
|| ((JAXBElement)o).getName().getLocalPart().equals("commentRangeEnd")
)) {
((Child)((JAXBElement)o).getValue()).setParent(XmlUtils.unwrap(parent));
} else {
o = XmlUtils.unwrap(o);
if (o instanceof Child) {
((Child)o).setParent(XmlUtils.unwrap(parent));
}
}
this.apply(o);
if (this.shouldTraverse(o)) {
walkJAXBElements(o);
}
}
}
}
}
}

ImageView doesn't slike on translationX animation

I'm trying to create a slider, when users fling left or right, this slider will slide animatedly, translation animation. However, it doesn't work in a right way.
package pete.android.study.home.scrollingindicator;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
public class MainScreen extends Activity {
protected ValueAnimator mScrollIndicatorAnimator;
protected ValueAnimator mScrollator;
protected ImageView mScrollIndicator = null;
protected static final int sScrollIndicatorFadeInDuration = 150;
protected static final int sScrollIndicatorFadeOutDuration = 650;
protected static final int sScrollIndicatorFlashDuration = 650;
public static final int PAGE_COUNT = 4;
private int mPageWidth = 0;
private int mCurrentPage = 0;
private int mIndicatorPos = 0;
private int mIndicatorSpace = 0;
private GestureDetector mGestureDetector;
private static final boolean DEBUG = true;
private static final String TAG = "indicator";
private Handler mHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
//ht = displaymetrics.heightPixels;
mPageWidth = displaymetrics.widthPixels;
mHandler = new Handler();
setupScrollingIndicator();
mGestureDetector = new GestureDetector(this, new LearnGestureListener());
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (mGestureDetector.onTouchEvent(event))
return true;
else
return false;
}
public void setupScrollingIndicator() {
if(mScrollIndicator == null) {
mScrollIndicator = (ImageView) findViewById(R.id.indicator);
}
mIndicatorSpace = mPageWidth / PAGE_COUNT;
mIndicatorPos = mIndicatorSpace * mCurrentPage;
if(DEBUG) {
Log.i(TAG, "mIndicatorSpace = " + mIndicatorSpace);
Log.i(TAG, "mCurrentPage = " + mCurrentPage);
Log.i(TAG, "mIndicatorPos = " + mIndicatorPos);
}
if(mScrollIndicator.getMeasuredWidth() != mIndicatorSpace) {
mScrollIndicator.getLayoutParams().width = mIndicatorSpace;
mScrollIndicator.requestLayout();
}
mScrollIndicator.setTranslationX(mIndicatorPos);
mScrollIndicator.invalidate();
}
public void showIndicator() {
setupScrollingIndicator();
mScrollIndicator.setVisibility(View.VISIBLE);
cancelScrollingAnimations();
mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 1f);
mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeInDuration);
mScrollIndicatorAnimator.start();
mScrollator = ObjectAnimator.ofFloat(mScrollIndicator, "translationX", mIndicatorPos);
mScrollator.setDuration(sScrollIndicatorFlashDuration);
mScrollator.start();
}
Runnable hideScrollingIndicatorRunnable = new Runnable() {
#Override
public void run() {
hideIndicator();
}
};
protected void flashIndicator() {
showIndicator();
mHandler.postDelayed(hideScrollingIndicatorRunnable, sScrollIndicatorFlashDuration);
}
public void hideIndicator() {
setupScrollingIndicator();
cancelScrollingAnimations();
mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 0f);
mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeOutDuration);
mScrollIndicatorAnimator.addListener(new AnimatorListenerAdapter() {
private boolean cancelled = false;
#Override
public void onAnimationCancel(android.animation.Animator animation) {
cancelled = true;
}
#Override
public void onAnimationEnd(Animator animation) {
if (!cancelled) {
mScrollIndicator.setVisibility(View.INVISIBLE);
}
}
});
mScrollIndicatorAnimator.start();
}
public void cancelScrollingAnimations() {
if(mScrollIndicatorAnimator != null) {
mScrollIndicatorAnimator.cancel();
}
}
public void scrollToRight() {
flashIndicator();
mCurrentPage++;
if(mCurrentPage >= PAGE_COUNT) {
mCurrentPage = 0;
}
}
public void scrollToLeft() {
flashIndicator();
mCurrentPage--;
if(mCurrentPage < 0) {
mCurrentPage = PAGE_COUNT - 1;
}
}
class LearnGestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if(e2.getX() - e1.getX() > 50) {
scrollToLeft();
} else if(e2.getX() - e1.getX() < 50) {
scrollToRight();
}
return true;
}
}
}
Please help me fix this, thanks very much!
mScrollIndicator.setTranslationX(mIndicatorPos) just redraw your view on new position mIndicatorPos. It doesn't do animating.
If you wanna mScrollIndicator move along with your scroll event, try to override onScroll method instead of onFling.
Or another way, create an android.animation.ObjectAnimator object, setup it for your view and call ObjectAnimator.start() on Fling.