public class UnitConverterActivity extends Activity implements OnTouchListener {
/** Called when the activity is first created. */
LinearLayout mLinearLayout;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLinearLayout = new LinearLayout(this);
ImageView i = new ImageView(this);
i.setImageResource(R.drawable.mainmenu);
//i.setAdjustViewBounds(false);
i.setScaleType(ScaleType.FIT_XY);
i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mLinearLayout.addView(i);
setContentView(mLinearLayout);
//setContentView(R.layout.main);
}
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
return false;
}
}
I have used the above method to load an image for the main menu I am trying to create. The image has four areas and each will be used to call a particular function of the app. Now I am trying to implement touch interface on those areas. I know how to define the range of pixels for that purpose but I am at loss on how to implement OnTouchListner on the image. Please help me in this regard.
If your image was split into four rectangular quarters (say)
then in onCreate have:
i.setOnTouchListener(this);
and for your listener, something like this (illustrates the principle only):
#Override
public boolean onTouch(View v, MotionEvent mev) {
int width = v.getWidth();
int height = v.getHeight();
float x = mev.getX();
float y = mev.getY();
String msg;
if (x < width / 2) {
if (y < height / 2)
msg = "Top left quarter";
else
msg = "Bottom left quarter";
} else {
if (y < height / 2)
msg = "Top right quarter";
else
msg = "Bottom right quarter";
}
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
return false;
}
Just put this code in onCreate().
i.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//your code
}
}
Related
I am new in the Android. I can not touch the three buttons at one time This code I can click on the three buttons but not the One Touch. I have researched a lot but I did not find the solution I tried to use OnCilckListener() but OnTouchListener() could not find a way
I want to give me an example or a tip. And you can see in the picture. Please help me, thank you
public class MainActivity extends Activity{
Button a,b,c;
int a1 = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//a = (Button)findView...;
//b = ....;
//c = ....;
a.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
a1 = 1;
b.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
if(a1 == 1){
a1 = 2;
c.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
if(a1 == 2){
Toast.makeText(getBaseContext(), "Toast", Toast.LENGTH_SHORT).show();
a1 = 0;
}}});
}
}});
}
});
}
Put the 3 buttons in a single parent view. Have the parent view implement the swiping behavior. Then have the parent view override onInterceptTouchEvent to return true for all touches. That way the parent view will handle all touches for all of its children, and you just have a basic swipe detector.
Attach an onTouchListener to the layout containing the three buttons. Check each touch for an ACTION_DOWN (putting the finger down) that is inside the bounds of the first view. Then look for the next ACTION_UP (releasing the initial touch) to be inside the bounds of the third view. You can check whether a touch event is in the bounds of a view with the following code:
public static boolean hitTest(View v, int x, int y) {
final int tx = (int) (ViewCompat.getTranslationX(v) + 0.5f);
final int ty = (int) (ViewCompat.getTranslationY(v) + 0.5f);
final int left = v.getLeft() + tx;
final int right = v.getRight() + tx;
final int top = v.getTop() + ty;
final int bottom = v.getBottom() + ty;
return (x >= left) && (x <= right) && (y >= top) && (y <= bottom);
}
Here is the problem I am facing. On a empty relative layout, when touched textview is instantiated at the touched x y position. I got this far correct, but the problem is that when I touch on the empty space near already instantiated view, previous view and currently placed views are overlapped. I tried by the getting the child views of the layout and checking the current view and already placed view using rect data that if they intersect. How to solve this problem?
Here is the code:
public class MainActivity extends AppCompatActivity
{
private int id = 0;
private RelativeLayout root;
private RelativeLayout.LayoutParams params;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_designer);
root = (RelativeLayout) findViewById(R.id.rootlayout);
root.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
instantiateView(v, event);
break;
}
return true;
}
});
}
private void instantiateView(View v, MotionEvent event)
{
int x = (int) event.getX();
int y = (int) event.getY();
TextView bt = new TextView(DesignerActivity.this);
bt.setText("1");
bt.setId(++id);
bt.setBackgroundColor(Color.BLACK);
bt.setTextColor(Color.WHITE);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
showDialog();
}
});
params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.setMargins(x, y, 0, 0);
bt.setLayoutParams(params);
//((ViewGroup) v).addView(bt);
if(root.getChildCount() <= 0)
{
((ViewGroup) v).addView(bt);
}
else
{
for (int i = 0; i < root.getChildCount(); i++)
{
if (!checkCollision(bt, root.getChildAt(i)))
{
if(bt != root.getChildAt(i))
{
((ViewGroup) v).addView(bt);
}
}
}
}
}
private void showDialog()
{
final Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.dialog_layout);
Button editBtn = (Button) dialog.findViewById(R.id.button1);
Button deleteBtn = (Button) dialog.findViewById(R.id.button2);
editBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0)
{
dialog.dismiss();
}
});
deleteBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0)
{
dialog.dismiss();
}
});
dialog.show();
}
private boolean checkCollision(View v1, View v2)
{
Rect r1 = new Rect(v1.getLeft(), v1.getTop(), v1.getRight(), v1.getBottom());
Rect r2 = new Rect(v2.getLeft(), v2.getTop(), v2.getRight(), v2.getBottom());
return r1.intersect(r2);
}
}
You are using Relative Layout that's why your Textviews are overlapping.
If you don't want the overlapping and want to place it next or somewhere else to the overlapped view , it is your decision. Just check if they intersect and take appropriate decision based on your requirement.
Below line is the problem in your code.
Rect r1 = new Rect(v1.getLeft(), v1.getTop(), v1.getRight(), v1.getBottom());
You set the params' Margin does not mean that you will get desired left,top,right, bottom values.You will get these values right after the inflation of your view hierarchy.
You can use this function:
private boolean checkCollision(View v1, View v2)
{
int leftMargin = ((RelativeLayout.LayoutParams) v1.getLayoutParams()).leftMargin;
int topMargin = ((RelativeLayout.LayoutParams) v1.getLayoutParams()).topMargin;
Rect r1 = new Rect(root.getPaddingLeft() + leftMargin, root.getPaddingTop() + topMargin,
root.getPaddingLeft() + leftMargin + v2.getWidth(), root.getPaddingTop() + topMargin + v2.getHeight());
Rect r2 = new Rect(v2.getLeft(), v2.getTop(), v2.getRight(), v2.getBottom());
return r1.intersect(r2);
}
After that use
params.addRule(); according to your requirement where you want to place your overlapping view.
In my app I have a horizontal scrollview of 6 duck images, while the horizontal scrollview can work properly, now I would like to add a SeekBar underneath the horizontal scrollview such that moving the seekbar will positioning the horizontal scrollview to the proper item.
I have written the codes as follows:
Seekbar:
seekBar1.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
#Override
public void onStopTrackingTouch(SeekBar seekBar)
{
// TODO Auto-generated method stub
}
#Override
public void onStartTrackingTouch(SeekBar seekBar)
{
// TODO Auto-generated method stub
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
seekBar.setProgress(progress);
if (progress ==5) {mLinearLayout.scrollTo(R.drawable.d_duck400_5, 0);}
if (progress ==4) {mLinearLayout.scrollTo(R.drawable.d_duck400_4, 0);}
if (progress ==3) {mLinearLayout.scrollTo(R.drawable.d_duck400_3, 0);}
if (progress ==2) {mLinearLayout.scrollTo(R.drawable.d_duck400_2, 0);}
if (progress ==1) {mLinearLayout.scrollTo(R.drawable.d_duck400_1, 0);}
if (progress ==0) {mLinearLayout.scrollTo(R.drawable.d_duck400_0, 0);}
}
});
}
Horizontal Scrollview:
private void getDeviceWidth()
{
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
mWidth = dm.widthPixels;
}
private void initView()
{
int[] imageArray = { R.drawable.d_duck400_0, R.drawable.d_duck400_1, R.drawable.d_duck400_2,
R.drawable.d_duck400_3, R.drawable.d_duck400_4, R.drawable.d_duck400_5};
// int[] imageArray = { R.drawable.d_duck1_400, R.drawable.d_duck1_400, R.drawable.d_duck1_400,
// R.drawable.d_duck1_400, R.drawable.d_duck1_400, R.drawable.d_duck1_400};
mLinearLayout = (LinearLayout) findViewById(R.id.scrollview_layout);
mLinearLayout.removeAllViews();
for (int i = 0; i < 6; i++)
{// Place 6 items into horizontalscrollview
int width = mWidth /1;
LinearLayout itemLayout = (LinearLayout) LinearLayout.inflate(Duck.this, R.layout.d_scrollview_item, null);
itemLayout.setLayoutParams(new LayoutParams(width, LayoutParams.MATCH_PARENT));// set the width as 1 screen showing 3 items
itemLayout.setGravity(Gravity.CENTER_VERTICAL);
ImageView mImageView = (ImageView) itemLayout.findViewById(R.id.imageview);
TextView mTextView = (TextView) itemLayout.findViewById(R.id.textview);
final String page = "The" + (i + 1) + "th page";
mTextView.setText(page);
mImageView.setBackgroundResource(imageArray[i]);
mLinearLayout.addView(itemLayout);
itemLayout.setOnTouchListener(new OnTouchListener()
{
public boolean onTouch(View v, MotionEvent event)
{
// Toast.makeText(Duck.this, "Click" + page, Toast.LENGTH_SHORT).show();
return false;
}
});
}
}
Question:
Once I move the seekbar, the pictures in the horizontal Scrollview all gone.
What is happening? Thanks in advance for your advice!
if (progress ==5) {mLinearLayout.scrollTo(R.drawable.d_duck400_5, 0);
scrollTo expects x,y coordinates to scroll to a new position. But you give it R.drawable.d_duck400_5 as x value. This will be just a random integer produced by compiler. It is not the x coordinate you want to scroll.
Try something like this:
if (progress ==5) {mLinearLayout.scrollTo(200, 0);
if (progress ==5) {mLinearLayout.scrollTo(400, 0);
....
If you want to find the position of a view, you can go with getLocationInWindow or getLocationOnScreen methods.
int[] location = new int[2];
yourView.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
I searched all over, but could not find a solution.
I have a view (lets call it myView) inside a scrollview. myView is bigger than the screen. Since I'm able to get the relative x,y position of my finger inside myView, I would like to make the scrollView autoscroll to the top/bottom when my finger enters a certain top/bottom threshold.
I have some ideas, namely translating the drag location to the screen position but this did not solve this problem.
thanks in advance
cheers
All right I figured it out by myself.
First I had to extend the ScrollView class and added an interface OnScrollViewListener.
public class MyScrollView extends ScrollView {
private OnScrollViewListener mListener;
public MyScrollView(Context c, AttributeSet attrs) {
super(c, attrs);
}
#Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (mListener != null) {
mListener.onScrollChanged((OnScrollViewListener) this);
}
}
public void setOnScrollViewListener(OnScrollViewListener listener) {
mListener = listener;
}
public static interface OnScrollViewListener {
public void onScrollChanged(OnScrollViewListener listener);
}
}
Next in my Activity I inserted a member mScrollDistance that indicates the amount of
pixels the user scrolls.
public class ScrollActivity extends Activity {
private int mScrollDistance;
#Override
protected void OnCreate(...) {
...
final MyScrollView myScrollView = (MyScrollView) findViewById(R.id.scroll_view);
myScrollView.setOnScrollViewListener(new MyScrollView.OnScrollViewListener() {
public void onScrollChanged(OnScrollViewListener listener) {
mScrollDistance = listener.getScrollY();
}
}
// making an drag and drop in an view that is inside the MyScrollView
final LinearLayout myLayout = (LinearLayout)findViewById(R.id.linear_layout);
myLayout.setOnDragListener(new View.OnDragListener() {
public boolean onDrag (View v, DragEvent event) {
int action = event.getAction();
switch(action) {
case DragEvent.ACTION_DRAG_STARTED: {
}
case DragEvent.ACTION_DRAG_LOCATION: {
int y = Math.round(event.getY());
int translatedY = y - mScrollDistance;
int threshold = 50;
// make a scrolling up due the y has passed the threshold
if (translatedY < threshold) {
// make a scroll up by 30 px
myScrollView.scrollBy(0, -30);
}
// make a autoscrolling down due y has passed the 500 px border
if (translatedY + threshold > 500) {
// make a scroll down by 30 px
myScrollView.scrollBy(0, 30);
}
// listen for more actions here
// ...
}
}
}
}
Now, mScrollDistance gets always a new value and the drag location will be translated to the view location.
I tested this and it works on layouts/views that are bigger than the screen size.
Hope that helps.
I came up with a different solution and I am happy with it.
I want to be able to drag and drop views inside a ScrollView. The ScrollView then needs to scroll up and down automatically when the shadow reaches the edges of the scroll view.
I ended up with a solution that detects wether the drop zone is completely visible inside the scrollview (with a 100px margin) and adjust the scroll view otherwise.
#Override
public boolean onDrag(View view, DragEvent event) {
MainWidget dropZoneView = (MainWidget) view;
int action = event.getAction();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
//(... other stuff happens here)
case DragEvent.ACTION_DRAG_LOCATION:
ScrollView mainScrollView = (ScrollView) findViewById(R.id.main_scroll);
int topOfDropZone = dropZoneView.getTop();
int bottomOfDropZone = dropZoneView.getBottom();
int scrollY = mainScrollView.getScrollY();
int scrollViewHeight = mainScrollView.getMeasuredHeight();
Log.d(LOG_TAG,"location: Scroll Y: "+ scrollY + " Scroll Y+Height: "+(scrollY + scrollViewHeight));
Log.d(LOG_TAG," top: "+ topOfDropZone +" bottom: "+bottomOfDropZone);
if (bottomOfDropZone > (scrollY + scrollViewHeight - 100))
mainScrollView.smoothScrollBy(0, 30);
if (topOfDropZone < (scrollY + 100))
mainScrollView.smoothScrollBy(0, -30);
break;
default:
break;
}
return true;
}
Hope this helps!
I used a timer in In C#
ScrollCalendar ScrollCalendar = new ScrollCalendar (yourScrollView);
Inside the drag event
public bool OnDrag (View v, DragEvent e)
{
var dragshadow = new EventDateDragShadow (v);
switch (e.Action) {
case DragAction.Started:
return true;
case DragAction.Entered:
break;
case Android.Views.DragAction.Location:
if (e.GetY () < 90) {
ScrollCalendar.StartScroll (-15);
} else if (e.GetY () > yourScrollView.Height - 90) {
ScrollCalendar.StartScroll (15);
} else
ScrollCalendar.StopScroll ();
return (true);
case DragAction.Exited:
return true;
case DragAction.Drop:
return true;
case DragAction.Ended:
ScrollCalendar.StopScroll ();
v.SetOnDragListener (null);
return true;
}
return true;
}
The ScrollCalendar class
public class ScrollCalendar
{
private ScrollView Calendar;
private System.Timers.Timer Timer;
private int ScrollDistance;
public ScrollCalendar(ScrollView calendar)
{
Calendar = calendar;
Timer = new System.Timers.Timer();
Timer.Elapsed+=new ElapsedEventHandler(Scroll);
Timer.Interval = 50;
}
public void StartScroll(int scrollDistance)
{
if (Timer.Enabled) {
return;
}
ScrollDistance = scrollDistance;
Timer.Enabled = true;
}
public void StopScroll()
{
Timer.Enabled = false;
}
private void Scroll(object source, ElapsedEventArgs e)
{
Calendar.SmoothScrollBy (0, ScrollDistance);
}
}
Change the StartScroll value and the Timer.Interval to adjust the speed of the scroll.
I have modified answer of Tiago A.
I faced the same problem and the solution from Tiago A was small and easy but have some limitation so if others require this may help.
Thanks to Tiago A.
case DragEvent.ACTION_DRAG_LOCATION:
ScrollView myScrollView =findViewById(R.id.myScrollView);
int topOfDropZone = myScrollView.getChildAt(0).getTop();
int bottomOfDropZone = myScrollView.getChildAt(0).getBottom();
int scrollY = myScrollView.getScrollY();
int scrollViewHeight = myScrollView.getMeasuredHeight();
if (Math.round(event.getY()) > scrollViewHeight - (scrollViewHeight / 45))
if (bottomOfDropZone > (scrollY + scrollViewHeight - 100))
myScrollView.smoothScrollBy(0, 30);
if (Math.round(event.getY()) < (scrollViewHeight / 45))
if (topOfDropZone < (scrollY + 100))
myScrollView.smoothScrollBy(0, -30);
return true;
I want to zoom text that is displayed at center of screen as per user choice. How can I achieve this ?
Using pinch multitouch cannot be tested on emulator and I want something that I can test on Android emulator.
Can I use zoom in and out controls to control only text view for my layout ?
Or Can I use webview to contain a text as webview has default zoom in out buttons ?
Can I use zoom in and out controls to
control only text view for my layout ?
There is no built-in support for that. You can probably achieve this effect yourself by drawing the text using the 2D graphics APIs (Canvas) and touch events. Or, intercept touch events on a TextView and change the font size of the text.
This is my answer for that
public class Songs extends SherlockActivity implements OnTouchListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_songs);
context = this;
sett = new SettRenderingEngine(context);
Intent i = getIntent();
song = i.getStringExtra("song");
singer = i.getStringExtra("singer");
lyrics = i.getStringExtra("lyrics");
txt_song_title = (TextViewPlus) findViewById(R.id.song_title);
txt_singer = (TextViewPlus) findViewById(R.id.singer);
txt_song_lyrics = (TextViewPlus) findViewById(R.id.song_lyrics);
txt_song_title.setText(sett.getSettString(song));
txt_singer.setText(sett.getSettString(singer));
txt_song_lyrics.setText(sett.getSettString(lyrics));
txt_song_lyrics.setOnTouchListener(this);
scaleGestureDetector = new ScaleGestureDetector(this,
new simpleOnScaleGestureListener());
}
public class simpleOnScaleGestureListener extends
SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
float size = txt_song_lyrics.getTextSize();
float factor = detector.getScaleFactor();
float product = size * factor;
txt_song_lyrics.setTextSize(TypedValue.COMPLEX_UNIT_PX, product);
size = txt_song_lyrics.getTextSize();
return true;
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
scaleGestureDetector.onTouchEvent(event);
return true;
}
}
For Zoom In Zoom Out
public class ZoomControls extends AppCompatActivity
{
Button zoomin, zoomout;
TextView text;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zoomcontrols);
zoomin = (Button) findViewById(R.id.zoomin);
zoomout = (Button) findViewById(R.id.zoomout);
text = (TextView) findViewById(R.id.text);
zoomin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
float x = text.getScaleX();
float y = text.getScaleY();
text.setScaleX((float) (x + 1));
text.setScaleY((float) (y + 1));
}
});
zoomout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
float x1 = text.getScaleX();
float y1 = text.getScaleY();
text.setScaleX((float) (x1 - 1));
text.setScaleY((float) (y1 - 1));
}
});
}
}