Im creating an OpenStreetMaps application using OSMDroid lib. I need LongPress gesture to add markers into an OverlayItem array to show them all, but i can't access to LongPress anyway.
I have tried with GestureListener, overridden the onTouch event, using GestureDetector(which is deprecated nowadays) and I can't find a solution for this problem.
The only way i have get the gesture is through setOnLongClickListener, but I have to choose between having longpress or panning the map, and I'm greedy and I want both :p
Have anyone any ideas?
Regards!
I have encounter a solution through OSMBonusPack library.
The object MapsEventsReceiver grants you a simple way to handle map's gestures.
You have to override singleTapUpHelper and longPressHelper methods and create a new overlay with this handler.
Here's the code:
MapEventsReceiver mReceive = new MapEventsReceiver() {
#Override
public boolean singleTapUpHelper(IGeoPoint arg0) {
Log.d("debug", "Single tap helper");
//your onSingleTap logic here
return false;
}
#Override
public boolean longPressHelper(IGeoPoint arg0) {
Log.d("debug", "LongPressHelper");
//your onLongPress logic here
setMarker(arg0);
return false;
}
};
//Creating a handle overlay to capture the gestures
MapEventsOverlay OverlayEventos = new MapEventsOverlay(getBaseContext(), mReceive);
map.getOverlays().add(OverlayEventos);
//Refreshing the map to draw the new overlay
map.invalidate();
//I use this method to set the marker on touchPoint
protected void setMarker(IGeoPoint arg0) {
touchPoint = (GeoPoint) arg0;
targetPoint = touchPoint;
path.addPoint(targetPoint);
//Listener to handle item's(markers) events
myOnItemGestureListener = new OnItemGestureListener<OverlayItem>() {
#Override
public boolean onItemLongPress(int arg0, OverlayItem arg1) {
Log.d("debug", "Testing long tap on item");
//your item onLongPress logic here
return false;
}
#Override
public boolean onItemSingleTapUp(int index, OverlayItem item) {
Log.d("debug", "Testing single tap on item");
//your item onSingleTap logic here
return true;
}
};
itemarray.add(new OverlayItem("Marker " + cnt, "Info about marker " + cnt, touchPoint));
ItemizedOverlayWithFocus<OverlayItem> overlayDeItems = new ItemizedOverlayWithFocus<OverlayItem>(getBaseContext(), itemarray, myOnItemGestureListener);
map.getOverlays().add(overlayDeItems);
overlayDeItems.setFocusItemsOnTap(true);
map.invalidate();
itemarray = new ArrayList<OverlayItem>();
cnt++;
}
private void setupGestureListener() {
GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {
#Override
public void onLongPress(MotionEvent e) {
//do something
}
};
final GestureDetector gestureDetector = new GestureDetector(getContext(), gestureListener);
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return gestureDetector.onTouchEvent(motionEvent);
}
});
}
Related
I am creating a video player in android studio. I want to hide buttons, layout and media controller after 5 seconds and I am using gestures for different properties but the issue is that when I apply 2 to 3 gestures in a certain time, after 5 seconds the buttons and media controller start blinking. I use this code for stying on screen
centerlayout.setOnTouchListener(new LinearLayout.OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent m) {
if (gestureDetectorc.onTouchEvent(m)) {
if(m.getAction()==MotionEvent.ACTION_UP){
handler.postDelayed(new Runnable() {
#Override
public void run() {
hide();
}
},5000);
}
}
return true;
}
});
Declare the runnable in global
Runnable mRunnable = new Runnable() {
#Override
public void run() {
hide();
}
};
call removeCallbacks before you call postDelay
centerlayout.setOnTouchListener(new LinearLayout.OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent m) {
if (gestureDetectorc.onTouchEvent(m)) {
if(m.getAction()==MotionEvent.ACTION_UP){
handler.removeCallbacks(mRunnable);//add this
handler.postDelayed(mRunnable, 5000);
}
}
return true;
}
});
I created a Checkbox, however, whenever I click a few Items random checkboxes become clicked. I have a recycler view, and I have an adapter class as well. Here is my CheckBox method can anyone tell me the problem?
public void CheckBox(View view) {
final CheckBox checkBox = (CheckBox)view;
if (checkBox.isChecked()) {
System.out.println("SET TO CHECKED");
//Input instance of selected course(CHECKED)
// TODO: 2/5/16 Need to pass in Persisted ID
mVolleySingleton = VolleySingleton.getInstance();
mRequestQueue = mVolleySingleton.getRequestQueue();
CharSequence ID_PUT_COURSES = ((TextView) ((RelativeLayout) view.getParent()).getChildAt(1)).getText();
System.out.println(PUT);
String URL_PUT_COURSES = "URL"+ID_PUT+"\n";
System.out.print(PUT);
StringRequest UrlPut = new StringRequest(Request.Method.PUT, URL_PUT, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println(response + "reponse");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
System.out.println("************Answer" + error + "error");
}
});
mRequestQueue.add(UrlPutCourses);
System.out.println("Added");
}
else{
System.out.println("SET TO UNCHECKED");
//delete instance of selected course(UNCHECKED)
mVolleySingleton = VolleySingleton.getInstance();
mRequestQueue = mVolleySingleton.getRequestQueue();
// TODO: 2/5/16 Need to pass in Persisted ID
CharSequence DELETE = ((TextView) ((RelativeLayout) view.getParent()).getChildAt(1)).getText();
System.out.print(ID_PUT_COURSES);
String UR_DELETE = "URL"+ DELETE;
StringRequest UrlDeleteCourses = new StringRequest(Request.Method.DELETE, UR_DELETE, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println(response + "reponse");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
System.out.println("************Answer" + error + "error");
}
});
mRequestQueue.add(UR_DELETE);
System.out.println("Deleted");
}
}
ublic class AdapterSearch extends RecyclerView.Adapter<AdapterSearch.ViewSearch>{
private LayoutInflater mLayoutInflater;
private ArrayList<Search> ListSearch=new ArrayList<>();
public AdapterSearch(Context context){
mLayoutInflater=LayoutInflater.from(context);
}
public void setListSearch(ArrayList<Search> ListSearch){
this.ListSearch=ListSearch;
notifyItemRangeChanged(0,ListSearch.size());
}
#Override
public ViewSearch onCreateViewHolder(ViewGroup parent, int viewType) {
View view= mLayoutInflater.inflate(R.layout.custom_search,(ViewGroup)null);
ViewSearch holder=new ViewSearch(view);
return holder;
}
#Override
public void onBindViewHolder(ViewSearch holder, int position) {
Search currentSearch=ListSearch.get(position);
holder.mSearchText.setText(currentSearch.getMtitle());
holder.mAnswerPointsSearch.setText(currentSearch.getMkey());
holder.mSearchId.setText(currentSearch.getMid());
holder.mCourseId.setText(currentSearch.getCourseId());
}
#Override
public int getItemCount() {
return ListSearch.size();
}
public void setFilter(ArrayList<Search> Search) {
ListSearch = new ArrayList<>();
ListSearch.addAll(Search);
notifyDataSetChanged();
}
static class ViewSearch extends RecyclerView.ViewHolder{
private TextView mSearchText;
private TextView mAnswerPointsSearch;
private TextView mSearchId;
private TextView mCourseId;
public ViewSearch (View view){
super(view);
mSearchText=(TextView)itemView.findViewById(R.id.SearchText);
mAnswerPointsSearch=(TextView)itemView.findViewById(R.id.AnswerPointsSearch);
mSearchId=(TextView)itemView.findViewById(R.id.SearchId);
mCourseId=(TextView)itemView.findViewById(R.id.CourseTextView);
}
}
}
Better late then never I'd say, it might help other people stumbling upon this issue later, so here goes.
This might not be the best solution ever, but it should work.
In your Search class, you have some variables like title and key. Add the boolean isChecked to it, and make it false by default. Also create the matching getter and setter. (I'm using isChecked() & setChecked() in this example)
In your onBindViewHolder() method, add the following lines:
CheckBox checkBox = (CheckBox) itemView.findViewById(R.id.CheckBoxID);
// Instantiating the checkbox
holder.checkBox.setChecked(currentSearch.isChecked());
// Every time the holder (one list item) is shown, this gets called.
// It sets the checked state based on what's stored in currentSearch.
checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (checkBox.isChecked()) {
currentSearch.setChecked(true)
} else {
currentSearch.setChecked(false);
}
});
}
// This listens for clicks on the checkbox, and changes the checked state of
// the boolean in currentSearch to the correct state based on
// what it already was on.
Please be aware that I haven't worked with checkboxes before, so some things (like setting the checked state) might be done slightly differently from what I've described above, but this should be a working base.
You also probably want the checkboxes to only persevere until you click a button or something like that, and then have them reset. You might want to add a simple for loop for that, something like:
public void resetAllCheckBoxes() {
for (Search s : ListSearch) {
s.setChecked(false);
}
}
I am trying to make a Helicopter-like game (as you can probably tell, I'm using "Rocket Man" instead of a helicopter). I'm new to Android programming and to Stack Overflow, so don't pick apart my code too much (please). Anyway, right now I'm just trying to get the rocketman to move up while touch is held down, and move down while touch is released.
It isn't working out very well.
I'm using a Moto XT886 for testing, (in case that's relevent). When I run the application, it starts up and loads the MainActivity perfectly well. When I touch the screen the first time (boolean start == true), the text views are hidden, as they are supposed to. However, on the second, third, fourth and all the rest of the times I touch the screen (Start == false), nothing happens. There are no errors in Log Cat, the code doesn't seem to recognize the touch.
I'm pretty sure that it has something to do with those while loops, but I'm using this application mainly to learn Android Java and I don't know enough (yet) to recognize that I'm doing something wrong. Are you able to put a while loop with the conditions as the MotionEvent of an onTouchListner? Or is it something else?
Either way, I appreciate the help, this is an awesome website (this is the first question I couldn't find already asked on Stack Overflow, and for all I know, mine could've already been answered)!
Here's the code to my MainActivity, if you need the .xml code as well, (though I'm pretty sure that's unnecessary) just say the word.
public class MainActivity extends ActionBarActivity {
boolean Start;
RelativeLayout rLayout;
TextView gameTitle;
TextView clickStart;
TextView highScore;
Handler handler;
ImageView rocketMan;
float Y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initialize();
rLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (Start == true) {
gameTitle.setVisibility(View.GONE);
clickStart.setVisibility(View.GONE);
highScore.setVisibility(View.GONE);
Start = false;
}
if (Start = false) {
while (event.getAction() == MotionEvent.ACTION_DOWN) {
Y = -7;
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(100);
handler.post(new Runnable() {
#Override
public void run() {
HeliMove();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
while (event.getAction() != MotionEvent.ACTION_DOWN) {
Y = 7;
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(100);
handler.post(new Runnable() {
#Override
public void run() {
HeliMove();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
return true;
}
});
}
private void initialize() {
rLayout = (RelativeLayout) findViewById(R.id.mainlayout);
Start = true;
gameTitle = (TextView) findViewById(R.id.rocketmanTitle);
clickStart = (TextView) findViewById(R.id.tapToStart);
highScore = (TextView) findViewById(R.id.highScore);
handler = new Handler();
rocketMan = (ImageView) findViewById(R.id.rocketMan);
}
private void HeliMove() {
rocketMan.setY(rocketMan.getY() + Y);
}
}
Thanks a million!
In my SMS app, I have a dialog that opens when the user clicks on an attached image to expand it.
Everything worked fine until I decided to add animations. This dialog has 3 buttons (one close ImageButton in the top right corner and two buttons in a bottom bar of the dialog). When the user clicks on the image, the buttons anime out/in. This all works fine except the buttons are still clickable even after they're hidden.
Before Animations:
After Animations:
My code for the dialog below:
// Declare these here to increase scope. (Listeners)
private static boolean ContainerChanged;
private static boolean ActionsHidden;
private static boolean AnimStarted;
private static boolean closeAnimFinished;
private static boolean barAnimFinished;
private void showExpandedImageDialog(Uri imgUri)
{
// Initialize Dialog
final Dialog dialog = new Dialog(ActivitySend.this, R.style.FullHeightDialog);
dialog.setContentView(R.layout.dialog_attachment_image_send);
// Initialize Views
final RelativeLayout Container = (RelativeLayout) dialog.findViewById(R.id.Container);
final LinearLayout actions = (LinearLayout) dialog.findViewById(R.id.Actions);
final ImageButton btnClose = (ImageButton) dialog.findViewById(R.id.btnClose);
Button btnReplace = (Button) dialog.findViewById(R.id.btnReplace);
Button btnRemove = (Button) dialog.findViewById(R.id.btnRemove);
ImageView image = (ImageView) dialog.findViewById(R.id.Image);
// Load Image & Make Zoomable
PhotoViewAttacher mAttacher = new PhotoViewAttacher(image);
image.setImageURI(imgUri);
mAttacher.update();
// Get animations ready
final Animation fiCloseAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.fade_in);
fiCloseAnim.setFillEnabled(true);
fiCloseAnim.setFillAfter(true);
final Animation foCloseAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.fade_out);
foCloseAnim.setFillEnabled(true);
foCloseAnim.setFillAfter(true);
final Animation dBarAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.slide_down);
dBarAnim.setFillEnabled(true);
dBarAnim.setFillAfter(true);
final Animation uBarAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.slide_up);
uBarAnim.setFillEnabled(true);
uBarAnim.setFillAfter(true);
// Reset static variables
ActionsHidden = false;
AnimStarted = false;
closeAnimFinished = false;
barAnimFinished = false;
// Initialize listeners
AnimationListener closeAnimListener = new AnimationListener()
{
#Override
public void onAnimationEnd(Animation animation)
{
closeAnimFinished = true;
if (closeAnimFinished && barAnimFinished)
{
AnimStarted = false;
closeAnimFinished = false;
barAnimFinished = false;
if (ActionsHidden)
{
actions.setVisibility(View.VISIBLE);
btnClose.setVisibility(View.VISIBLE);
}
else
{
actions.setVisibility(View.GONE);
btnClose.setVisibility(View.GONE);
}
ActionsHidden = !ActionsHidden;
}
}
#Override
public void onAnimationRepeat(Animation animation)
{
// Nothing
}
#Override
public void onAnimationStart(Animation animation)
{
AnimStarted = true;
}
};
AnimationListener barAnimListener = new AnimationListener()
{
#Override
public void onAnimationEnd(Animation animation)
{
barAnimFinished = true;
if (closeAnimFinished && barAnimFinished)
{
AnimStarted = false;
closeAnimFinished = false;
barAnimFinished = false;
if (ActionsHidden)
{
actions.setVisibility(View.VISIBLE);
btnClose.setVisibility(View.VISIBLE);
}
else
{
actions.setVisibility(View.GONE);
btnClose.setVisibility(View.GONE);
}
ActionsHidden = !ActionsHidden;
}
}
#Override
public void onAnimationRepeat(Animation animation)
{
// Nothing
}
#Override
public void onAnimationStart(Animation animation)
{
AnimStarted = true;
}
};
// Set listeners
fiCloseAnim.setAnimationListener(closeAnimListener);
foCloseAnim.setAnimationListener(closeAnimListener);
dBarAnim.setAnimationListener(barAnimListener);
uBarAnim.setAnimationListener(barAnimListener);
// Actions Appear/Disappear onTap (Animate)
mAttacher.setOnPhotoTapListener(new OnPhotoTapListener()
{
#Override
public void onPhotoTap(View view, float x, float y)
{
if (!AnimStarted && ActionsHidden)
{
actions.startAnimation(uBarAnim);
btnClose.startAnimation(fiCloseAnim);
}
else if (!AnimStarted)
{
actions.startAnimation(dBarAnim);
btnClose.startAnimation(foCloseAnim);
}
}
});
// Make dialog square
ContainerChanged = false;
ViewTreeObserver vto = Container.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
{
public boolean onPreDraw()
{
// Set boolean to save processing power
if (!ContainerChanged)
{
int width = Container.getMeasuredWidth();
Container.getLayoutParams().height = width;
ContainerChanged = true;
}
return true;
}
});
// Set button listeners
btnClose.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
dialog.dismiss();
}
});
btnReplace.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
}
});
btnRemove.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
}
});
// Show dialog
dialog.show();
}
Everything works perfectly if I remove the animations and only use view.setVisibility(View.GONE) but I really like the animations...
Any ideas on what I could do to fix this?
I could probably use view.setClickable(false); but I'm sure there's a better solution than that.
You can do it like this:
Let your activity implement AnimationListener. Then there will be an overridden method public void onAnimationEnd(Animation arg0), write setClickable(false) or setEnabled(false) in this method for all three of your buttons, enable them again when you are starting your animation....hope you got me..
I'm currently creating a custom double tap using the onClickListener with the following code:
newImage.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
counterTap++;
Timer t = new Timer("Double tap counter");
t.schedule(new TimerTask() {
#Override
public void run() {
counterTap = 0;
}
}, 0, 300);
if(counterTap >= 2) {
newImage.setVisibility(FrameLayout.GONE);
counterTap = 0;
}
}
});
The problem I'm facing is as follows:
Whenever I tap the ImageView the event does fire. However, the second time I tap the ImageView, the above code only executes when clicking on the exact same position on the ImageView as before.
Rather use a onTouchListener. In the touch listener in the onTouch method you can return false the first time you tapped which means the event was not handled, the second time you return true and the touch listener will handle the event as finished. See my example below, you can use a similar method
new OnTouchListener() {
boolean doubleTap = false;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
if (!doubleTap) {
doubleTap = true;
return false;
} else {
return true;
}
}
}
};
this might solve your issue.
EDIT : This is a better opotion
private class GestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onDown(MotionEvent e) {
return true;
}
// double tap event
#Override
public boolean onDoubleTap(MotionEvent e) {
return true;
}
}
This question might also help you get to the best answer