I am still relatively new to Java, and am trying to work with the code at the address. http://proyectouvipool.googlecode.com/svn-history/r87/trunk/Android/PFC/src/pablo/developer/BalloonItemizedOverlay.java
Unfortunately, I get the following error message
Bound mismatch: The type Item is not a valid substitute for the bounded parameter of the type BalloonOverlayView
at code
protected BalloonOverlayView<Item> createBalloonOverlayView() {
return new BalloonOverlayView<Item>(getMapView().getContext(), getBalloonBottomOffset());
}
Would appreciate some help on what to do to fix this?
public class CustomBalloonItemizedOverlay extends
BalloonItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> m_overlays = new ArrayList<OverlayItem>();
private Context c;
public MyFavoritePlacesItemizedOverlay(Drawable defaultMarker,
MapView mapView) {
super(boundCenter(defaultMarker), mapView);
c = mapView.getContext();
}
public void addOverlay(OverlayItem overlay) {
m_overlays.add(overlay);
populate();
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
if (!shadow) {
super.draw(canvas, mapView, false);
}
}
public void removeOverlay(OverlayItem overlay) {
m_overlays.remove(overlay);
populate();
}
#Override
protected OverlayItem createItem(int i) {
return m_overlays.get(i);
}
#Override
public int size() {
return m_overlays.size();
}
#Override
protected boolean onBalloonTap(int index, OverlayItem item) {
// Your code...
return true;
}
}
Below is how to use that...
initGeoPoint = new GeoPoint((int) (latitude * 1E6),
(int) (longitude * 1E6));
mapOverlays = myMapView.getOverlays();
drawableImage = this.getResources().getDrawable(R.drawable.any_icon);
CustomBalloonItemizedOverlay customItemizedOverlayObject = new public class CustomBalloonItemizedOverlay(
drawableImage, myMapView);
OverlayItem overlayItem = new OverlayItem(initGeoPoint, name,
address);
customItemizedOverlayObject.addOverlay(overlayItem);
mapOverlays.add(customItemizedOverlayObject);
}
Related
I am trying to implement a ImageView which will have different reaction with each action(Drag, DoubleTap and Single Tap). What I am doing is based in this tutorial:
DoubleTap in android
Which I used to create my class:
public class MyIcon extends ImageView {
GestureDetector gestureDetector;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// creating new gesture detector
gestureDetector = new GestureDetector(context, new GestureListener());
}
// skipping measure calculation and drawing
// delegate the event to the gesture detector
#Override
public boolean onTouchEvent(MotionEvent e) {
return gestureDetector.onTouchEvent(e);
}
private class GestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onDown(MotionEvent e) {
return true;
}
// event when double tap occurs
#Override
public boolean onDoubleTap(MotionEvent e) {
//A Toast just to see if it is working
return true;
}
#Override
public boolean onShowPress(MotionEvent e) {
//A Toast just to see if it is working
return true;
}
}
}
To instantiate:
private WindowManager windowManager;
private MyIcon myIcon;
private WindowManager.LayoutParams params;
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
chatHead = new MyIcon(this);
chatHead.setImageResource(R.mipmap.ic_launcher);
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT
);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
params.y = 100;
I used a setOnTouchListener() which worked fine to make do Drag, but it is not work to DoubleTap.
Which would be the correct way to implement and instantiate this class to both work?
try this may help you SimpleGestureFilter
public class SimpleGestureFilter extends SimpleOnGestureListener {
public final static int SWIPE_UP = 1;
public final static int SWIPE_DOWN = 2;
public final static int SWIPE_LEFT = 3;
public final static int SWIPE_RIGHT = 4;
public final static int MODE_TRANSPARENT = 0;
public final static int MODE_SOLID = 1;
public final static int MODE_DYNAMIC = 2;
private final static int ACTION_FAKE = -13; // just an unlikely number
private int swipe_Min_Distance = 100;
private int swipe_Max_Distance = 350;
private int swipe_Min_Velocity = 100;
private int mode = MODE_DYNAMIC;
private boolean running = true;
private boolean tapIndicator = false;
private Activity context;
private GestureDetector detector;
private SimpleGestureListener listener;
public SimpleGestureFilter(Activity context, SimpleGestureListener sgl) {
this.context = context;
this.detector = new GestureDetector(context, this);
this.listener = sgl;
}
public void onTouchEvent(MotionEvent event) {
if (!this.running)
return;
boolean result = this.detector.onTouchEvent(event);
if (this.mode == MODE_SOLID)
event.setAction(MotionEvent.ACTION_CANCEL);
else if (this.mode == MODE_DYNAMIC) {
if (event.getAction() == ACTION_FAKE)
event.setAction(MotionEvent.ACTION_UP);
else if (result)
event.setAction(MotionEvent.ACTION_CANCEL);
else if (this.tapIndicator) {
event.setAction(MotionEvent.ACTION_DOWN);
this.tapIndicator = false;
}
}
// else just do nothing, it's Transparent
}
public void setMode(int m) {
this.mode = m;
}
public int getMode() {
return this.mode;
}
public void setEnabled(boolean status) {
this.running = status;
}
public void setSwipeMaxDistance(int distance) {
this.swipe_Max_Distance = distance;
}
public void setSwipeMinDistance(int distance) {
this.swipe_Min_Distance = distance;
}
public void setSwipeMinVelocity(int distance) {
this.swipe_Min_Velocity = distance;
}
public int getSwipeMaxDistance() {
return this.swipe_Max_Distance;
}
public int getSwipeMinDistance() {
return this.swipe_Min_Distance;
}
public int getSwipeMinVelocity() {
return this.swipe_Min_Velocity;
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
final float xDistance = Math.abs(e1.getX() - e2.getX());
final float yDistance = Math.abs(e1.getY() - e2.getY());
if (xDistance > this.swipe_Max_Distance
|| yDistance > this.swipe_Max_Distance)
return false;
velocityX = Math.abs(velocityX);
velocityY = Math.abs(velocityY);
boolean result = false;
if (velocityX > this.swipe_Min_Velocity
&& xDistance > this.swipe_Min_Distance) {
if (e1.getX() > e2.getX()) // right to left
this.listener.onSwipe(SWIPE_LEFT);
else
this.listener.onSwipe(SWIPE_RIGHT);
result = true;
} else if (velocityY > this.swipe_Min_Velocity
&& yDistance > this.swipe_Min_Distance) {
if (e1.getY() > e2.getY()) // bottom to up
this.listener.onSwipe(SWIPE_UP);
else
this.listener.onSwipe(SWIPE_DOWN);
result = true;
}
return result;
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
this.tapIndicator = true;
return false;
}
#Override
public boolean onDoubleTap(MotionEvent arg) {
this.listener.onDoubleTap();
;
return true;
}
#Override
public boolean onDoubleTapEvent(MotionEvent arg) {
return true;
}
#Override
public boolean onSingleTapConfirmed(MotionEvent arg) {
if (this.mode == MODE_DYNAMIC) { // we owe an ACTION_UP, so we fake an
arg.setAction(ACTION_FAKE); // action which will be converted to an
// ACTION_UP later.
this.context.dispatchTouchEvent(arg);
}
return false;
}
static interface SimpleGestureListener {
void onSwipe(int direction);
void onDoubleTap();
}
}
Use in code this way
private SimpleGestureFilter detector;
detector = new SimpleGestureFilter(this, this);
Just change in this method
#Override
public boolean dispatchTouchEvent(MotionEvent me) {
// Call onTouchEvent of SimpleGestureFilter class
this.detector.onTouchEvent(me);
return super.dispatchTouchEvent(me);
}
I looked several places, including on here and the answers I found did not help. I also looked through the code of the template that I am using and did not see where I went wrong, so I am sorry if this seems like a bad question. But I am making a watch face and I am trying to extend it from my Engine, WeatherWatchFaceEngine. But when I do this, I get the error that is in the title of this question. What have I done wrong?
This is the code of the watch face:
public class NimbusSplashAnalog extends WeatherWatchFaceService {
/**
* Update rate in milliseconds for interactive mode. We update once a second to advance the
* second hand.
*/
private static final long INTERACTIVE_UPDATE_RATE_MS = TimeUnit.SECONDS.toMillis(1);
/**
* Handler message id for updating the time periodically in interactive mode.
*/
private static final int MSG_UPDATE_TIME = 0;
#Override
public Engine onCreateEngine() {
return new Engine();
}
private class Engine extends WeatherWatchFaceEngine {
Paint mBackgroundPaint;
Paint mHandPaint;
boolean mAmbient;
Time mTime;
final Handler mUpdateTimeHandler = new EngineHandler(this);
final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
mTime.clear(intent.getStringExtra("time-zone"));
mTime.setToNow();
}
};
boolean mRegisteredTimeZoneReceiver = false;
/**
* Whether the display supports fewer bits for each color in ambient mode. When true, we
* disable anti-aliasing in ambient mode.
*/
boolean mLowBitAmbient;
#Override
public void onCreate(SurfaceHolder holder) {
super.onCreate(holder);
setWatchFaceStyle(new WatchFaceStyle.Builder(NimbusSplashAnalog.this)
.setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT)
.setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
.setShowSystemUiTime(false)
.build());
Resources resources = NimbusSplashAnalog.this.getResources();
mBackgroundPaint = new Paint();
mBackgroundPaint.setColor(resources.getColor(R.color.analog_background));
mHandPaint = new Paint();
mHandPaint.setColor(resources.getColor(R.color.analog_hands));
mHandPaint.setStrokeWidth(resources.getDimension(R.dimen.analog_hand_stroke));
mHandPaint.setAntiAlias(true);
mHandPaint.setStrokeCap(Paint.Cap.ROUND);
mTime = new Time();
}
#Override
public void onDestroy() {
mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME);
super.onDestroy();
}
#Override
public void onPropertiesChanged(Bundle properties) {
super.onPropertiesChanged(properties);
mLowBitAmbient = properties.getBoolean(PROPERTY_LOW_BIT_AMBIENT, false);
}
#Override
public void onTimeTick() {
super.onTimeTick();
invalidate();
}
#Override
public void onAmbientModeChanged(boolean inAmbientMode) {
super.onAmbientModeChanged(inAmbientMode);
if (mAmbient != inAmbientMode) {
mAmbient = inAmbientMode;
if (mLowBitAmbient) {
mHandPaint.setAntiAlias(!inAmbientMode);
}
invalidate();
}
// Whether the timer should be running depends on whether we're visible (as well as
// whether we're in ambient mode), so we may need to start or stop the timer.
updateTimer();
}
#Override
public void onDraw(Canvas canvas, Rect bounds) {
mTime.setToNow();
int width = bounds.width();
int height = bounds.height();
// Draw the background.
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mBackgroundPaint);
// Find the center. Ignore the window insets so that, on round watches with a
// "chin", the watch face is centered on the entire screen, not just the usable
// portion.
float centerX = width / 2f;
float centerY = height / 2f;
float secRot = mTime.second / 30f * (float) Math.PI;
int minutes = mTime.minute;
float minRot = minutes / 30f * (float) Math.PI;
float hrRot = ((mTime.hour + (minutes / 60f)) / 6f) * (float) Math.PI;
float secLength = centerX - 20;
float minLength = centerX - 40;
float hrLength = centerX - 80;
if (!mAmbient) {
float secX = (float) Math.sin(secRot) * secLength;
float secY = (float) -Math.cos(secRot) * secLength;
canvas.drawLine(centerX, centerY, centerX + secX, centerY + secY, mHandPaint);
}
float minX = (float) Math.sin(minRot) * minLength;
float minY = (float) -Math.cos(minRot) * minLength;
canvas.drawLine(centerX, centerY, centerX + minX, centerY + minY, mHandPaint);
float hrX = (float) Math.sin(hrRot) * hrLength;
float hrY = (float) -Math.cos(hrRot) * hrLength;
canvas.drawLine(centerX, centerY, centerX + hrX, centerY + hrY, mHandPaint);
}
#Override
public void onVisibilityChanged(boolean visible) {
super.onVisibilityChanged(visible);
if (visible) {
registerReceiver();
// Update time zone in case it changed while we weren't visible.
mTime.clear(TimeZone.getDefault().getID());
mTime.setToNow();
} else {
unregisterReceiver();
}
// Whether the timer should be running depends on whether we're visible (as well as
// whether we're in ambient mode), so we may need to start or stop the timer.
updateTimer();
}
private void registerReceiver() {
if (mRegisteredTimeZoneReceiver) {
return;
}
mRegisteredTimeZoneReceiver = true;
IntentFilter filter = new IntentFilter(Intent.ACTION_TIMEZONE_CHANGED);
NimbusSplashAnalog.this.registerReceiver(mTimeZoneReceiver, filter);
}
private void unregisterReceiver() {
if (!mRegisteredTimeZoneReceiver) {
return;
}
mRegisteredTimeZoneReceiver = false;
NimbusSplashAnalog.this.unregisterReceiver(mTimeZoneReceiver);
}
/**
* Starts the {#link #mUpdateTimeHandler} timer if it should be running and isn't currently
* or stops it if it shouldn't be running but currently is.
*/
private void updateTimer() {
mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME);
if (shouldTimerBeRunning()) {
mUpdateTimeHandler.sendEmptyMessage(MSG_UPDATE_TIME);
}
}
/**
* Returns whether the {#link #mUpdateTimeHandler} timer should be running. The timer should
* only run when we're visible and in interactive mode.
*/
private boolean shouldTimerBeRunning() {
return isVisible() && !isInAmbientMode();
}
/**
* Handle updating the time periodically in interactive mode.
*/
private void handleUpdateTimeMessage() {
invalidate();
if (shouldTimerBeRunning()) {
long timeMs = System.currentTimeMillis();
long delayMs = INTERACTIVE_UPDATE_RATE_MS
- (timeMs % INTERACTIVE_UPDATE_RATE_MS);
mUpdateTimeHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIME, delayMs);
}
}
}
private static class EngineHandler extends Handler {
private final WeakReference<NimbusSplashAnalog.Engine> mWeakReference;
public EngineHandler(NimbusSplashAnalog.Engine reference) {
mWeakReference = new WeakReference<>(reference);
}
#Override
public void handleMessage(Message msg) {
NimbusSplashAnalog.Engine engine = mWeakReference.get();
if (engine != null) {
switch (msg.what) {
case MSG_UPDATE_TIME:
engine.handleUpdateTimeMessage();
break;
}
}
}
}
}
This is the code of the Engine/Service that I am extending from:
public abstract class WeatherWatchFaceService extends CanvasWatchFaceService {
public class WeatherWatchFaceEngine extends CanvasWatchFaceService.Engine
implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
DataApi.DataListener, NodeApi.NodeListener {
protected static final int MSG_UPDATE_TIME = 0;
protected long UPDATE_RATE_MS;
protected static final long WEATHER_INFO_TIME_OUT = DateUtils.HOUR_IN_MILLIS * 6;
protected final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Time zone changed
mWeatherInfoReceivedTime = 0;
mTime.clear(intent.getStringExtra("time-zone"));
mTime.setToNow();
}
};
/**
* Handler to update the time periodically in interactive mode.
*/
protected final Handler mUpdateTimeHandler = new Handler() {
#Override
public void handleMessage(Message message) {
switch (message.what) {
case MSG_UPDATE_TIME:
invalidate();
if (shouldUpdateTimerBeRunning()) {
long timeMs = System.currentTimeMillis();
long delayMs = UPDATE_RATE_MS - (timeMs % UPDATE_RATE_MS);
mUpdateTimeHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIME, delayMs);
requireWeatherInfo();
}
break;
}
}
};
protected int mTheme = 3;
protected int mTimeUnit = ConverterUtil.TIME_UNIT_12;
protected AssetManager mAsserts;
protected Bitmap mWeatherConditionDrawable;
protected GoogleApiClient mGoogleApiClient;
protected Paint mBackgroundPaint;
protected Paint mDatePaint;
protected Paint mDateSuffixPaint;
protected Paint mDebugInfoPaint;
protected Paint mTemperatureBorderPaint;
protected Paint mTemperaturePaint;
protected Paint mTemperatureSuffixPaint;
protected Paint mTimePaint;
protected Resources mResources;
protected String mWeatherCondition;
protected String mWeatherConditionResourceName;
protected Time mSunriseTime;
protected Time mSunsetTime;
protected Time mTime;
protected boolean isRound;
protected boolean mLowBitAmbient;
protected boolean mRegisteredService = false;
protected int mBackgroundColor;
protected int mBackgroundDefaultColor;
protected int mRequireInterval;
protected int mTemperature = Integer.MAX_VALUE;
protected int mTemperatureScale;
protected long mWeatherInfoReceivedTime;
protected long mWeatherInfoRequiredTime;
private String mName;
public WeatherWatchFaceEngine(String name) {
mName = name;
mGoogleApiClient = new GoogleApiClient.Builder(WeatherWatchFaceService.this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Wearable.API)
.build();
}
#Override
public void onConnected(Bundle bundle) {
log("Connected: " + bundle);
getConfig();
Wearable.NodeApi.addListener(mGoogleApiClient, this);
Wearable.DataApi.addListener(mGoogleApiClient, this);
requireWeatherInfo();
}
#Override
public void onConnectionSuspended(int i) {
log("ConnectionSuspended: " + i);
}
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
for (int i = 0; i < dataEvents.getCount(); i++) {
DataEvent event = dataEvents.get(i);
DataMap dataMap = DataMap.fromByteArray(event.getDataItem().getData());
log("onDataChanged: " + dataMap);
fetchConfig(dataMap);
}
}
#Override
public void onPeerConnected(Node node) {
log("PeerConnected: " + node);
requireWeatherInfo();
}
#Override
public void onPeerDisconnected(Node node) {
log("PeerDisconnected: " + node);
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
log("ConnectionFailed: " + connectionResult);
}
#Override
public void onCreate(SurfaceHolder holder) {
super.onCreate(holder);
setWatchFaceStyle(new WatchFaceStyle.Builder(WeatherWatchFaceService.this)
.setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT)
.setAmbientPeekMode(WatchFaceStyle.AMBIENT_PEEK_MODE_HIDDEN)
.setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
.setShowSystemUiTime(false)
.build());
mResources = WeatherWatchFaceService.this.getResources();
mAsserts = WeatherWatchFaceService.this.getAssets();
mDebugInfoPaint = new Paint();
mDebugInfoPaint.setColor(Color.parseColor("White"));
mDebugInfoPaint.setTextSize(20);
mDebugInfoPaint.setAntiAlias(true);
mTime = new Time();
mSunriseTime = new Time();
mSunsetTime = new Time();
mRequireInterval = mResources.getInteger(R.integer.weather_default_require_interval);
mWeatherInfoRequiredTime = System.currentTimeMillis() - (DateUtils.SECOND_IN_MILLIS * 58);
mGoogleApiClient.connect();
}
#Override
public void onDestroy() {
log("Destroy");
mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME);
super.onDestroy();
}
#Override
public void onInterruptionFilterChanged(int interruptionFilter) {
super.onInterruptionFilterChanged(interruptionFilter);
log("onInterruptionFilterChanged: " + interruptionFilter);
}
#Override
public void onPropertiesChanged(Bundle properties) {
super.onPropertiesChanged(properties);
mLowBitAmbient = properties.getBoolean(WatchFaceService.PROPERTY_LOW_BIT_AMBIENT, false);
log("onPropertiesChanged: LowBitAmbient=" + mLowBitAmbient);
}
#Override
public void onTimeTick() {
super.onTimeTick();
log("TimeTick");
invalidate();
requireWeatherInfo();
}
#Override
public void onVisibilityChanged(boolean visible) {
super.onVisibilityChanged(visible);
log("onVisibilityChanged: " + visible);
if (visible) {
mGoogleApiClient.connect();
registerTimeZoneService();
// Update time zone in case it changed while we weren't visible.
mTime.clear(TimeZone.getDefault().getID());
mTime.setToNow();
} else {
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
Wearable.DataApi.removeListener(mGoogleApiClient, this);
Wearable.NodeApi.removeListener(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
unregisterTimeZoneService();
}
// Whether the timer should be running depends on whether we're visible (as well as
// whether we're in ambient mode), so we may need to start or stop the timer.
updateTimer();
}
protected Paint createTextPaint(int color, Typeface typeface) {
Paint paint = new Paint();
paint.setColor(color);
if (typeface != null)
paint.setTypeface(typeface);
paint.setAntiAlias(true);
return paint;
}
protected boolean shouldUpdateTimerBeRunning() {
return isVisible() && !isInAmbientMode();
}
protected void fetchConfig(DataMap config) {
if (config.containsKey(Consts.KEY_WEATHER_UPDATE_TIME)) {
mWeatherInfoReceivedTime = config.getLong(Consts.KEY_WEATHER_UPDATE_TIME);
}
if (config.containsKey(Consts.KEY_WEATHER_CONDITION)) {
String cond = config.getString(Consts.KEY_WEATHER_CONDITION);
if (TextUtils.isEmpty(cond)) {
mWeatherCondition = null;
} else {
mWeatherCondition = cond;
}
}
if (config.containsKey(Consts.KEY_WEATHER_TEMPERATURE)) {
mTemperature = config.getInt(Consts.KEY_WEATHER_TEMPERATURE);
if (mTemperatureScale != ConverterUtil.FAHRENHEIT) {
mTemperature = ConverterUtil.convertFahrenheitToCelsius(mTemperature);
}
}
if (config.containsKey(Consts.KEY_WEATHER_SUNRISE)) {
mSunriseTime.set(config.getLong(Consts.KEY_WEATHER_SUNRISE) * 1000);
log("SunriseTime: " + mSunriseTime);
}
if (config.containsKey(Consts.KEY_WEATHER_SUNSET)) {
mSunsetTime.set(config.getLong(Consts.KEY_WEATHER_SUNSET) * 1000);
log("SunsetTime: " + mSunsetTime);
}
if (config.containsKey(Consts.KEY_CONFIG_TEMPERATURE_SCALE)) {
int scale = config.getInt(Consts.KEY_CONFIG_TEMPERATURE_SCALE);
if (scale != mTemperatureScale) {
if (scale == ConverterUtil.FAHRENHEIT) {
mTemperature = ConverterUtil.convertCelsiusToFahrenheit(mTemperature);
} else {
mTemperature = ConverterUtil.convertFahrenheitToCelsius(mTemperature);
}
}
mTemperatureScale = scale;
}
if (config.containsKey(Consts.KEY_CONFIG_THEME)) {
mTheme = config.getInt(Consts.KEY_CONFIG_THEME);
}
if (config.containsKey(Consts.KEY_CONFIG_TIME_UNIT)) {
mTimeUnit = config.getInt(Consts.KEY_CONFIG_TIME_UNIT);
}
if (config.containsKey(Consts.KEY_CONFIG_REQUIRE_INTERVAL)) {
mRequireInterval = config.getInt(Consts.KEY_CONFIG_REQUIRE_INTERVAL);
}
invalidate();
}
protected void getConfig() {
log("Start getting Config");
Wearable.NodeApi.getLocalNode(mGoogleApiClient).setResultCallback(new ResultCallback<NodeApi.GetLocalNodeResult>() {
#Override
public void onResult(NodeApi.GetLocalNodeResult getLocalNodeResult) {
Uri uri = new Uri.Builder()
.scheme("wear")
.path(Consts.PATH_CONFIG + mName)
.authority(getLocalNodeResult.getNode().getId())
.build();
getConfig(uri);
uri = new Uri.Builder()
.scheme("wear")
.path(Consts.PATH_WEATHER_INFO)
.authority(getLocalNodeResult.getNode().getId())
.build();
getConfig(uri);
}
});
}
protected void getConfig(Uri uri) {
Wearable.DataApi.getDataItem(mGoogleApiClient, uri)
.setResultCallback(
new ResultCallback<DataApi.DataItemResult>() {
#Override
public void onResult(DataApi.DataItemResult dataItemResult) {
log("Finish Config: " + dataItemResult.getStatus());
if (dataItemResult.getStatus().isSuccess() && dataItemResult.getDataItem() != null) {
fetchConfig(DataMapItem.fromDataItem(dataItemResult.getDataItem()).getDataMap());
}
}
}
);
}
protected void log(String message) {
Log.d(WeatherWatchFaceService.this.getClass().getSimpleName(), message);
}
protected void registerTimeZoneService() {
//TimeZone
if (mRegisteredService) {
return;
}
mRegisteredService = true;
// TimeZone
IntentFilter filter = new IntentFilter(Intent.ACTION_TIMEZONE_CHANGED);
WeatherWatchFaceService.this.registerReceiver(mTimeZoneReceiver, filter);
}
protected void requireWeatherInfo() {
if (!mGoogleApiClient.isConnected())
return;
long timeMs = System.currentTimeMillis();
// The weather info is still up to date.
if ((timeMs - mWeatherInfoReceivedTime) <= mRequireInterval)
return;
// Try once in a min.
if ((timeMs - mWeatherInfoRequiredTime) <= DateUtils.MINUTE_IN_MILLIS)
return;
mWeatherInfoRequiredTime = timeMs;
Wearable.MessageApi.sendMessage(mGoogleApiClient, "", Consts.PATH_WEATHER_REQUIRE, null)
.setResultCallback(new ResultCallback<MessageApi.SendMessageResult>() {
#Override
public void onResult(MessageApi.SendMessageResult sendMessageResult) {
log("SendRequireMessage:" + sendMessageResult.getStatus());
}
});
}
protected void unregisterTimeZoneService() {
if (!mRegisteredService) {
return;
}
mRegisteredService = false;
//TimeZone
WeatherWatchFaceService.this.unregisterReceiver(mTimeZoneReceiver);
}
protected void updateTimer() {
mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME);
if (shouldUpdateTimerBeRunning()) {
mUpdateTimeHandler.sendEmptyMessage(MSG_UPDATE_TIME);
}
}
}
}
Any help would be GREATLY appreciated :) (This is also my first real time making a watch face, so please forgive me)
A default constructor accepts zero arguments. You have only a one-argument constructor in WeatherWatchFaceEngine.
Add a zero-argument constructor to WeatherWatchFaceEngine, whose signiture will be public WeatherWatchFaceEngine(){...}
I am trying to create an image viewer which can load images from given URLs.The code below implement the User Interface.
My intention is to let user Zoom the image and move to next image with a Swipe event.But the problem is that when i zoom and then swipe , instead of showing the remaining portion , it moves to the next image.
I tried using requestDisallowInterceptTouchEvent in TouchImageView's(https://github.com/MikeOrtiz/TouchImageView) onTouchListener .After this the remaining portion could show but now i cannot go to the next page. I was wondering how this can be achieved as the event can only go to either TouchView or PageAdapter
public class PageActivity extends Activity {
private int numPages = 33;
private TouchImageView[] imageViews = new TouchImageView[numPages];
private String URL = "http://www.smbc-comics.com/comics/200905";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewPager viewPager = new ViewPager(this);
for (int i = 0; i < numPages; i++) {
imageViews[i] = new TouchImageView(this);
imageViews[i].setBackgroundResource(R.drawable.banke);
imageViews[i].setMaxZoom(4f);
}
setContentView(viewPager);
ImagePagerAdapter adapter = new ImagePagerAdapter();
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(2);
}
#SuppressWarnings("unused")
private class ImagePagerAdapter extends PagerAdapter {
#Override
public int getCount() {
return numPages;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((TouchImageView) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Context context = PageActivity.this;
String pageURL = URL;
if (imageViews[position].getDrawable() == null) {
ImageFetcher imagefetcher = new ImageFetcher();
imagefetcher.execute(
pageURL + String.format("%02d", position+1) + ".gif",
String.valueOf(position));
}
((ViewPager) container).addView(imageViews[position], 0);
return imageViews[position];
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((TouchImageView) object);
imageViews[position].setImageDrawable(null);
}
}
public class ImageFetcher extends AsyncTask<String, Integer, Drawable> {
int fillthisPos;
public Drawable doInBackground(String... urls) {
try {
InputStream is = (InputStream) new URL(urls[0]).getContent();
fillthisPos = Integer.parseInt(urls[1]);
Drawable d = Drawable.createFromStream(is, "src name");
return d;
} catch (Exception e) {
return null;
}
}
#Override
protected void onPostExecute(Drawable result) {
super.onPostExecute(result);
imageViews[fillthisPos].setImageDrawable(result);
result = null;
}
}
}
You can add following code in TouchImageView class:
public boolean isZoomed () {
return (normalizedScale > minScale);
}
private void onSwipeEvent(MotionEvent event) {
boolean zoomed = this.isZoomed();
if (!zoomed && (swipeLen > 0)) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
swipeStartPos = (int) event.getRawX();
}
else if (event.getAction() == MotionEvent.ACTION_MOVE) {
int distance = ((int) event.getRawX()) - swipeStartPos;
int swipeVector = SWIPE_RIGHT;
if (distance < 0) swipeVector = SWIPE_LEFT;
if (Math.abs(distance) > swipeLen) {
onSwipeHandler.onSwipe(swipeVector);
swipeStartPos = (int) event.getRawX();
this.setScaleX(1f);
}
else {
int swipeStDist = swipeLen - Math.round(((swipeLen / 100) * 50));
if (Math.abs(distance) > swipeStDist) {
this.setScaleX(0.98f);
}
}
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
swipeStartPos = (int) event.getRawX();
this.setScaleX(1f);
}
}
}
public static int SWIPE_LEFT = 0;
public static int SWIPE_RIGHT = 1;
public int swipeStartPos = 0;
public onSwipeListener onSwipeHandler = new onSwipeListener() {
public void onSwipe(int vector) {}
};
public static int swipeLen = 0;
public void setOnSwipeListener(onSwipeListener c, int swipeLength) {
onSwipeHandler = c;
swipeLen = swipeLength;
}
public interface onSwipeListener {
public void onSwipe(int vector);
}
And also in TouchImageView below line 636 add onSwipeEvent(event) like this:
......
setImageMatrix(matrix);
onSwipeEvent(event);
//
// indicate event was handled
//
return true;
...........
After this from you code you can add swipe event listener, like this:
imageView.setOnSwipeListener(new TouchImageView.onSwipeListener() {
#Override
public void onSwipe(int vector) {
if (vector == TouchImageView.SWIPE_LEFT) {
Log.d("swipe", "swipe left!");
}
else if (vector == TouchImageView.SWIPE_RIGHT) {
Log.d("swipe", "swipe right!");
}
}
}, 200); //length of swiping - 200 dip
This onSwipeListener ignore onswipe where image is zoomed+. It work for me.
I'm having trouble in adding a little animation in onfling method. Everything is working just fine. Flipping pages left to right and right to left is done but there's no animation. I tried various things but couldn't get the animation working. Please guide me how can I add flipper animation or swipe animation. Here is the code:
public class MainActivity extends CustomTitlebarActivityBase {
// some random variables..
// detect swipe left/right
private GestureDetector gestureDetector;
private MyGestureListener gestureListener;
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "Creating MainActivity");
super.onCreate(savedInstanceState, true);
setContentView(R.layout.main_view);
// create related objects
gestureListener = new MyGestureListener(MainActivity.this);
gestureDetector = new GestureDetector( gestureListener );
documentViewManager = new DocumentViewManager(this);
documentViewManager.buildView();
myContentManager = new myContentManager(documentViewManager);
// force the screen to be populated
myContentManager.updateText(true);
}
// there are some other methods
/** user swiped left */
public void next() {
if (getDocumentViewManager().getDocumentView().isPageNextOkay()) {
CurrentPageManager.getInstance().getCurrentPage().next();
}
}
/** user swiped left */
public void previous() {
if (getDocumentViewManager().getDocumentView().isPagePreviousOkay()) {
CurrentPageManager.getInstance().getCurrentPage().previous();
}
}
}
// here is the listener class
public class MyGestureListener extends SimpleOnGestureListener {
// measurements in dips for density independence
private static final int DISTANCE_DIP = 40;
private int scaledDistance;
private int minScaledVelocity;
private MainActivity mainActivity;
private boolean sensePageDownTap;
private static final String TAG = "MyGestureListener";
public MyGestureListener(MainActivity mainActivity) {
super();
this.mainActivity = mainActivity;
scaledDistance = CommonUtils.convertDipsToPx(DISTANCE_DIP);
minScaledVelocity = ViewConfiguration.get(mainActivity).getScaledMinimumFlingVelocity();
// make it easier to swipe
minScaledVelocity = (int)(minScaledVelocity*0.66);
}
#Override
public void onLongPress(MotionEvent e) {
// do something
}
// here is the onFling
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// get distance between points of the fling
double vertical = Math.abs( e1.getY() - e2.getY() );
double horizontal = Math.abs( e1.getX() - e2.getX() );
Log.d(TAG, "onFling vertical:"+vertical+" horizontal:"+horizontal+" VelocityX"+velocityX);
if ( vertical > scaledDistance ) {
return false;
}
// test horizontal distance and velocity
else if ( horizontal > scaledDistance && Math.abs(velocityX) > minScaledVelocity ) {
if (e1.getX() > e2.getX()) {
mainActivity.next();
}
// left to right swipe
else {
mainActivity.previous();
}
return true;
}
return false;
}
}
Try to implement OnGestureListener. Sample code is beloe
public class MyActivity extends Activity implements GestureDetector.OnGestureListener {
private GestureDetector gestureScanner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.yourlayout);
this.gestureScanner = new GestureDetector(this);
}
#Override
public boolean dispatchTouchEvent(MotionEvent paramMotionEvent) {
super.dispatchTouchEvent(paramMotionEvent);
return this.gestureScanner.onTouchEvent(paramMotionEvent);
}
public boolean onDown(MotionEvent paramMotionEvent) {
return false;
}
public boolean onFling(MotionEvent paramMotionEvent1, MotionEvent paramMotionEvent2, float paramFloat1,
float paramFloat2) {
// your fling code goes here
return true;
}
public void onLongPress(MotionEvent paramMotionEvent) {
}
public boolean onScroll(MotionEvent paramMotionEvent1, MotionEvent paramMotionEvent2, float paramFloat1,
float paramFloat2) {
return false;
}
public void onShowPress(MotionEvent paramMotionEvent) {
}
public boolean onSingleTapUp(MotionEvent paramMotionEvent) {
return false;
}
}
I have created a class that extends the Overlay class in Osmdroid (CustomOverlay.java). However, nothing appear on the map after I call the method createMark() on the main activity which make use of CustomOverlay.java. I do not want to use ItemizedOverlay class.
Any idea?
CustomOverlay.java (class that extends Overlay)
public CustomOverlay(Context context) {
super(context);
}
#Override
protected void draw(Canvas canvas, MapView mapView, boolean shadow) {
Point screenPoint = new Point();
mapView.getProjection().toPixels(geoPoint, screenPoint);
super.drawAt(canvas, mapView.getResources().getDrawable(R.drawable.marker), screenPoint.x, screenPoint.y, shadow);
}
}
This is the method I call in the main activity:
private void createMarker() {
List<Overlay> mapOverlays = mMapView.getOverlays();
Overlay c = new CustomOverlay(this);
mapOverlays.add(c);
mMapView.invalidate();
}
Answer:
#Override
protected void draw(Canvas canvas, MapView mapView, boolean shadow) {
Point screenPoint = new Point();
mapView.getProjection().toPixels(geoPoint, screenPoint);
Bitmap marker= BitmapFactory.decodeResource(mapView.getResources(), R.drawable.marker);
canvas.drawBitmap(marker, screenPoint.x, screenPoint.y, null);
}
Here's the skeleton of a customized overlay:
public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
public MyItemizedOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
}
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
#Override
public int size() {
return mOverlays.size();
}
public void removeAllOverlay() {
mOverlays.clear();
}
public void addOverlay(OverlayItem overlay) {
mOverlays.add(overlay);
populate();
}
}
See the differences? Where is your populate() call?
Hope this helps.