I'm new to Android, I've followed the hello world tutorial through and have a basic idea of what's going on. I'm particularly interested in the touch screen of my T-Mobile Pulse so just to get me started I want to be able to write the co-ordinates of a tocuh event on the screen, so say the user touched the co-ordinate 5,2 - a textview on the screen would display that.
At present I have a simple program that just loads an xml file which contains the textview I intend to write the co-ordinates in.
Thank you in advance, I did Google for help and searched stackoverflow but everything I found either went way over my head or wasn't suitable for this. Cheers.
You can use this function : http://developer.android.com/reference/android/view/View.html#setOnTouchListener(android.view.View.OnTouchListener)
You will probably put it in your onCreate method roughly this way (tested this time) :
Activity onCreate code
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView textView = (TextView)findViewById(R.id.textView);
// this is the view on which you will listen for touch events
final View touchView = findViewById(R.id.touchView);
touchView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
textView.setText("Touch coordinates : " +
String.valueOf(event.getX()) + "x" + String.valueOf(event.getY()));
return true;
}
});
}
layout code
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="#+id/touchView"
android:background="#f00"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="#+id/textView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, TestActivity"
/>
</LinearLayout>
Edit: I tried my code and indeed there were a few errors. Anyway, with the layout I give you here it works on my emulator. Can you provide maybe more code/context so I can see what's wrong?
It sounds like you want to get touch events from the whole area of your layout for this particular test. Try attaching the touch listener to your parent view rather than a separate target view.
This isn't a very common approach. In most cases you will want to listen for touch events in a specific child view and if you have other views in your layout that handle touch events (such as a button) they'll take priority over a parent view. See http://developer.android.com/guide/topics/ui/ui-events.html for more info about handling UI events.
Layout (touch_viewer.xml):
<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="#+id/parent" >
<TextView android:id="#+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello, World!" />
</LinearLayout>
And in your activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.touch_viewer);
final LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
final TextView text = (TextView) findViewById(R.id.text);
parent.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent ev) {
text.setText("Touch at " + ev.getX() + ", " + ev.getY());
return true;
}
});
}
The following works using a touch screen on the jetboy sample android app.
Joes code worked with one tweak to make it shine the background thru.
The only line I added was
android:background="#0000"
android:layout_height="fill_parent"
android:layout_height="fill_parent"
Thanks Joe (above).
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView textView = (TextView)findViewById(R.id.textView);
// this is the view on which you will listen for touch events
final View touchView = findViewById(R.id.touchView);
touchView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
textView.setText("Touch coordinates : " +
String.valueOf(event.getX()) + "x" + String.valueOf(event.getY()));
return true;
}
});
}
layout code
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.android.samples.jetboy.JetBoyView android:id="#+id/JetBoyView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<TextView
android:id="#+id/touchView"
android:background="#0000"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<TextView
android:id="#+id/textView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="Hello World, TestActivity"
/>
</FrameLayout>
The corrected version without the errors:
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textView = (TextView) findViewById(R.id.textView);
// this is the view on which you will listen for touch events
final View touchView = findViewById(R.id.touchView);
touchView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
textView.setText("Touch coordinates : "
+ String.valueOf(event.getX()) + "x"
+ String.valueOf(event.getY()));
return true;
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Related
I am using onTouchEvent to capture clicks on buttons. These buttons are in views, inflated in the main view.
My problem is that I have to click twice time on the screen to get my onTouchEvent triggered.
I found a similar topic telling to call setContentView after inflating but my app contains many other things so I just cannot call setContentView each time I inflate a new view.
activity_main.xml :
<RelativeLayout android:id="#+id/activity_main"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.pixeemedical.kneeplus.MainActivity"
xmlns:app="http://schemas.android.com/apk/res-auto">
... other stuff here
<RelativeLayout
android:id="#+id/rlayout_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true">
</RelativeLayout>
</RelativeLayout>
My ActivityMain.java :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMainLayout = findViewById(R.id.rlayout_content);
mMainLayout.removeAllViews();
View currentLayoutToAdd = LayoutInflater.from(this).inflate(R.layout.layout_to_inflate, mMainLayout, false);
mMainLayout.addView(currentLayoutToAdd, 0);
Button btn = findViewById(R.id.btn);
btn.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
// called only after second click
}
});
}
}
create a custom view for color picker that contains image and I'm going to take a color from this image on touch bot neither onTouch(View v, MotionEvent ev) nor onClick(View v) is called.
So here is my view class:
public class ChangeColor extends RelativeLayout {
public ChangeColor(Context context) { super(context); init(); }
public ChangeColor(Context context, AttributeSet attrs) { super(context, attrs); init(); }
private void init(){
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.change_color, this);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
ImageView iv = (ImageView)findViewById(R.id.colorScaleImageView);
final Bitmap bitmap = ((BitmapDrawable) iv.getDrawable()).getBitmap();
iv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d("ImageView", "onClick();");
}
});
iv.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent ev) {
Log.d("ChangeColor", "onTouch();");
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
int c = bitmap.getPixel((int)ev.getX(), (int)ev.getY());
SettingsManager.setColor(c);
Log.d("ChangeColor", "" + c);
return false;
default:
return true;
}
}
});
}
}
and layout xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/colorScaleImageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/seekBar1"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:clickable="true"
android:layout_gravity="center_horizontal"
android:src="#drawable/background_color" />
<SeekBar
android:id="#+id/seekBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/textView1"
android:layout_alignParentLeft="true"
android:focusable="false"
android:maxHeight="8dp"
android:minHeight="8dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:progressDrawable="#drawable/seekbar_progress"
android:thumb="#drawable/seekbar_thumb_"
android:thumbOffset="7dp" />
</RelativeLayout>
So no one log message appear in LogCat.
P.S. I saw few similar questions on SO but they did not helped me.
P.P.S. This view is used in fragment and fragment is used in Activity. I added a fullscreen view in that activity with OnClickListener in order to see if clicks go to the parent view and I can see Log message from that background view only I tap outside the image and no message if I tap on image.
Thanks.
You have extended the relative layout but are not calling it in this example.
In the XML you should implement the class you developed instead of RelativeLayout
try
<?xml version="1.0" encoding="utf-8"?>
<**namespace**.ChangeColor xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/colorScaleImageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/seekBar1"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:clickable="true"
android:layout_gravity="center_horizontal"
android:src="#drawable/background_color" />
</**namespace**.ChangeColor>
**EDIT
It was correct the first time. To implement it you'll have to attach ChangeColor to another layout, it cannot be called in the layout that it is attempting to inflate when it's called. Ex. ChangeColor inflates change_color.xml, you cannot have the tag NAMESPACE.ChangeColor called in the layout that ChangeColor.init() is inflating.
New to programming android apps and keep getting a null pointer exception and im not sure why. Ive ressearched this a bit and it seems that most people get this because of the setContentView but it seems that from what everyone else is saying my setContentView is in the right space etc...
int randInt;
int[] randColor = {Color.RED,Color.BLUE,Color.GREEN,Color.YELLOW,Color.BLACK,
Color.CYAN,Color.MAGENTA,Color.LTGRAY,Color.DKGRAY,Color.WHITE};
TextView textView1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(this);
View layout = findViewById(R.layout.activity_main);
layout.setOnTouchListener(this);
textView1 = (TextView) findViewById(R.id.textView1);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
public void onClick(View v) {
setBackGroundColor(randInt);
}
#Override
public boolean onTouch(View v, MotionEvent e){
float xPos = e.getX();
float yPos = e.getY();
changeText(xPos,yPos);
return true;
}
public void setBackGroundColor(int randInt){
getWindow().setBackgroundDrawable(new ColorDrawable(randColor[getRandomInt()]));
}
public int getRandomInt(){
Random randomInt = new Random();
randInt = randomInt.nextInt(10);
return randInt;
}
public void changeText(float xPos, float yPos){
textView1.setText("You are at " + xPos + " , " + yPos);
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="#string/hello_world" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="66dp"
android:text="#string/button" />
Assign an id to your layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="#+id/my_layout">
Then change your code as so:
View layout = findViewById(R.id.my_layout);
findViewByID(), like the method name says, needs an ID. Passing off a layout does pass an int, so it compiles fine, but it's unlikely you'll match against an id, and the method returns null.
If anything else also returns null, make sure your layout (and its children views) are contained in the xml file called activity_main.xml and that you have cleaned your project.
Instead of this statement
View layout = findViewById(R.layout.activity_main);
Change it to
View layout = findViewById(android.R.id.content);
findViewById(android.R.id.content) means You want to get the content view of an Activity
Replace your setContentView line with this:
LayoutInflater inflater = LayoutInflater.from(this);
View view = (View) inflater.inflate(R.layout.activity_main); // can't remember if casting is necessary here
setContentView(view);
I added to the activitiy java file:
#Override
public boolean onTouchEvent(MotionEvent event) {
Button p1_button = (Button)findViewById(R.id.mybutton);
p1_button.setText("Some text");
return super.onTouchEvent(event);
}
Once I add this:
Button p1_button = (Button)findViewById(R.id.mybutton);
p1_button.setText("Some text");
The application crash when I touch the screen on my device.
If im removing this two lines when touching the screen on my device will not do anything but also will not crash.
This is the main xml file where the button is added:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<FrameLayout
android:id="#+id/videoview"
android:layout_width="720px"
android:layout_height="480px"/>
<Button
android:id="#+id/mybutton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="REC"
android:textSize="12dp"/>
</LinearLayout>
</LinearLayout>
I wanted to do that when I touch the screen on my device it will change the button text.
What should I do ?
because the button does not exist in this context you are trying to find it. Define the button as static in your class and find it in the onCreate
static Button p1_button;
...
protected void onCreate(...){
....
p1_button =(Button)findViewById(R.id.mybutton);
}
then use the p1_button variable in the onTouchEvent
OR
you can pass the activity in the onTouchEvent like
final Activity activity = this;
and then
#Override
public boolean onTouchEvent(MotionEvent event) {
Button p1_button = (Button)activity.findViewById(R.id.mybutton);
p1_button.setText("Some text");
return super.onTouchEvent(event);
}
I have this main.xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/background"
>
<ImageView
android:id="#+id/img1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/z01"
/>
<ImageView
android:id="#+id/img2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/z02"
/>
</LinearLayout>
What I am trying to achieve is:
when the user touch and hold img1, the picture changs to the pressed pic (i.e. changed from z01.png to z01_pressed.png)
when (for example) the user moves from img1 to img2 while he holding, img2 get pressed (changed its picture from z02.png to z02_pressed.png) and img1 returns to its state (to z01.png).
to achieve this, I wrote this in onCreate method:
final ImageView img1 = (ImageView) findViewById(R.id.img1);
final ImageView img2 = (ImageView) findViewById(R.id.img2);
img1.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
img1.setBackgroundResource(R.drawable.z01_pressed);
return false;
}
});
img2.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
img2.setBackgroundResource(R.drawable.z01_pressed);
return false;
}
});
However, this does not work. Am I getting something wrong?
You can use a button and set a custom image as the drawable of that button. That way, you won't have to manage the pressed and unpressed states yourself. See this link:
http://blog.androgames.net/40/custom-button-style-and-theme/
To those who might be interested:
This can be done using OnDragListener. It needs some work to accomplish this. I gave up on that to make my life easier.