I have a class that extends android.view.Animation:
package diffusi.on.com.fifteen_puzzle;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
public class CustomAnimation extends Animation {
private boolean _isLast = false;
private View _currentTarget = null;
public interface AnimationListener {
void onAnimationEnd(CustomAnimation animation);
void onAnimationRepeat(CustomAnimation animation);
void onAnimationStart(CustomAnimation animation);
}
public static void animateSetOfViews(
View[] viewsSet,
int animResId,
int[] startTimeOffsets,
Context context,
AnimationListener animationListener
) {
CustomAnimation animation;
int startTimeOffset;
boolean isLastAnim;
for (int intA = 0; intA < viewsSet.length; intA++) {
isLastAnim = intA == viewsSet.length - 1;
animation = (CustomAnimation) AnimationUtils.loadAnimation(context, animResId);
if (intA <= startTimeOffsets.length - 1) {
startTimeOffset = startTimeOffsets[intA];
} else startTimeOffset = 0;
animation.applyToView(viewsSet[intA], startTimeOffset, isLastAnim, animationListener);
}
}
public CustomAnimation() {
}
public CustomAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
}
public boolean isLast() {
return this._isLast;
}
public View getCurrentTarget() {
return this._currentTarget;
}
private void applyToView(View view, int startTimeOffset, boolean isLast, AnimationListener listener) {
this._isLast = isLast;
this._currentTarget = view;
this.setStartOffset(startTimeOffset);
this.setAnimationListener((Animation.AnimationListener) listener);
this._currentTarget.startAnimation(this);
}
}
It compiles in IDE without errors. But in runtame, it throws an exception (ClassCastEcxeption) on line:
animation = (CustomAnimation) AnimationUtils.loadAnimation(context, animResId)
Why does I can't upcast Animation instance to my CustomAnimation, which extends Animation ?
It's not upcasting, it is downcasting. Upcasting would be of the form CustomAnimation to Animation.
Presumably AnimationUtils.loadAnimation returns a reference to an object which isn't actually a CustomAnimation - so you can't cast to it. You can only cast to a type when the actual type of the object at execution time is compatible with the type you're casting to. For example:
Object x = new Integer(10);
String y = (String) x; // Bang - invalid cast
Object a = "Foo";
String b = (String) a; // This is fine
Related
I've got a JTextArea with setLineWrap(true) and (for now) setWrapStyleWord(true).
The text which is contained in that textArea contains almost no white space, and so the wrapping never occurs. But the text is semi-colon separated. And so I'd like to achieve a wrap style at the ";" instead of at the " ".
With the following text:
hello;world;foo;bar;I am the Wizard;of;Oz
Wrapping like
hello;world;foo;bar;
I am the Wizard;
of;Oz
Instead of (with setWrapStyleWord(true))
hello;world;foo;bar;I
am the Wizard;of;Oz
or
Instead of (with setWrapStyleWord(false))
hello;world;foo;bar;I a
m the Wizard;of;Oz
Any idea on how to realize this ?
The solution is to tweak the ComponentUI used by the JTextArea. See this discussion.
One could create directly a new ComponentUI and assign it to the JTextArea, but I recommend to create a new JTextArea subclass handling all this under the radar.
The Component
package com.zparkingb.swing;
import com.zparkingb.swing.ui.SeparatedTextAreaUI;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.text.Document;
public class ZSeparatedTextArea extends JTextArea {
private final Character wordSeparator;
private static final String uiClassID = "SeparatedTextAreaUI";
public ZSeparatedTextArea(Character separator) {
super();
this.wordSeparator = separator;
}
public ZSeparatedTextArea(Character separator, String text) {
super(text);
this.wordSeparator = separator;
}
public ZSeparatedTextArea(Character separator, int rows, int columns) {
super(rows, columns);
this.wordSeparator = separator;
}
public ZSeparatedTextArea(Character separator, String text, int rows, int columns) {
super(text, rows, columns);
this.wordSeparator = separator;
}
public ZSeparatedTextArea(Character separator, Document doc) {
super(doc);
this.wordSeparator = separator;
}
public ZSeparatedTextArea(Character separator, Document doc, String text, int rows, int columns) {
super(doc, text, rows, columns);
this.wordSeparator = separator;
}
public Character getWordSeparator() {
return wordSeparator;
}
public void setUI(SeparatedTextAreaUI ui) {
super.setUI(ui);
}
#Override
public void updateUI() {
if (UIManager.get(getUIClassID()) != null) {
SeparatedTextAreaUI ui = (SeparatedTextAreaUI) UIManager.getUI(this);
setUI(ui);
}
else {
setUI(new SeparatedTextAreaUI());
}
}
public SeparatedTextAreaUI getUI() {
return (SeparatedTextAreaUI) ui;
}
#Override
public String getUIClassID() {
return uiClassID;
}
}
The ComponentUI
package com.zparkingb.swing.ui;
import com.zparkingb.swing.ZSeparatedTextArea;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTextAreaUI;
import javax.swing.text.Element;
import javax.swing.text.View;
public class SeparatedTextAreaUI extends BasicTextAreaUI {
private ZSeparatedTextArea textArea = null;
/**
* Creates the view for an element. Returns a SeparatedWrappedPlainView (or WrappedPlainView/PlainView if no wordSeparator is provided)
*
* #param elem the element
*
* #return the view
*/
public View create(Element elem) {
if (textArea.getWordSeparator() == null)
return super.create(elem);
View v = new SeparatedWrappedPlainView(textArea.getWordSeparator(), elem);
return v;
}
public static ComponentUI createUI(JComponent c) {
return new SeparatedTextAreaUI();
}
#Override
public void installUI(JComponent c) {
textArea = (ZSeparatedTextArea) c;
super.installUI(c);
}
#Override
public void uninstallUI(JComponent c) {
super.uninstallUI(c);
textArea = null;
}
}
The View
This one is more tricky. As some information required to do the word wrapping are private in SeparatedWrappedPlainView they have been duplicated (e.g. metrics)
package com.zparkingb.swing.ui;
import java.awt.Container;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
import java.text.BreakIterator;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.Segment;
import javax.swing.text.TabExpander;
import javax.swing.text.Utilities;
import javax.swing.text.WrappedPlainView;
class SeparatedWrappedPlainView extends WrappedPlainView {
private int _tabBase;
private FontMetrics _metrics;
private final Character wordSeparator;
public SeparatedWrappedPlainView(Character wordSeparator, Element elem) {
super(elem);
assert(wordSeparator!=null);
this.wordSeparator=wordSeparator;
}
/**
* Rem: Copied from WrappedPlainView only to be able to use our own
* getBreakLocation instead of the {#link Utilities#getBreakLocation} used by default
*/
#Override
protected int calculateBreakPosition(int p0, int p1) {
Segment s = new Segment();
try {
getDocument().getText(p0, p1 - p0, s);
} catch (BadLocationException ex) {
assert false : "Couldn't load text";
}
int width = getWidth();
int pos;
pos = p0 + getBreakLocation(s, _metrics, _tabBase, _tabBase + width, this, p0);
return pos;
}
/**
* Rem: Copied from {#link Utilities#getBreakLocation} in order to
* to break the text on our separator instead of on whitespaces.
*/
private int getBreakLocation(Segment s, FontMetrics metrics, float x0, float x, TabExpander e, int startOffset) {
char[] txt = s.array;
int txtOffset = s.offset;
int txtCount = s.count;
int index = Utilities.getTabbedTextOffset(s, metrics, x0, x, e, startOffset, false); //, null, useFPIAPI);
if (index >= txtCount - 1) {
return txtCount;
}
for (int i = txtOffset + index; i >= txtOffset; i--) {
char ch = txt[i];
if (ch < 256) {
// break on separator
if (wordSeparator.equals(ch)) {
index = i - txtOffset + 1;
break;
}
}
else {
// a multibyte char found; use BreakIterator to find line break
BreakIterator bit = BreakIterator.getLineInstance();
bit.setText(s);
int breakPos = bit.preceding(i + 1);
if (breakPos > txtOffset) {
index = breakPos - txtOffset;
}
break;
}
}
return index;
}
void _updateMetrics() {
Container component = getContainer();
_metrics = component.getFontMetrics(component.getFont());
}
#Override
public void paint(Graphics g, Shape a) {
Rectangle r = a instanceof Rectangle ? (Rectangle) a : a.getBounds();
_tabBase = r.x;
_updateMetrics();
super.paint(g, a);
}
#Override
public float getPreferredSpan(int axis) {
_updateMetrics();
return super.getPreferredSpan(axis);
}
#Override
public float getMaximumSpan(int axis) {
_updateMetrics();
return super.getMaximumSpan(axis);
}
#Override
public float getMinimumSpan(int axis) {
_updateMetrics();
return super.getMinimumSpan(axis);
}
#Override
public void setSize(float width, float height) {
_updateMetrics();
super.setSize(width, height);
}
}
I'm pretty new at Java and need answer quick so don't judge if I haven't searched enough. So i have class Antena and trying to make Controller class and i can't make array list instance. Code is unfinished. Can someone solve this? :D
This is controller class:
package paket;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Scanner;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
public class KontrolaAntene implements Initializable {
private List<Antena> antene= new ArrayList<Antena>();
private int broj;
#FXML
private Button btnIspisi;
#FXML
private Button btnIzlaz;
#FXML
private TextArea taIspis;
#FXML
private TextArea taIspis_izlaz;
#FXML
private Label label1;
#FXML
private Label label2;
#FXML
private Label label3;
#FXML
private TextField tfx;
#FXML
private TextField tfy;
#FXML
void ispisi(ActionEvent event){
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Izaberi datoteku");
fileChooser.getExtensionFilters().addAll(
new ExtensionFilter("Text files","*.txt"),
new ExtensionFilter("All files","*.txt")
);
String pocetakputanja = System.getProperty("user.dir");
File pocetak = new File(pocetakputanja);
if(!pocetak.canRead())
{
pocetak = new File("C:/");
}
fileChooser.setInitialDirectory(pocetak);
File selectedFile = fileChooser.showOpenDialog(TestAntene.mainStage);
if(selectedFile == null || selectedFile.getName()!="antene.txt"){
taIspis.setText("Datoteka antene.txt nije izabrana");
}
else{
taIspis.setText("");
ispisiFajl(selectedFile);
}
}
void ispisiFajl(File selectedFile){
antene.clear();
Path put = Paths.get(selectedFile.getPath());
Charset kod = StandardCharsets.UTF_8;
Scanner sc;
try {
sc = new Scanner(put, kod.name());
while(sc.hasNextLine()){
String linija = sc.nextLine();
String tip = linija.substring(0,linija.indexOf(":")).trim();
String delovi[]= linija.substring(linija.indexOf(":") + 1,
linija.length()).split(", ");
if(tip == "K"){
//THIS LINE IS A PROBLEM!
Antena nova = new Antena(Integer.parseInt(delovi[1].trim()),
Integer.parseInt(delovi[1].trim()),Integer.parseInt(delovi[1].trim()));
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
taIspis.setText("Datoteka antene.txt nije izabrana");
}
}
#FXML
void ispisi_izlaz(ActionEvent event){
taIspis_izlaz.appendText("Broj antena koje pokrivaju zadato mesto je "+broj);
}
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
// TODO Auto-generated method stub
}
}
This is class Antena:
package paket;
public abstract class Antena {
public int x;
public int y;
public int Domet1;
public int Domet2;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getDomet1() {
return Domet1;
}
public void setDomet1(int domet1) {
Domet1 = domet1;
}
public int getDomet2() {
return Domet2;
}
public void setDomet2(int domet2) {
Domet2 = domet2;
}
public Antena(int x, int y, int domet1, int domet2) {
super();
this.x = x;
this.y = y;
Domet1 = domet1;
Domet2 = domet2;
}
boolean uDometu(int x, int y)
{
double rastojanje;
int x2 = getX();
int y2 = getY();
int domet1= getDomet1();
int domet2= getDomet2();
if(getDomet2() == 0){
rastojanje= Math.sqrt((y-y2)*(y-y2)+(x-x2)*(x-x2));
if((double)getDomet1() >= rastojanje)
return true;
else
return false;
}
else
{
if((x2==x && y2+domet2>y)||
(x2==x && y2-domet2<y)||
(x2+domet1>x && y2==y)||
(x2-domet1<x && y2==y)){ return true;}
else if((x2+domet1>=x && y2+domet1>=y)||
(x2-domet1<=x && y2+domet1<=y)||
(x2+domet1<=x && y2+domet1>=y)||
(x2+domet1>=x && y2+domet1<=y))
{return true;}
else return false;
}
}
}
You don't seem to be comparing String(s) correctly, and you can't instantiate an abstract class. Options1,
Remove abstract from Antenna, or
Create a concrete subclass and instantiate that subclass
Something like
if (tip.equals("K")) { // == "K"){
Antenna nova = new Antenna(Integer.parseInt(delovi[1].trim()), // ...
And remember to then change "Antena" like
public class Antenna { // <-- Not abstract
1I have also corrected the spelling of antenna.
There are 2 problems in the line you have marked :
Antena is and abstract class and cannot be instantiated. That's a very fundamental feature of abstract classes that are meant to be inherited from. You should subclass Antena or make non-abstract
You are calling the constructor of Antena and you are passing 3 integers as arguments. But the only constructor for Antena takes 4 arguments of type int
Abstract class and cannot be instantiated and antena is a abstract type.So remove the abstract keyword and it will work.
Basically, I'd like to subclass ClipData.Item so that I can send data other than CharSequence, Intent or URI along with a DragEvent. The docs seem to suggest this is possible (see the documentation alongside the toString() method, which specifically mentions subclasses of Item), however everything I've tried hasn't worked despite neither ClipData nor Item being declared final.
The basic setup that I've got is an inner class extending ClipData.Item like so:
TowerButton.java
package com.conundrum.toweroffensenative.app;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.List;
/**
* Created by Nums on 27/03/14.
*/
public class TowerButton extends View {
private Paint mBackgroundPaint, mTowerPaint, mShadowPaint, mLabelPaint, mDisabledPaint;
private List<Tower> mTowers;
private Path mTowerPath;
private DragShadowBuilder mDragShadowBuilder;
private Rect r;
public TowerButton(Context context, AttributeSet attrs, List<Tower> towers) {
super(context, attrs);
mTowers = towers;
init();
}
// If I need a tower type that starts with 0 stock, add constructor which takes Paint/Path as args
private void init() {
mBackgroundPaint = new Paint();
mBackgroundPaint.setStyle(Paint.Style.FILL);
mBackgroundPaint.setColor(Color.GRAY);
mTowerPaint = mTowers.get(0).getPaint();
mTowerPath = mTowers.get(0).getPath();
mShadowPaint = new Paint(mTowerPaint);
mShadowPaint.setAlpha(150);
mDisabledPaint = new Paint(mTowerPaint);
mDisabledPaint.setColor(Color.LTGRAY);
mDisabledPaint.setAlpha(150);
mLabelPaint = new Paint();
mLabelPaint.setTextSize(28);
mLabelPaint.setTextAlign(Paint.Align.CENTER);
mLabelPaint.setAntiAlias(true);
mLabelPaint.setColor(Color.WHITE);
mDragShadowBuilder = new DragShadowBuilder(this) {
#Override
public void onDrawShadow(Canvas canvas) {
canvas.drawPath(mTowerPath, mShadowPaint);
}
};
setTag(mTowers.get(0).getClass().getName() + "Button");
r = new Rect();
}
public String getQuantity() {
return String.valueOf(mTowers.size());
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Matrix pathMatrix = new Matrix();
RectF pathBounds = new RectF();
mTowerPath.computeBounds(pathBounds, false);
pathMatrix.setScale(w / pathBounds.width(), h / pathBounds.height());
mTowerPath.transform(pathMatrix);
r.set(0, 0, w, h);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(r, mBackgroundPaint);
if (mTowers.size() > 0) {
canvas.drawPath(mTowerPath, mTowerPaint);
canvas.drawText(getQuantity(), getX() + (getWidth() / 2), getY() + (getHeight() / 2), mLabelPaint);
} else {
canvas.drawPath(mTowerPath, mDisabledPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN && mTowers.size() > 0) {
Tower dragTower = mTowers.get(0);
TowerItem item = new TowerItem(dragTower);
ClipData dragData = new ClipData(dragTower.getBuildRow(),
new String[]{ ClipDescription.MIMETYPE_TEXT_PLAIN }, item);
startDrag(dragData, mDragShadowBuilder, null, 0);
return true;
}
return false;
}
public Tower giveTower() {
// TODO: need checking to ensure size > 0?
Tower tower = mTowers.remove(0);
invalidate();
return tower;
}
public void recycleTower(Tower tower) {
mTowers.add(tower);
invalidate();
}
public static class TowerItem extends ClipData.Item {
final Tower mTower;
public TowerItem(Tower tower) {
super("");
mTower = tower;
}
public Tower getTower() {
return mTower;
}
#Override
public CharSequence coerceToText(Context context) {
if (mTower != null) {
return mTower.getClass().getName();
}
return super.coerceToText(context);
}
}
}
Then, in the class which will accept the DropEvent:
TowerView.java
package com.conundrum.toweroffensenative.app;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.ClipData;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.DragEvent;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
/**
* Created by Nums on 24/03/14.
*/
public class TowerView extends View {
private Paint mBasePaint, mHighlightPaint, mStunnedPaint, mSelectedPaint;
private Tower mTower;
private Path mTowerPath;
private Paint mTowerPaint;
private boolean highlighted;
private boolean stunned;
private boolean selected;
private int mIndex;
private List<TowerView> mNeighbours;
private Rect r;
private class mListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onDown(MotionEvent e) {
return true;
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
for (TowerView tv : mNeighbours) {
tv.highlighted ^= true;
tv.invalidate();
}
return true;
}
#Override
public void onLongPress(MotionEvent e) {
List<TowerView> myRow = ((TowerGrid) getParent()).getRow(mIndex % TowerGrid.ROWS);
for (TowerView v : myRow) {
v.stunned ^= true;
v.invalidate();
}
}
}
GestureDetector mDetector = new GestureDetector(TowerView.this.getContext(), new mListener());
Callable<Void> mStartRecycleCallable = new Callable<Void>() {
#Override
public Void call() throws Exception {
startRecycle();
return null;
}
};
Callable<Void> mRecycleCallable = new Callable<Void>() {
#Override
public Void call() throws Exception {
recycle();
return null;
}
};
public TowerView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mIndex = -1;
mNeighbours = new ArrayList<TowerView>();
highlighted = false;
stunned = false;
selected = false;
LinearGradient baseGradient = new LinearGradient(0, 0, 0, 25,
new int[] {Color.LTGRAY, Color.DKGRAY}, null, Shader.TileMode.MIRROR);
LinearGradient highlightGradient = new LinearGradient(0, 0, 0, 25,
new int[] {Color.YELLOW, Color.RED}, null, Shader.TileMode.MIRROR);
LinearGradient stunnedGradient = new LinearGradient(0, 0, 0, 25,
new int[] {Color.CYAN, Color.BLUE}, null, Shader.TileMode.MIRROR);
mBasePaint = new Paint();
mBasePaint.setShader(baseGradient);
mHighlightPaint = new Paint();
mHighlightPaint.setShader(highlightGradient);
mStunnedPaint = new Paint();
mStunnedPaint.setShader(stunnedGradient);
mSelectedPaint = new Paint();
mSelectedPaint.setStyle(Paint.Style.STROKE);
mSelectedPaint.setColor(Color.GREEN);
mSelectedPaint.setStrokeWidth(5);
r = new Rect();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
r.set(0, 0, w, h);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Draw the tower base in one of three styles
if (highlighted) {
canvas.drawRect(r, mHighlightPaint);
} else if (stunned) {
canvas.drawRect(r, mStunnedPaint);
} else {
canvas.drawRect(r, mBasePaint);
}
if (mTower != null) {
canvas.drawPath(mTowerPath, mTowerPaint);
}
if (selected) {
canvas.drawRect(r, mSelectedPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean result = mDetector.onTouchEvent(event);
if (!result) {
// Custom gesture code
}
return result;
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
boolean result = super.dispatchTouchEvent(event);
return result;
}
#Override
public boolean onDragEvent(DragEvent event) {
final int action = event.getAction();
switch(action) {
case DragEvent.ACTION_DRAG_STARTED:
// check if Tower can be built on this col - in case I allow that to differ per Tower
if (mIndex / TowerGrid.ROWS == Integer.parseInt(event.getClipDescription().getLabel().toString())) {
selected = true;
invalidate();
return true;
}
return false;
case DragEvent.ACTION_DRAG_ENTERED:
highlighted = true;
invalidate();
break;
case DragEvent.ACTION_DRAG_EXITED:
highlighted = false;
invalidate();
break;
case DragEvent.ACTION_DROP:
ClipData.Item item = event.getClipData().getItemAt(0);
if (item instanceof TowerButton.TowerItem) {
Log.d("towerview", "SUCCESS!");
}
// Always returns false
TowerButton.TowerItem tItem = (TowerButton.TowerItem) item; // exception
Tower dragTower = item.getTower();
setTower(dragTower);
return true;
case DragEvent.ACTION_DRAG_ENDED:
highlighted = false;
selected = false;
invalidate();
return true;
}
return false;
}
public void setTower(Tower tower) {
if (mTower != null) {
TowerButton button = (TowerButton) getRootView().findViewWithTag(mTower.getClass().getName() + "Button");
button.recycleTower(mTower);
}
mTower = tower;
mTowerPaint = tower.getPaint();
mTowerPath = tower.getPath();
Matrix pathMatrix = new Matrix();
RectF pathBounds = new RectF();
mTowerPath.computeBounds(pathBounds, false);
pathMatrix.setScale(getWidth() / pathBounds.width(), getHeight() / pathBounds.height());
mTowerPath.transform(pathMatrix);
invalidate();
}
public boolean advance(int distance) {
if (!stunned) {
// first account for the new view being added
setTranslationX(getTranslationX() - distance);
// then animate right over 1000 ms
ViewPropertyAnimator animator = animate().translationXBy(distance).setDuration(1000);
addCompatibilityAnimationCallback(animator, mStartRecycleCallable).start();
return true;
}
return false;
}
private void startRecycle() {
if (mIndex / TowerGrid.ROWS == TowerGrid.COLS - 1) {
ViewPropertyAnimator animator = animate().translationXBy(getWidth() / -2).scaleX(0).setDuration(1000);
addCompatibilityAnimationCallback(animator, mRecycleCallable).start();
}
}
private void recycle() {
if (mTower != null) {
TowerButton button = (TowerButton) getRootView().findViewWithTag(mTower.getClass().getName() + "Button");
button.recycleTower(mTower);
}
((ViewGroup) getParent()).removeView(this);
}
public void updateNeighbours() {
ViewGroup parent = (ViewGroup) getParent();
mIndex = parent.indexOfChild(this);
mNeighbours.clear();
if (mIndex >= TowerGrid.ROWS) {
mNeighbours.add((TowerView) parent.getChildAt(mIndex - TowerGrid.ROWS));
}
if (mIndex < TowerGrid.ROWS * (TowerGrid.COLS - 2)) {
mNeighbours.add((TowerView) parent.getChildAt(mIndex + TowerGrid.ROWS));
}
if (mIndex % TowerGrid.ROWS != 0) {
mNeighbours.add((TowerView) parent.getChildAt(mIndex - 1));
}
if (mIndex % TowerGrid.ROWS != TowerGrid.ROWS - 1) {
mNeighbours.add((TowerView) parent.getChildAt(mIndex + 1));
}
}
private ViewPropertyAnimator addCompatibilityAnimationCallback(ViewPropertyAnimator animator, final Callable<Void> callbackFunc) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
animator.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
try {
callbackFunc.call();
} catch (Exception e) {
e.printStackTrace();
}
}
});
} else {
animator.withEndAction(new Runnable() {
#Override
public void run() {
try {
callbackFunc.call();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
return animator;
}
}
There are no compile-time errors. However, when attempting to perform the cast at runtime, I get the exception:
java.lang.ClassCastException: android.content.ClipData$Item cannot be cast to com.conundrum.toweroffensenative.app.TowerButton$TowerItem
Similarly, code like item instanceof TowerButton.TowerItem returns false, even though TowerItem is obviously extending ClipData.Item.
Is there something I'm missing that prevents these classes from being subclassed? Or am I doing something wrong? I know I could use a ContentProvider and URIs to transfer more complex information, but that seems like overkill when the data being transferred never has to be made available outside this application.
EDIT
I've also tried making a subclass of ClipData with it's own Item inner class, so that I can override getItem() to return a TowerItem - but then I need to cast a ClipData to a TowerClipData, which fails with the same error.
EDIT 3
Included the entirety of both relevant files.
TowerItem is descended from ClipData.Item, therefore a TowerItem is a ClipData.Item but the reverse is not always true. A ClipData.Item can be a TowerItem but it isn't necessarily.
You avoid the compiler error by explicitly casting ClipData.Item to TowerItem: (TowerItem)ClipData.Item. But you cannot avoid runtime error.
The right usage of instanceOf should be in this way:
if(event.getClipData().getItemAt(0) instanceOf TowerButton.TowerItem) {
TowerButton.TowerItem item = (TowerButton.TowerItem) event.getClipData().getItemAt(0);
}
Similar problem, and I've been going over the system code for this. Basically, the ClipData is a Parcelable, so I think a subclass of ClipData.Item which doesn't have a sensible subclass of ClipData that recognises your custom ClipData.Item is going to get converted to a Charsequence and then come back as a basic text ClipData.Item. Otherwise, you need to create a ContentProvider for the URI format, which, for this use case, a ui in a single app, is overkill and possibly wrong.
My hack for this was eventually to pass an identifying tag in the ClipData as text, and make the drag initiating view (passed in the event data via the state) responsible for turning this into an object. Not entirely clean but not totally ugly.
Hi i have created and android application using an ipcamera,for that i have used mjpeg class
Main class
package com.example.mjpeg;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
import com.example.mjpeg.MjpegInputStream;
import com.example.mjpeg.MjpegView;
public class MainActivity extends Activity {
private MjpegView mv;
private static final int MENU_QUIT = 1;
/* Creates the menu items */
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MENU_QUIT, 0, "Quit");
return true;
}
/* Handles item selections */
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_QUIT:
finish();
return true;
}
return false;
}
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
//sample public cam
String URL = "http://192.168.2.1/?action=appletvstream";
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
mv = new MjpegView(this);
setContentView(mv);
mv.setSource(MjpegInputStream.read(URL));
mv.setDisplayMode(MjpegView.SIZE_BEST_FIT);
mv.showFps(false);
}
public void onPause() {
super.onPause();
mv.stopPlayback();
}
}
MjpegInputstream class
package com.example.mjpeg;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Properties;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class MjpegInputStream extends DataInputStream {
private final byte[] SOI_MARKER = { (byte) 0xFF, (byte) 0xD8 };
private final byte[] EOF_MARKER = { (byte) 0xFF, (byte) 0xD9 };
private final String CONTENT_LENGTH = "Content-Length";
private final static int HEADER_MAX_LENGTH = 100;
private final static int FRAME_MAX_LENGTH = 40000 + HEADER_MAX_LENGTH;
private int mContentLength = -1;
public static MjpegInputStream read(String url) {
HttpResponse res;
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
res = httpclient.execute(new HttpGet(URI.create(url)));
return new MjpegInputStream(res.getEntity().getContent());
} catch (ClientProtocolException e) {
} catch (IOException e) {}
return null;
}
public MjpegInputStream(InputStream in) { super(new BufferedInputStream(in, FRAME_MAX_LENGTH)); }
private int getEndOfSeqeunce(DataInputStream in, byte[] sequence) throws IOException {
int seqIndex = 0;
byte c;
for(int i=0; i < FRAME_MAX_LENGTH; i++) {
c = (byte) in.readUnsignedByte();
if(c == sequence[seqIndex]) {
seqIndex++;
if(seqIndex == sequence.length) return i + 1;
} else seqIndex = 0;
}
return -1;
}
private int getStartOfSequence(DataInputStream in, byte[] sequence) throws IOException {
int end = getEndOfSeqeunce(in, sequence);
return (end < 0) ? (-1) : (end - sequence.length);
}
private int parseContentLength(byte[] headerBytes) throws IOException, NumberFormatException {
ByteArrayInputStream headerIn = new ByteArrayInputStream(headerBytes);
Properties props = new Properties();
props.load(headerIn);
return Integer.parseInt(props.getProperty(CONTENT_LENGTH));
}
public Bitmap readMjpegFrame() throws IOException {
mark(FRAME_MAX_LENGTH);
int headerLen = getStartOfSequence(this, SOI_MARKER);
reset();
byte[] header = new byte[headerLen];
readFully(header);
try {
mContentLength = parseContentLength(header);
} catch (NumberFormatException nfe) {
mContentLength = getEndOfSeqeunce(this, EOF_MARKER);
}
reset();
byte[] frameData = new byte[mContentLength];
skipBytes(headerLen);
readFully(frameData);
return BitmapFactory.decodeStream(new ByteArrayInputStream(frameData));
}
}
Mjpeg View
package com.example.mjpeg;
import java.io.IOException;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MjpegView extends SurfaceView implements SurfaceHolder.Callback {
public final static int POSITION_UPPER_LEFT = 9;
public final static int POSITION_UPPER_RIGHT = 3;
public final static int POSITION_LOWER_LEFT = 12;
public final static int POSITION_LOWER_RIGHT = 6;
public final static int SIZE_STANDARD = 1;
public final static int SIZE_BEST_FIT = 4;
public final static int SIZE_FULLSCREEN = 8;
private MjpegViewThread thread;
private MjpegInputStream mIn = null;
private boolean showFps = false;
private boolean mRun = false;
private boolean surfaceDone = false;
private Paint overlayPaint;
private int overlayTextColor;
private int overlayBackgroundColor;
private int ovlPos;
private int dispWidth;
private int dispHeight;
private int displayMode;
public class MjpegViewThread extends Thread {
private SurfaceHolder mSurfaceHolder;
private int frameCounter = 0;
private long start;
private Bitmap ovl;
public MjpegViewThread(SurfaceHolder surfaceHolder, Context context) { mSurfaceHolder = surfaceHolder; }
private Rect destRect(int bmw, int bmh) {
int tempx;
int tempy;
if (displayMode == MjpegView.SIZE_STANDARD) {
tempx = (dispWidth / 2) - (bmw / 2);
tempy = (dispHeight / 2) - (bmh / 2);
return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
}
if (displayMode == MjpegView.SIZE_BEST_FIT) {
float bmasp = (float) bmw / (float) bmh;
bmw = dispWidth;
bmh = (int) (dispWidth / bmasp);
if (bmh > dispHeight) {
bmh = dispHeight;
bmw = (int) (dispHeight * bmasp);
}
tempx = (dispWidth / 2) - (bmw / 2);
tempy = (dispHeight / 2) - (bmh / 2);
return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
}
if (displayMode == MjpegView.SIZE_FULLSCREEN) return new Rect(0, 0, dispWidth, dispHeight);
return null;
}
public void setSurfaceSize(int width, int height) {
synchronized(mSurfaceHolder) {
dispWidth = width;
dispHeight = height;
}
}
private Bitmap makeFpsOverlay(Paint p, String text) {
Rect b = new Rect();
p.getTextBounds(text, 0, text.length(), b);
int bwidth = b.width()+2;
int bheight = b.height()+2;
Bitmap bm = Bitmap.createBitmap(bwidth, bheight, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
p.setColor(overlayBackgroundColor);
c.drawRect(0, 0, bwidth, bheight, p);
p.setColor(overlayTextColor);
c.drawText(text, -b.left+1, (bheight/2)-((p.ascent()+p.descent())/2)+1, p);
return bm;
}
public void run() {
start = System.currentTimeMillis();
PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER);
Bitmap bm;
int width;
int height;
Rect destRect;
Canvas c = null;
Paint p = new Paint();
String fps = "";
while (mRun) {
if(surfaceDone) {
try {
c = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder) {
try {
bm = mIn.readMjpegFrame();
destRect = destRect(bm.getWidth(),bm.getHeight());
c.drawColor(Color.BLACK);
c.drawBitmap(bm, null, destRect, p);
if(showFps) {
p.setXfermode(mode);
if(ovl != null) {
height = ((ovlPos & 1) == 1) ? destRect.top : destRect.bottom-ovl.getHeight();
width = ((ovlPos & 8) == 8) ? destRect.left : destRect.right -ovl.getWidth();
c.drawBitmap(ovl, width, height, null);
}
p.setXfermode(null);
frameCounter++;
if((System.currentTimeMillis() - start) >= 1000) {
fps = String.valueOf(frameCounter)+"fps";
frameCounter = 0;
start = System.currentTimeMillis();
ovl = makeFpsOverlay(overlayPaint, fps);
}
}
} catch (IOException e) {}
}
} finally { if (c != null) mSurfaceHolder.unlockCanvasAndPost(c); }
}
}
}
}
private void init(Context context) {
SurfaceHolder holder = getHolder();
holder.addCallback(this);
thread = new MjpegViewThread(holder, context);
setFocusable(true);
overlayPaint = new Paint();
overlayPaint.setTextAlign(Paint.Align.LEFT);
overlayPaint.setTextSize(12);
overlayPaint.setTypeface(Typeface.DEFAULT);
overlayTextColor = Color.WHITE;
overlayBackgroundColor = Color.BLACK;
ovlPos = MjpegView.POSITION_LOWER_RIGHT;
displayMode = MjpegView.SIZE_STANDARD;
dispWidth = getWidth();
dispHeight = getHeight();
}
public void startPlayback() {
if(mIn != null) {
mRun = true;
thread.start();
}
}
public void stopPlayback() {
mRun = false;
boolean retry = true;
while(retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {}
}
}
public MjpegView(Context context, AttributeSet attrs) { super(context, attrs); init(context); }
public void surfaceChanged(SurfaceHolder holder, int f, int w, int h) { thread.setSurfaceSize(w, h); }
public void surfaceDestroyed(SurfaceHolder holder) {
surfaceDone = false;
stopPlayback();
}
public MjpegView(Context context) {
super(context);
init(context);
}
public void surfaceCreated(SurfaceHolder holder) {
surfaceDone = true;
}
public void showFps(boolean b) {
showFps = b;
}
public void setSource(MjpegInputStream source) {
mIn = source;
startPlayback();
}
public void setOverlayPaint(Paint p) {
overlayPaint = p;
}
public void setOverlayTextColor(int c) {
overlayTextColor = c;
}
public void setOverlayBackgroundColor(int c) {
overlayBackgroundColor = c;
}
public void setOverlayPosition(int p) {
ovlPos = p;
}
public void setDisplayMode(int s) {
displayMode = s;
}
}
i got this code from a blog,now i want to take a picture when i click on a button and save it in sd card,can anyone help me please
currently i can only view the video from the ipcam,i need to add a button in this class and when i click on the button it should capture a image and save it in sdcard.
You have a public Bitmap readMjpegFrame() method right there in MjpegInputStream.
Take the bitmap from that method and save it on SD card after you click on the button.
I have a simple list field class which shows the default menu when I select a particular listitem. I want to customize the listfield item, so that when an item is selected a new screen is pushed onto the stack. I am overridding trackwheeel() method, but am not able to make it work.
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import java.util.Vector;
public class TeamListScreen extends UiApplication
{
public static void main(String[] args)
{
TeamListScreen theApp = new TeamListScreen();
theApp.enterEventDispatcher();
}
public TeamListScreen()
{
pushScreen(new ListFieldScreen());
}
}
class ListFieldScreen extends MainScreen
{
private ListField _listField;
private Vector _listElements;
int listFieldIndex = -1;
public ListFieldScreen()
{
setTitle("List Field Sample");
_listElements = new Vector();
_listField = new ListField();
ListCallback _callback = new ListCallback();
_listField.setCallback(_callback);
_listField.setRowHeight(45);
//_listField.setChangeListener(this);
add(_listField);
initializeList();
_listField = new ListField(_listElements.size()) {
protected void drawFocus(Graphics graphics, boolean on) {
}
protected boolean trackwheelClick(int status, int time) {
listFieldIndex = _listField.getSelectedIndex();
if (listFieldIndex < 0) {
listFieldIndex = 0;
}
try {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(new LiveScreen());
// UiApplication.getUiApplication().popScreen(getActiveScreen());
}
});
} catch (Exception e) {
}
return true;
}
};
}
private void initializeList()
{
String itemOne = "List item one";
String itemTwo = "List item two";
_listElements.addElement(itemOne);
_listElements.addElement(itemTwo);
reloadList();
}
private void reloadList()
{
_listField.setSize(_listElements.size());
}
private class ListCallback implements ListFieldCallback
{
public void drawListRow(ListField list, Graphics g, int index, int y, int w)
{
String text = (String)_listElements.elementAt(index);
g.drawText(text, 0, y, 0, w);
}
public Object get(ListField list, int index)
{
return _listElements.elementAt(index);
}
public int indexOfList(ListField list, String prefix, int string)
{
return _listElements.indexOf(prefix, string);
}
public int getPreferredWidth(ListField list)
{
return Display.getWidth();
}
}
}
trackwheelClick() function is deprecated, you should use navigationClick() instead.
BTW, you don't need to use UiApplication.getUiApplication().invokeLater, because it is already running in the event queue.