I am working on an application that allows user to drag a dot on a screen and set the values of distance for example. What I want is to have half screen for drag function and the other half with gadgets (buttons and textViews). To do so I created a class extending SurfaceView, used a bitmap "dot" and the function onTouchEvent and in my xml file I referenced like following to my view:
<test1.DragView
android:id="#+id/view"
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"
/>
Which gives me what I want. But now I want to dynamically update the position of the dot. To do so I added setText() function for my textView in my onTouchEvent function:
#Override
public boolean onTouchEvent(MotionEvent event) {
x=(int)event.getX();
y=(int)event.getY();
bitmap =BitmapFactory.decodeResource(getResources(), R.drawable.dot);
if(x<0)
x=0;
if(x > width+(bitmap.getWidth()/2))
x=width+(bitmap.getWidth()/2);
if(y <0)
y=0;
if(y > height/2)
y=height/2;
tv=(TextView) findViewById(R.id.textView); //I declared tv in the beginning of my class
tv.setText(x);
updateBall(); //it's a function that resets the position of the dot
return true;
}
it gives me errors like
AndroidRuntime(845): FATAL EXCEPTION: main
AndroidRuntime(845): java.lang.NullPointerException
AndroidRuntime(845):
at test1.DragView.onTouchEvent(DragView.java:87)
AndroidRuntime(845):
at android.view.View.dispatchTouchEvent(View.java:5462)
AndroidRuntime(845): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1953)
I cannot use my textView in my DragView class. Is it normal? I can provide more explications if needed.
EDIT:
After using the solution of ReubenScratton I can acces my textView now but I'm getting the following error:
AndroidRuntime(672): FATAL EXCEPTION: main
AndroidRuntime(672): android.content.res.Resources$NotFoundException: String resource ID #0x109
AndroidRuntime(672): at android.content.res.Resources.getText(Resources.java:247)
AndroidRuntime(672): at android.widget.TextView.setText(TextView.java:3427)
AndroidRuntime(672): at test1.DragView.onDraw(DragView.java:73)
I am answering my own question but note that I'm just putting together the solutions given by others (ReubenScratton and lazeR) so that if someone else is having the same problem he'll find the whole solution.
So the solution: first of all instead of accessing my textView directly I had to use
tv=(TextView) ((Activity)getContext()).findViewById(R.id.textView)
because if you use
tv=(TextView)findViewById();
You're using View.findViewById() which will only search through child views.
You want to use the Activity.findViewById() ReubenScratton
And for my second problem as I was using directly an int to the setText() function it wasn't working but thanks to lazeR's comment I noticed it and found the solution. Thanks to all those who helped me :).
Related
In Android Studio my data binding itself works and is set up fine. I have a boolean defined like this:
<resources>
<bool name="showAds">false</bool>
</resources>
and in a layout.xml file i would like to referenced this boolean (which works fine) but i want to assign a id based on this boolean. Let me show you what i am trying to accomplish:
I have a button that is in a relativeLayout tag and depending on this boolean i would like to reposition the button. So I have this:
<Button
android:id="#+id/startButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="64dip"
****************
android:layout_below="#{#bool/showAds ? #+id/adone : #+id/title_main}"
****************
android:layout_centerHorizontal="true"
android:textColor="#0080FF"
android:text="#string/start_btn_title" />
See what i want to to do? I want to layout the button below a layout called adone if the showAds boolean is true, otherwise place it below a layout called title_main. Whats the syntax for this as what I have here is not compiling. I get a compile error:
expression expected after the second # sign
The above is the same problem as in How to get dimensions from dimens.xml
None of the LayoutParams attributes have built-in support. As answered in the linked article, data binding of LayoutParams was thought to be too easy to abuse so it was left out of the built-in BindingAdapters. You are not abusing it, so you should add your own.
#BindingAdapter("android:layout_below")
public static void setLayoutBelow(View view, int oldTargetId, int newTargetId) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)
view.getLayoutParams();
if (oldTargetId != 0) {
// remove the previous rule
layoutParams.removeRule(RelativeLayout.BELOW);
}
if (newTargetId != 0) {
// add new rule
layoutParams.addRule(RelativeLayout.BELOW, newTargetId);
}
view.setLayoutParams(layoutParams);
}
As an aside, the #+id/adone in the binding syntax will not create the id. You should create the id in the View you're binding to.
This question comes up quite often, however in all examples i have found, the image src is defined in the XML. e.g android:src="..."
My code doesn't specificy the src untill the activity, using ImageButton.setImageResource() as it is a single button, performing play/stop
How do i fill the ImageButton with the src, when src is defined later?
I tryed ImageButton.setScaleType="fitXY", however sdk doesn't like it using string...
UPDATE: After trying to use the suggested below, the problem still occurs. here is more explanation to help
<ImageButton
android:id="#+id/imgStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
/>
public class MainActivity extends Activity{
private ImageButton player;
protected void onCreate(){
player = (ImageButton) findViewById(R.id.imgStart);
...
if(isPlaying){
player.setImageResource(bitmap image);
}
else{
player.setImageResource(different bitmap image);
}
...
}
Use ScaleType.CENTER_CROP instead
player .setScaleType(ImageView.ScaleType.CENTER_CROP);
It seems CENTER_CROP works as fit_xy.
but, it's not sure why it does..
Please try below code to set ScaleType programatically
ImageButton object".setScaleType(ScaleType.FIT_XY)
"ImageButton object" should be object of class ImageButton
(that you defined probably in xml).
Do it this way
ImageButton object.setScaleType(ScaleType.FIT_XY)
Use ScaleType.FIT_XY instead of fitXY in your code
ImageButton.setScaleType="fitXY"
yes this will not work, because you have to use it properly using below code also should setAdjustViewBounds to true.like this:
player.setAdjustViewBounds(true);
player.setScaleType(ScaleType.FIT_XY);
This will definitely work!
I am taking reference from TextJustify-Android. I am implementing option 2 in above link. When I run my app on emulator text appears one word in one line, next word in next line and so on. I dont know whats wrong in my code. Please help me. Thanks.
Activity class code-
textView1 = (TextView) findViewById (R.id.textView1);
textView1.setMovementMethod(new ScrollingMovementMethod());
textView1.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener()
{
boolean isJustified = false;
#Override
public boolean onPreDraw()
{
if(!isJustified)
{
TextJustifyUtils.run(textView1,0);
isJustified = true;
}
return true;
}
});
Xml code-
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="8"
android:gravity="center">
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="vertical"
android:text="#string/his"
android:textColor="#FFFFFF"/>
</LinearLayout>
And I am implementing TextJustifyUtils class in my app as suggested in above link.
I have made one change In that link given TextJustifyUtils.run(textView1); and In my code eclipse suggest me to change in TextJustifyUtils.run(textView1,0);. Is anything wrong with this?
Update:
In TextJustifyUtils I change public static void justify(TextView textView) into public static void run(TextView textView) as commented by the author there and TextJustifyUtils.run(textView1,0); into TextJustifyUtils.run(textView1); in Activity class. But the output is same as I type in my textView i.e text without justification.
If some one following the above link to justify text please choose option 1. Its work fine. And if you have any problem. Ask from author. I think he always happy to help you nice guy. As he helps me so much. And option 1 working with minor changes.
I'm searching a method to navigate in a app throw all elements with a virtual dpad. But how do I find the nearest neighbor in the directions up, down, left and right?
e.g I have an event received to go down, now I want to set the focus on the button below.
I don't want to use the definition in the xml files like this:
<LinearLayout android:orientation="vertical" ... >
<Button android:id="#+id/top" android:nextFocusUp="#+id/bottom" ... />
<Button android:id="#+id/bottom" android:nextFocusDown="#+id/top" ... />
</LinearLayout>
How can I do that?
Thx.
For this you should override onKeyDown() method in Activity, there you can find currently focused view with method View.getFocusedChild(), then use View.focusSearch(int) for searching next view, and View.requestFocus() for getting focus.
I hope you can combine this methods for good result :)
I found the smart solution (e.g for go down):
bic=new BaseInputConnection(this.getWindow().getDecorView(),false);
KeyEvent event2 = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN,0, KeyEvent.META_SYM_ON, 0, 0, KeyEvent.FLAG_VIRTUAL_HARD_KEY);
bic.sendKeyEvent(event2);
Thats all, an internal algortihm find the next element in your selected direction
I've been working on an app where a ball (bitmap) appears on the canvas at the point where the user taps on the screen. The background is an xml layout setContentView(R.layout.newsession). The canvas is a black painted canvas. When i set my java parent class setContentView(customView), the program works fine but when I add the custom surface view to my XML layout and setContentView(R.layout.newsession), the screen just shows the canvas, and the OnTouch event doesn't work. Am I doing something wrong? I've been working on this for almost a week now and I really need help. I will post my code below for the XML layout and custom surfaceView. Thanks in advance!
XML layout (newsession)
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/newSessionPage"
>
<ImageView
android:layout_width="231dp"
android:id="#+id/ivStrikeGrid"
android:layout_gravity="center"
android:layout_height="270dp"
android:layout_marginTop="18dp"
android:src="#drawable/strike_grid"
android:layout_marginBottom="10dp"
/>
<appsys.studios.CustomSurfaceViewOne
android:id="#+id/customSurfaceViewOne1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></appsys.studios.CustomSurfaceViewOne
>
</FrameLayout>
Custom SurfaceView
package appsys.studios;
public class CustomSurfaceViewOne extends SurfaceView implements Runnable{
public CustomSurfaceViewOne(Context context, AttributeSet attr) {
super(context, attr);
ourHolder = getHolder();
}
// Other stuff
}
It works fine like this:
newSeshView = new CustomSurfaceViewOne(this, null);
setContentView(newSeshView);
But nothing happens when I try to use it from the XML layout, like this:
newSeshView = new CustomSurfaceViewOne(this, null);
setContentView(R.layout.newsession);
Thanks again! :)
I think you might be missing invallidate() call of the view on its touch reading delegates.
I am not sure exactly what is happening in your code. But if i would be creating my own view and adding it in my own layout as you did.
And want it to change itself on reading touch events then i would be doing something like
in the myown view class it self
#override
// i dont remem exact signature of this method. google it or see docs
// motive is to read touch event of view and doing appropriate changes
// and redrawing the view again
public void onTouchEvent(MotionEvent me)
{
doCalculation(); // change points where to draw the ball next time. Read me
invalidate(); // tell the view re draw it self
}
Hope it helps :)
I ran into the same issue, and found your question while looking for the answer. I solved it, but I'm not sure it is the proper way.
3 files, your main activity, your surfaceview, and your XML file.
Your XML file looks ok, you have the surfaceview in it
<appsys.studios.CustomSurfaceViewOne
android:id="#+id/customSurfaceViewOne1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></appsys.studios.CustomSurfaceViewOne
>
In your activity, add implements OnTouchListener, use setContentView(R.layout.newsession); and after that, still in your onCreate() add this line CustomViewOne cvo = (CustomViewOne)findViewById(R.id.customSurfaceViewOne1) and set the listener to it by cvo.setOnTouchListener(this);
then add your onTouch
#Override
public boolean onTouch(View v, MotionEvent event) {
customSurfaceViewOne1.myOnTouch(event);
return false;
}
where myOnTouch() is a method in your customSurfaceViewOne1 class where you will do all your ontTouch events. Notice I passed in the MotionEvent event.
Again, I'm not sure if this is the proper way to do it, it's just how I got it to work. The reason I did it was just so I could have an admob ad above my surfaceview lol.