How to make the two textviews invisible on the touch in android - android

I have come up with an idea such that on the touch of the two TextViews both become invisible. This idea works when I touch a single finger on the TextView and only one TextView becomes invisible. But when I test it with two finger, only one Textview becomes invisible. It does not make both the textviews invisble.
I have written the following code.
public class MatchMeaning1 extends Activity implements OnTouchListener{
private static final String TAG = MatchMeaning1.class.getSimpleName();
TextView[] txtWord, txtMeaning;
int [] wordID = {R.id.txtWord1, R.id.txtWord2, R.id.txtWord3, R.id.txtWord4, R.id.txtWord5};
int[] meaningID = {R.id.txtMeaning1,R.id.txtMeaning2, R.id.txtMeaning3, R.id.txtMeaning4, R.id.txtMeaning5 };
String[] word = {"1.abidcation","2.abhor","3.abide","4.abyssmal","5.award"};
String[] meaning = {"a.deep","b.stay","c.cede","d.accolade","5.hate"};
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.match_meaning);
txtWord = new TextView[5];
txtMeaning = new TextView[5];
for(int i = 0; i < txtWord.length; i++){
txtWord[i] = (TextView)findViewById(wordID[i]);
txtMeaning[i] = (TextView)findViewById(meaningID[i]);
txtWord[i].setText(word[i]);
txtMeaning[i].setText(meaning[i]);
txtWord[i].setOnTouchListener(this);
txtMeaning[i].setOnTouchListener(this);
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
int pointerCount = event.getPointerCount();
if(pointerCount == 2){
TextView [] tv = new TextView[2];
for(int i = 0; i < tv.length ;i++){
tv[i] = (TextView)v;
tv[i].setVisibility(TextView.INVISIBLE);
}
}
return true;
}
}
The above code doesn't work for pointerCount = 2, but it works for pointerCount = 1.
Can anyone tell me the solution for this?

The onTouch event is processed on a per view basis so it would be firing for both textviews except you're returning true which swallows the event. What you want is probably closer to:
#Override
public boolean onTouch(View v, MotionEvent event) {
if(v != YOUR_TEXT_VIEW1 && v != YOUR_TEXT_VIEW2) return false;
((TextView)v).setVisibility(TextView.INVISIBLE);
return false;
}
Replace YOUR_TEXT_VIEW 1 & 2 with objects you declare as the current two text views you want to disappear.
EDIT:
If you only want the views to disappear if the user is touching both of them you're going to have to devise a more involved approach. I see two possibilities:
The onTouch event needs to call another function which appends all views triggered by each unique MotionEvent. After appending the view to the list the function checks to see if both expected views are present. If so, trigger the invisibility calls.
Instead of using onTouch use the onTouchEvent method and determine if the getX(index) getY(index) coordinates fall inside the two views you are expecting to be touched.

Your phone does not support multitouchEvent.That's why if you are touching two text view at a time, its taking only one event at a time and one textviewbecame invisible.
so first check whether your phone support more then one touch at time.

Related

Which listener should I use for the letters in a wordsearch android application?

....
case 5:
sizeperbutton = sizeOfLayout/5;
for( i = 0; i<25; i++) {
buttons[i] = new Button(this)
ll.addView(buttons[i]);
ViewGroup.LayoutParams mParams = buttons[i].getLayoutParams();
mParams.height = sizeperbutton;
mParams.width = sizeperbutton;
int j = (int)(Math.random()*26);
buttons[i].setText(letterEN[j]);
buttons[i].setTag(i);
buttons[i].setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
Object tag = view.getTag();
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
/* Set the background drawable only for the button I've clicked, and get its text and append it to a textView*/
}
if(motionEvent.getAction() == MotionEvent.ACTION_MOVE){
/* Set the background drawable all the buttons I dragged through my finger and append their letters to the same textView*/
}
if(motionEvent.getAction() == MotionEvent.ACTION_UP){
/*Release touching, check if the text which is stacked to the textView is contained by a list.*/
}
return false;
}
});
}
It creates an area with 5 buttons horizontally and vertically in my gameactivity.
All of them get a random letter and get the touch listener which is I think not adequate for clicking more objects simultaneously, it only works for just one button. I'd appreciate any sources or codes. I'd taken a long-long research but finally I had to ask for information. Here is what I want to attain: https://www.youtube.com/watch?v=NRIvZioTdMc.

List View Item Scroll able vertical

Currently I'm using ListView and it's working fine. But I have text in a ListView that is like a paragraph and I just want to show those 2 lines of text and make the rest of the text scrollable, but I'm having an issue that if I make the TextView scrollable inside of the ListView, then the TextView get the focus of its parent (ListView) and won't let it be scrolled.
So can I achieve this scrollable TextView functionality that won't disturb the scrolling property of the ListView?
Thank you.
I was able to do this in the following way:
Into the getView method of the ListAdapter obtain the TextView object of the line, and write
textView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
v.getParent().getParent().requestDisallowInterceptTouchEvent(true);
return false ;
}
});
when you will touch the TextView, take control of the scrolling
What you are trying to achieve really is impossible. How can the OS know that you are trying to scroll the list vs the list row paragraph? You would essentially need to scroll to the bottom of the list row paragraph before the actual list itself could scroll. This is confusing to the user, and not common UX.
I would suggest you look into ExpandableListView. It allows you to have collapsed versions of each row, in your case just 2 lines of text for each list row. When the user taps on the row, it could expand to the full paragraph form, and the list would be scrollable the whole time. There are plenty of tutorials you should be able to find online.
Nothing is Impossible yet way to do things are may b difficult. Directly this thing can`t be achieved but indirectly yes it can be achieved, and yes i achieved.
how did i achieve is a bit complex but yes will share that how did i achieve.
In a ListView when i click on Textview i block the Touch mode of the listView so that their toch method don't intercept each other, and that can be done by using requestDisallowInterceptTouchEvent(true);
this block the TouchListener of the parent (ListView).
Now when click on TextView i allow its touch listener and also setMovementMethod()
but for Movement i made a custom class and Class is Following
public class myScrollMethod extends ScrollingMovementMethod {
#Override
public void onTakeFocus(TextView widget, Spannable text, int dir) {
// TODO Auto-generated method stub
super.onTakeFocus(widget, text, dir);
}
#Override
public boolean onKeyDown(TextView widget, Spannable buffer,
int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_DOWN:
for (int i = 0, scrollAmount = getScrollAmount(widget); i < scrollAmount; i++) {
down(widget, buffer);
}
return true;
case KeyEvent.KEYCODE_DPAD_UP:
for (int i = 0, scrollAmount = getScrollAmount(widget); i < scrollAmount; i++) {
up(widget, buffer);
}
return true;
default:
return super.onKeyDown(widget, buffer, keyCode, event);
}
}
private int getScrollAmount(TextView widget) {
final int visibleLineCount = (int) ((1f * widget.getHeight()) / widget
.getLineHeight());
int scrollAmount = visibleLineCount - 1;
if (scrollAmount < 1) {
scrollAmount = 1;
}
return scrollAmount;
}
}
After that when i click on parent i enable the TouchIntercepter of the parent set true and that get hold on its parent and start scrolling.
By this way i have successfully achieved this requirement

Simultaneous GridView button events/determining which button has been touched

I'm having a hard time trying to figure this out. I have a gridview of 8 buttons. At the moment I'm using an onItemClickListener to trigger the buttons actions, however this produces two problems for me.
1) The buttons action happens after the button has been unpressed.
2) Two buttons cannot the pressed at the same time, you must release the first button.
As I have learnt, an onTouchListener should resolve my first issue, though I'm not sure how to determine which button has been pressed. My code for the onItemClickListener is as follows
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(Activity.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
Now with the above, I know exactly which button has been pushed. I believe the code for implementing as an onTouchListener is as follows
gridview.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return false;
}
}) {
How am I supposed to determine which button has been pressed using MotionEvent? Before I was getting passed 'position' and it made this fairly easy. I also need to account for if two or more buttons have been pushed simultaneously/without letting another one go.
Does anyone know how to achieve this?
Having hit this very issue recently and coming across this post in my quest for help, I wanted to add two things from what I did which seem to have worked:
1) I added the onTouchListener to the object in the adapter rather than the activity or gridview.
2) In the OnTouchListener, I looked for MotionEvent.ACTION_DOWN (first finger touch) and MotionEvent.ACTION_POINTER_DOWN (subsequent finger touches), this way I can get multitouches and process them immediately without waiting for the user to lift their finger(s).
Note that I called it ImageAdapter, even though I've added a TextView to each as that way I can use the TextView background for the image, but add invisible text to the TextView so it works with Talkback):
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return numCols * numRows;
}
public Object getItem(int position) {
return this;
}
public long getItemId(int position) {
return position;
}
// create a new TextView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView;
if (convertView == null) { // if it's not recycled, initialize some attributes
textView = new TextView(mContext);
} else {
textView = (TextView) convertView;
}
// place any other initial setup needed for the TextView here
// here's our onTouchListener
textView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
boolean returnValue;
int thePosition = v.getId();
// MotionEvent.ACTION_DOWN gets the first touch
// MotionEvent.ACTION_POINTER_DOWN gets any subsequent touches (if you place a second finger on the screen)
// Between these I can get touches as soon as they happen, including multitouch support, without needing to wait until the user lifts their finger.
if ((event.getAction() == MotionEvent.ACTION_DOWN) || (event.getAction() == MotionEvent.ACTION_POINTER_DOWN)) {
TextView textView;
if (v == null) { // if it's not recycled, initialize some attributes
textView = new TextView(mContext);
} else {
textView = (TextView) v;
}
// Do any processing based on the touch - I call a function and pass the position (number of cell, 1..n) and textview so can make changes to it as needed
ScreenTapped(thePosition, textView);
// I used a returnValue
returnValue = true;
} else returnValue = false;
return returnValue;
});
return textView;
} // getView
} //imageadapter
I am infact trying to figure the same thing out. I got as far as figuring out which gridcell has been clicked using the following code
public boolean onTouch(View v, MotionEvent me) {
float currentXPosition = me.getX();
float currentYPosition = me.getY();
int position = gridView.pointToPosition((int) currentXPosition, (int) currentYPosition);
Position gives you the number on the gridView, and you can supposedly retrieve that particular item as following
gridView.getItemAtPosition(position)
But that is where I am stuck. My gridView has Textview items in it, and I am having trouble converting the item to a textview and then performing operations on it.
Hope this helps!
When using gridView the philosophy is:
the grid view implements the onTouchLister
when touch happens onTouchLister gathers the coordinates (a lot :) )
for all ACTION_MOVE events
when the touch event is MOVE_UP, calculate the real positions under
the coordinates and return the item in the grid
So the solution would be:
In your activity where you have findViewById(some_grid_view)
//Register handler for the onTouch event of gridView in your activity
gridView.setOnTouchListener(new MyActivityOnTouchListener(this));
NOTE: my onTouch listener is implemented in another class (MyActivityOnTouchListener) instead of inside the activity
...then in the MyActivityOnTouchListener class you implement the onTouch method:
public class CalendarActivityOnTouchListener implements View.OnTouchListener {
private MyActivity myActivityContext;
private GridView mGridView;
private HashSet<Point> movementCoordinates = new HashSet<Point>;
//Constructor
public MyActivityOnTouchListener (MyActivity context){
this.myActivityContext= context;
mGridView= myActivityContext.getGridView(); //assign touched gridView into a local variable
}
#Override
public boolean onTouch(View v, MotionEvent event) {
/*
* NOTE:
* ACTION_MOVE fires events until you release it
* ACTION_UP once you release it fires it
*/
//while touching the grid a bunch of ACTION_MOVE events are dispatched
if (event.getAction() == MotionEvent.ACTION_MOVE) {
//gather all coordinates touched (in a set to avoid duplicates)
movementCoordinates.add(new Point((int)event.getX(), (int)event.getY()));
return true;
}
//Finally the finger is lifted
if (event.getAction() == MotionEvent.ACTION_UP) {
//convert all movementCoordinates gathered in the previous block into real grid positions
int position;
for(Point p : movementCoordinates){
Log.d("Luka", p.x +" / "+p.y);
position = calendarGridView.pointToPosition(p.x, p.y);
//...Do whatever with the position
}
}
}
}
Be careful about the pointToPosition() method because in some cases it can return -1 instead of the position behind the coordinates. For example, if you have a margin between items in the grid those coordinates cannot return a position, hence the -1
hope it helps...

Is it possible to pass an onTouchEvent to multiple views in Android?

I have read a few questions regarding this topic on SO but haven't really found a solid answer to it.
I have a framelayout that I stack multiple custom views on, however the onTouch event only works with the top view. (the custom views are all the same view with the same onTouch event, just multiple of them)
FrameLayout
customView[2] <--- this is the last view added and the only one that receives the event
customView[1]
customView[0]
I'm testing it on Android 2.2 and am wondering if there is any way for the other views below to know where the touch happened?
EDIT (Adding some code)
I'm adding some code to hopefully help explain where I'm running into issues. At first I just automatically had the onTouchEvent return true. This made it so that the last view (in my case customerView[2]) would be the only one generating a value.
However, once I added the method to set the onTouchEvent to return true or false, now the only view returning a generated value is customView[0].
I hope this clears up what I am asking. I'm rather new to this and I appreciate you taking the time to explain it (and of course I appreciate your patience).
Also, I realize that my TextView's don't update with the value on each touchEvent, I'm working on fixing that.
My Activity:
public class MyActivity extend Activity {
CustomView[] customView;
TextView[] textView;
int numViews 3;
//FrameLayout and Params created
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
for(int i = 0; i < numViews; i++) {
customView[i] = new CustomView(this, i);
//Allows the onTouch to be handled by all Views - View[0] is the bottom view
if(i == 0) {
customView[i].setTouchBool(true); //set view's onTouch to return true
} else {
customView[i].setTouchBool(false); //set view's onTouch to return false
}
//Set TextView to display the number generated by the CustomView
textView[i].setText(Double.toString(customView[i].getGeneratedNumber()));
//Add views to main layout
frame.addView(textView[i]);
frame.addView(customView[i]);
}
}
}
My View:
public class CustomView extends View {
boolean onTouchHandler = true;
int xVal = 0, yVal = 0;
int index;
double generatedNum = 0;
public CustomView(Context context) {
this(context, 0);
this.index = 0;
}
public CustomView(Context context, int index) {
super(context);
this.index = index;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch(action) {
case MotionEvent.ACTION_DOWN: {
//do logic
}
case MotionEvent.ACTION_MOVE: {
//do logic
}
case MotionEvent.ACTION_UP: {
xVal = (int) ev.getX();
yVal = (int) ev.getY();
generateNumber(xVal, yVal, index);
break;
}
}
return onTouchHandler;
}
private void generateNumber(int x, int y, int index) {
if(index == 0) {
generatedNum = (x / 2) * (y / 2) + 64;
} else {
generatedNum = (x / 2) * (y / 2) + (index * 128);
}
}
public double getGeneratedNumber() {
return generatedNum;
}
public boolean setTouchBool(boolean b) {
this.onTouchHandler = b;
}
}
Android will cascade down the views calling onTouchEvent on each one until it receives a true from one of them. If you want a touch event to be handled by all of them, then return false until it reaches the last one.
EDIT:
Ok. If I understand correctly, you have a single top view containing a bunch of child views one layer deep. My original answer was assuming that you had three custom views that were on top of each other in the ViewGroup's hierarchy (View3 is a child of View2. View2 is a child of View1. View1 is a child of ParentView). You want the user's touch event on the parent view to get sent to all of it's children.
If that's the case, AFAIK, there is no view in Android's API that allows that. So, you'll have to make a custom view that does it.
OK, I haven't tested this, so please tell me if it works and if it's what you're trying. Create a custom class that extends whatever object frame is, then override the onTouch method like so.
#Override
public boolean onTouchEvent(MotionEvent ev) {
for(int i = 0; i < this.getChildCount(); i++){
this.getChildAt(i).dispatchTouchEvent(ev);
}
return true;
}
Now, keep the same logic that your custom views have, except they should all return false because your parent view will not receive the onTouch event unless they do as stated in my previous answer
note: with this implementation, the child view that the user actually touches will fire twice because the logic will go
fire child touch event -> return false -> fire parent touch event -> fire child touch event again
I know this question is very old, but I had the same problem and solved it by creating my own Layout to determine which child is actually touched.
I therefore iterate over the children of my custom layout and check if the user actually clicked on the view. The collision detection is handled in the custom view's onTouch() method. (Collision detection is done by intersecting a Region() with the event's x,y coordinates. For me this was convennient because I drew the custom view with a Path())
Here is a kotlin code snippet from my custom layout for better understanding:
class CustomLayout(context: Context, attrs: AttributeSet) :
RelativeLayout(context, attrs){
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
if(ev.action != MotionEvent.ACTION_UP){
return true
}
//Iterate over child view and search for the right child that should handle this touch event
for (i in childCount - 1 downTo 0) {
val child = getChildAt(i)
if (!viewTouched(child, ev)) {
continue
}
//Do something
Timber.d("Touched view: ${child.id}")
}
return true
}
private fun viewTouched(child: View, ev: MotionEvent) : Boolean {
child as OnTouchListener
//onTouch() does the collision detection
return child.onTouch(child, ev)
}

Detect which view your finger is sliding over in Android

While similar questions have been asked in the past they don't seem to really have been answered which might be due to confusion as to what's being asked.
Put simply, I'd like to detect which view is being entered as your finger slides over the screen. The best example of this in action is the soft keyboard on any android phone. When you press any key it shows up as a popup to tell you what letter is under your finger. If you now move your finger over the keyboard in a single gesture the various letters pop up as you move over the various letters of the alphabet.
What listeners are used for this type of behaviour. I've tried OnTouchListeners but they seem to be only when you 'touch' the button as opposed to 'finger past' them
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {doStuff();}
});
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
doStuff();
return false;
}
});
OnFocusChangeListener don't help either.
create a Layout
add Views to your Layout
set the setOnTouchListener to your Layout
override the onTouch method with the following:
public boolean onTouch(View v, MotionEvent event)
{
LinearLayout layout = (LinearLayout)v;
for(int i =0; i< layout.getChildCount(); i++)
{
View view = layout.getChildAt(i);
Rect outRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
if(outRect.contains((int)event.getX(), (int)event.getY()))
{
// over a View
}
}
}
EDIT:
I saw keyboard. I guess, it just one view and coordinates of every letter is known. So you can easily compute which letter the user slides through
AND NOW THE ANSWER:
I'm not sure, but probably this code helps your.
It's so far away, I wrote it for me. But the idea is following.
If I remember right, there is no gesturedetector for views, but you can combine touchlistener of the view with geturelistener of your activity.
Once you've touched your view, you have
private GestureDetector mGestureDetector;
// x and y coordinates within our view
private static float sideIndexX;
private static float sideIndexY;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
...
mGestureDetector = new GestureDetector(this, new SideIndexGestureListener());
}
class MyGestureListener extends
GestureDetector.SimpleOnGestureListener
{
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY)
{
// we know already coordinates of first touch
// we know as well a scroll distance
sideIndexX = sideIndexX - distanceX;
sideIndexY = sideIndexY - distanceY;
// when the user scrolls within our side index
// we can show for every position in it a proper
// item in the country list
if (sideIndexX >= 0 && sideIndexY >= 0)
{
doStuff();
}
return super.onScroll(e1, e2, distanceX, distanceY);
}
}
button.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
// now you know coordinates of touch
// store them
sideIndexX = event.getX();
sideIndexY = event.getY();
doStuff();
return false;
}
});
You may want to try GestureDetector.
http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html
it's geared to multitouch, but this is a good start toward understanding android touch/gestures, next stop, api docs/samples
The simple answer is you can't - not like the iPhone when in accessibility mode.
Until Ice Cream Sandwich that is. It now has the iPhone-like capability of being able to identify elements under your finger without having to lift it.
It's fairly straight forward to handle this manually.
Using your parent layout as the onTouchListener (in the following example, I extend a RelativeLayout), you can check for collisions between a MotionEvent and the child Views using simple co-ordinate comparison logic:
/** Returns the View colliding with the TouchEvent. */
private final View getCollisionWith(final MotionEvent pMotionEvent) {
// Declare the LocationBuffer.
final int[] lLocationBuffer = new int[2];
// Iterate the children.
for(int i = 0; i < this.getChildCount(); i++) { /** TODO: Order. */
// Fetch the child View.
final View lView = this.getChildAt(i);
// Fetch the View's location.
lView.getLocationOnScreen(lLocationBuffer);
// Is the View colliding?
if(pMotionEvent.getRawX() > lLocationBuffer[0] && pMotionEvent.getRawX() < lLocationBuffer[0] + lView.getWidth() && pMotionEvent.getRawY() > lLocationBuffer[1] && pMotionEvent.getRawY() < lLocationBuffer[1] + lView.getHeight()) {
// Return the colliding View.
return lView;
}
}
// We couldn't find a colliding View.
return null;
}
Calls to getCollisionWith will return View references that may be manipulated arbitrarily.

Categories

Resources