Detecting which views are touched within swipre over gridlayout - android

I am currently working on an application which should be able to detect which individual textviews in a gridlayout are touched. Goal is to set the background color of the touched views to a different color. I am creating the views like this:
for (int row = 1; row < 13; row++) {
for (int col=0; col<24; col++) {
TextView tv = new TextView(this);
GridLayout.LayoutParams params = new GridLayout.LayoutParams(GridLayout.spec(row), GridLayout.spec(col));
params.width = (int)(screenWidth / 24);
params.height = (int) (tenth_heigth * 8) / 12 ;
tv.setLayoutParams(params);
tv.setGravity(Gravity.CENTER);
tv.setBackgroundColor(Color.WHITE);
tv.setText("A");
tv.setTextAppearance(this, android.R.style.TextAppearance_Large);
gridLayout.addView(tv, params);
}
}
I tried to do this with an overridden onTouchEvent method within the activity, but so far I had no luck achieving my goal. What's the best way to do this?
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN :
// would like to set the background color of the touched view to blue
break;
case MotionEvent.ACTION_MOVE :
// would like to set the background color of the touched views to red
break;
case MotionEvent.ACTION_UP :
// set the background color to purple
break;
}
return super.onTouchEvent(event);
}
I would appreciate if someone could point me in the right direction. Thanks a lot!

Related

Android Drag and Drop ImageView into another ImageView

I'm stuck on this problem in Android Drag and Drop. I've already read the documentation and more than one question/answer here on stackoverflow .
The problem is that:
i've 3 ImageView that can i move inside another 3 ImageView, but when i start to drag one of the 3 ImageView i can drop it inside in just one ImageView area.
Here the code! . Basically i'll see active only the dropViewArancio area even if i drag the other ImageView.
What i want it's to have all the 3 area active where i can drop one of the 3 ImageView.
Thanks for the support!
An ImageView can't contain another View inside, only classes derived from ViewGroup can. Then you can move an ImageView over or behind another (depending on Z order) but not inside.
Here a working example of how to move all the views contained in a RelativeLayout using onTouch. I think that onDrag event applies better to drag and drop data items, not to move views. Hope it will help
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
private RelativeLayout mRelLay;
private float mInitialX, mInitialY;
private int mInitialLeft, mInitialTop;
private View mMovingView = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRelLay = (RelativeLayout) findViewById(R.id.relativeLayout);
for (int i = 0; i < mRelLay.getChildCount(); i++)
mRelLay.getChildAt(i).setOnTouchListener(this);
}
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
RelativeLayout.LayoutParams mLayoutParams;
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
mMovingView = view;
mLayoutParams = (RelativeLayout.LayoutParams) mMovingView.getLayoutParams();
mInitialX = motionEvent.getRawX();
mInitialY = motionEvent.getRawY();
mInitialLeft = mLayoutParams.leftMargin;
mInitialTop = mLayoutParams.topMargin;
break;
case MotionEvent.ACTION_MOVE:
if (mMovingView != null) {
mLayoutParams = (RelativeLayout.LayoutParams) mMovingView.getLayoutParams();
mLayoutParams.leftMargin = (int) (mInitialLeft + motionEvent.getRawX() - mInitialX);
mLayoutParams.topMargin = (int) (mInitialTop + motionEvent.getRawY() - mInitialY);
mMovingView.setLayoutParams(mLayoutParams);
}
break;
case MotionEvent.ACTION_UP:
mMovingView = null;
break;
}
return true;
}
}
So, i've solved my problem following this tutorial. Anyway my desire solution it's something similar this, the perfect way it's a mixing of tutorial and a previous link. Thanks all for help.

Img(ImageView) moving randomly within screen with onTouch onDrag listener

EDIT: Cliffnote of what i want accomplished
straight to the point,
My XML set up is has 2 linearview (top, bottom)
1. I want my img to stay within screen when moving
2. Moving continuously randomly
3. Have it clickable/draggable
4. Have the img get its new position and move whereever it is dropped (top or bottom)
Thank you.
Hello making an app (Android Studio) for autistic children (inspired by my autistic son). In my Activity i have 2 linear layout: Top and Bottom. The top is where 3/4 of my screen that has 4 images. The bottom is the targeted drop point where the "Answer" or img should be dropped.
I have an 4 img randomly created in a (via databaseFP iterated) but now i want those img to be moving randomly within screen (top screen) and drag them into a target drag box (bottom screen). Only 1 of four img is the correct "answer" so if its "incorrect" i want this img to return to its position MOVING all the while within screen until the "correct" img is chosen to the targeted drop box. That is all...Please Please help me i have read many and not like this specifically where it involves onTouch/onDrag listener and the img goes back to position if dragged.
So far all i have done is make the img move (it retains the on click and drag but when its incorrect it goes off screen) Pls see code below
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
int height = displaymetrics.heightPixels;
Random r = new Random();
int distance = 100; //the distance to move in pixels
int duration = 500; //the duration of the animation in ms
double direction = Math.random() * 2 * Math.PI;
int translationX = (int) (Math.cos(direction) * distance);
int translationY = (int) (Math.sin(direction) * distance);
int id2 = getResources().getIdentifier(myShuffledArray[0], "drawable", getPackageName());
image.setImageResource(id2);
image.animate().translationX(translationX - width).translationY(translationY - height).setDuration(duration).start();
I am a newbie but this would help my autistic son and this is a Thesis project for my college.
EDIT this is my ontouch/drag
public boolean onDrag(View v, DragEvent event) {
// TODO Auto-generated method stub
if(event.getAction()==DragEvent.ACTION_DROP){
//we want to make sure it is dropped only to left and right parent view
View view = (View)event.getLocalState();
//if(v.getId() == R.id.left_view || v.getId() == R.id.right_view){
if(view.getId() == R.id.box_view1){
ViewGroup source = (ViewGroup) view.getParent();
source.removeView(view);
LinearLayout target = (LinearLayout) v;
target.addView(view);
}
//make view visible as we set visibility to invisible while starting drag
view.setVisibility(View.VISIBLE);
}
return true;
}
#Override
public boolean onTouch(View view, MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction() == MotionEvent.ACTION_DOWN){
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(null, shadowBuilder, view, 0);
view.setVisibility(View.INVISIBLE);
return true;
}
return false;
}
I have found the solution posted on this website
https://blahti.wordpress.com/2011/01/17/moving-views-part-2/
Check it out for those who wants learn more on Views and Drag and Drop

Why RecyclerView Adapter doesn't instantly initialize its items on manual scroll?

I am using 2 RecyclerViews inside a Dialogue. One of the RecyclerView further uses a nested list inside it. Everything's alright till now (no height issues).
However, from the other RecyclerView, I drag an image/view and inside another RecyclerView i wish to drop it.
This functionality works fine but problem occurs here:
I usually highlight a particular Text area when the dragged image enters that area using DragListener's available Drag events (see image below):
So if I drag the image till "Customer Voice 5" Text header, it'll highlight.
When I drag it to the 5th item, it scrolls down (as coded inside DragListener using smoothScrollBy()) and 6th item with the header "Customer Voice 6" Text header is also visible, BUT it doesn't get highlighted. Neither it scrolls down further to show 7th completely, no code works on this item, as if RecyclerView hasn't yet updated/recognized this item inside it's onBindViewHolder(...) method.
Now I drop the dragged image elsewhere (no action) and again drag image to "Customer Header 6", it highlights! (and scrolls too) That means RecyclerView has updated it after I had dropped my image on the first run.
So while I drag, the Drag Listener's event ACTION_DRAG_LOCATION runs continuously and Recycler View seems to not able to take the control while this happens. So how to get both things DragListener and RecyclerViewAdapter, work together? [I am aware how RV uses the items from holder and re-uses it when invisible from to dirty view list]
I tried notifyDataSetChanged(); but doesn't help. Can't find any other thing on this. Maybe LinearLayoutManager might help but can't link it with my problem. Below are some code blocks from my RV adapter.
#Override
public void onBindViewHolder(MyHolder holder, int position) {
Log.d("Log","OnBindViewHolder"+position);
holder.customerVoiceTitle.setText(hashMap.get(position)); //Setting Header Text - "Customer Voice [position+1]"
holder.customerVoiceTitle.setId(position + 100); // Setting id to be able to detect each header while performing drag actions
holder.customerVoiceTitle.setOnDragListener(new MyDragListener());
customerVoiceMainHeaderText.setId(50); //Neglect this for the time being, this is also a part of the issue.
customerVoiceMainHeaderText.setOnDragListener(new MyDragListener());
holder.totalWorkLayoutListView.setId(position + 150); //ListView also is utilized to perform drag actions
holder.totalWorkLayoutListView.setOnDragListener(new MyDragListener());
UtilityClass.setListViewHeightBasedOnChildren(holder.totalWorkLayoutListView, "", ""); //To avoid height inflation issues
/* if(allFlag) {
customerVoiceWorkListCustomAdapter = new CustomerVoiceWorkListCustomAdapter(context, 5, true);
}
else if(!allFlag) {
customerVoiceWorkListCustomAdapter = new CustomerVoiceWorkListCustomAdapter(context, 5, false);
}*/
holder.totalWorkLayoutListView.setAdapter(customerVoiceWorkListCustomAdapter);
}
class MyDragListener implements View.OnDragListener {
Drawable normalShape = context.getResources().getDrawable(R.drawable.bg_fragment_header_with_border);
Drawable targetShape = context.getResources().getDrawable(R.drawable.target_shape);
#Override
public boolean onDrag(View v, DragEvent event) {
// Handles each of the expected events
switch (event.getAction()) {
//signal for the start of a drag and drop operation.
case DragEvent.ACTION_DRAG_STARTED:
// do nothing
break;
//the drag point has entered the bounding box of the View
case DragEvent.ACTION_DRAG_ENTERED:
if(v.getId() >= 100 && v.getId() < 150) //For Header Text only
v.setBackground(targetShape); //change the shape of the view
break;
//the user has moved the drag shadow outside the bounding box of the View
case DragEvent.ACTION_DRAG_EXITED:
if(v.getId() >= 100 && v.getId() < 150) //For Header Text only
v.setBackground(normalShape); //change the shape of the view back to normal
break;
//drag shadow has been released,the drag point is within the bounding box of the View
case DragEvent.ACTION_DROP:
Log.d("Log", "" + v.getId());
// if the view is the bottomlinear, we accept the drag item
if (v.getId() >= 100 && v.getId() < 150) { //For Header Text only. If dragged image is dropped some changes take place inside the list. Not IMP now
TextView workListHeaderText = (TextView) v;
LinearLayout containerLayout = (LinearLayout) workListHeaderText.getParent();
ListView workLayoutList = (ListView) containerLayout.getChildAt(1);
customerVoiceWorkListCustomAdapter = new CustomerVoiceWorkListCustomAdapter(context, 5, true);
workLayoutList.setAdapter(customerVoiceWorkListCustomAdapter);
} else if (v.getId() == 50) {
allFlag = true;
TextView workListRootHeaderText = (TextView) v;
LinearLayout layout = (LinearLayout) workListRootHeaderText.getParent();
RecyclerView technicianAllotment = (RecyclerView) layout.getChildAt(1);
int childCount = technicianAllotment.getChildCount();
for (int listCount = 0; listCount < childCount; listCount++) {
LinearLayout linearLayout = (LinearLayout) technicianAllotment.getChildAt(listCount);
ListView workLayoutList = (ListView) linearLayout.getChildAt(1);
customerVoiceWorkListCustomAdapter = new CustomerVoiceWorkListCustomAdapter(context, 5, true);
workLayoutList.setAdapter(customerVoiceWorkListCustomAdapter);
UtilityClass.setListViewHeightBasedOnChildren(workLayoutList, "", "");
}
}
break;
case DragEvent.ACTION_DRAG_LOCATION: //This is used to scroll when dragged image is dragged to the bottom of screen
LinearLayout dropZoneView = (LinearLayout) v.getParent();
int topOfDropZone = dropZoneView.getTop();
int bottomOfDropZone = dropZoneView.getBottom();
int scrollY = recyclerView.getScrollY();
int scrollViewHeight = recyclerView.getMeasuredHeight();
Log.d("Log", "location: Scroll Y: " + scrollY + " Scroll Y+Height: " + (scrollY + scrollViewHeight));
Log.d("Log", " top: " + topOfDropZone + " bottom: " + bottomOfDropZone);
if (bottomOfDropZone > (scrollY + scrollViewHeight - 100)) { //Manual scrolling down when image is dragged to bottom RV item
notifyDataSetChanged();
recyclerView.smoothScrollBy(0, 300);
}
if (topOfDropZone < (scrollY + 50)) //Manual scrolling up
recyclerView.smoothScrollBy(0, -50);
break;
//the drag and drop operation has concluded.
case DragEvent.ACTION_DRAG_ENDED:
if(v.getId() >= 100 && v.getId() < 150)
v.setBackground(normalShape); //go back to normal shape
default:
break;
}
return true;
}
}
EDIT
https://stackoverflow.com/a/14458111/4452231
This so far has worked. Got better solutions? Kindly suggest.

how to set textview dynamically according to numbers of strings

I am getting list of phone companies from web service and i have to set it to textview but the problem is i am not getting alignment as above image.How to achieve it.
From what I understand, you want to add text views one beside the other, but when they overflow (go out of the screen) the next text view should be placed in the next line.
Doing this is not trivial. Implementing something like this (optimally and correctly) requires understanding of how android draws views (onMeasure and onLayout). However if you do not care about efficiency that much (mainly because you are going to do it only for a small portion of the view) then here is my quick hack:
mContainer = (RelativeLayout) findViewById(R.id.container);
// first layout all the text views in a relative layout without any params set.
// this will let the system draw them independent of one another and calculate the
// width of each text view for us.
for (int i = 0; i < 10; i++) {
TextView tv = new TextView(getApplicationContext());
tv.setText("Text View " + i);
tv.setId(i+1);
tv.setPadding(10, 10, 20, 10);
mContainer.addView(tv);
}
// post a runnable on the layout which will do the layout again, but this time
// using the width of the individual text views, it will place them in correct position.
mContainer.post(new Runnable() {
#Override
public void run() {
int totalWidth = mContainer.getWidth();
// loop through each text view, and set its layout params
for (int i = 0; i < 10; i++) {
View child = mContainer.getChildAt(i);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// this text view can fit in the same row so lets place it relative to the previous one.
if(child.getWidth() < totalWidth) {
if(i > 0) { // i == 0 is in correct position
params.addRule(RelativeLayout.RIGHT_OF, mContainer.getChildAt(i-1).getId());
params.addRule(RelativeLayout.ALIGN_BOTTOM, mContainer.getChildAt(i-1).getId());
}
}
else {
// place it in the next row.
totalWidth = mContainer.getWidth();
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
params.addRule(RelativeLayout.BELOW, mContainer.getChildAt(i-1).getId());
}
child.setLayoutParams(params);
totalWidth = totalWidth - child.getWidth();
}
mContainer.requestLayout();
}
});
Basically, I let the system do the layout and measurement for me in the first round(s) of drawing. Then using the widths of each text view now available, I reset the layout params based on the wrapping logic and do the layout again.
Try it with text of different size, it will auto adjust. I would say this solution is pretty hacky but it works. If you are not satisfied with it take a look at this.
use
android:textAlignment="textStart"

How to select one particular view from group of view's?

For an app I need to develop, I need to be able to select one view from ViewGroup when user long press on the view have to popup an alert dialog, from that i will select options depending on the requirement, those are delete view and change background color for that particular view. I am creating different custom view's ( Custom view extends from View) and It has Touchlistener's. Dynamically attaching those view's to layout (RelativeLayout). Let us assume my layout having 3 views.
My questions:
I want to select one view from the list of available view's on the layout.
How to restrict the Custom view size instead of occupying full parent view.
I am facing Problem's like this: Look at this image if i set background color for custom view it look like this, Actually i was set for layout background color White here custom view occupies full screen. so, unable to see parent background color. Here problem with customview size, unable to restrict the customview size rather than occupying full parent view. even if i touch outside of my custom view, the touch listeners of custom view was triggering. i want to restrict those touch listeners upto my customview only..
.
Main Requirement:
Finally i want to be achieve like this below image, Now i am able to add more custom view's to layout,but unable to delete selected one. When i long press on any one of the view from the layout, it should popup one alert dialog with two buttons, if i select one selected view should be delete for another selection background color change.
RelaventCode: i am adding view to layout like this.
findViewById(R.id.line).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
CustomView drawView = new CustomView(context);
frame.addView(drawView);
}
});
and this is the customview :
public class CustomView extends View {
public CustomView (Context context) {
super(context);
init();
}
private void init() {
Paint paint = new Paint();
Paint pai = new Paint();
Path path = new Path();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
path.lineTo(50, 100);
}
#Override
public void onDraw(Canvas canvas) {
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(Top_Point.x, Top_Point.y);
path.lineTo(Right_Point.x, Right_Point.y);
path.lineTo(Left_Point.x, Left_Point.y);
path.lineTo(Top_Point.x, Top_Point.y);
path.close();
canvas.drawPath(path, Inner_Paint);
canvas.drawLine(Top_Point.x, Top_Point.y, Right_Point.x, Right_Point.y,
Lines_Paint);
canvas.drawLine(Right_Point.x, Right_Point.y, Left_Point.x,
Left_Point.y, Lines_Paint);
canvas.drawLine(Left_Point.x, Left_Point.y, Top_Point.x, Top_Point.y,
Lines_Paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
PointF NewP = new PointF(0, 0);
NewP.x = event.getX();
NewP.y = event.getY();
if (TopTouchArea.contains(event.getX(), event.getY())) {
currentTouch = TOUCH_TOP;
} else if (RightTouchArea.contains(event.getX(), event.getY())) {
currentTouch = TOUCH_RIGHT;
} else if (LeftTouchArea.contains(event.getX(), event.getY())) {
currentTouch = TOUCH_LEFT;
} else if (a) {
Translate_Point.x = event.getX();
Translate_Point.y = event.getY();
currentTouch = Inner_Touch;
return true; // Return false if user touches none of the
// corners
} else {
return false;
}
return true;
case MotionEvent.ACTION_MOVE:
switch (currentTouch) {
case TOUCH_TOP:
/* ------ */
case TOUCH_RIGHT:
/* ----- */
invalidate();
return true;
case TOUCH_LEFT:
/* ------ */
invalidate();
return true;
case Inner_Touch:
/* ------ */
invalidate();
return true;
}
return false;
case MotionEvent.ACTION_UP:
switch (currentTouch) {
case TOUCH_TOP:
/* ----- */
return true;
case TOUCH_RIGHT:
/* ----- */
return true;
case TOUCH_LEFT:
/* ----- */
return true;
case Inner_Touch:
/* ----- */
invalidate();
return true;
}
return false;
}
return super.onTouchEvent(event);
}
You should override onSizeChanged or onMeasure methods to let your ViewGroup know your view's size. And make sure that your view's width and height are both WRAP_CONTENT.
About touch event - problem here is that your view size is matching parent size, so it intercepts all touch events (since it returns true in onTouchEvent).
And here is a great tutorial
Add an OnLongClickListener to the customview before adding it to the view group.
To help identify the view at a higher level, you may want to set an identifier on the view using setTag("id", id);
If I understand you correctly, the view you add is too big and fills it's parent.
Isn't it sufficient to do something like
TwoPointsDraw drawView = new TwoPointsDraw(context);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
drawView.setLayoutParams(lp)
frame.addView(drawView);
Checkout this project, it might be helpful => Android multitouch controller, a simple multitouch pinch zoom library for Android.
Here is another example.

Categories

Resources