I have been looking all over SOF and online tutorials, but for some reason I still can't get it to work. I want to implement a drag and drop functionality in my game. Here is the activity:
I want to be able to drag and drop the 4 shapes in the bottom. If the correct shape fits, I want the shape with the "?" to change into the correct shape. Can someone show me how I can do this?
Here is my code:
public class SecondActivity extends AppCompatActivity {
int n;
ImageView shape1, shape2, shape3, shape4, guessShape;
ImageButton exit;
private android.widget.RelativeLayout.LayoutParams layoutParams;
Random rand = new Random();
ImageView[] shapes = new ImageView[4];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
//declare each imageview
shape1 = (ImageView) findViewById(R.id.shape1);
shape2 = (ImageView) findViewById(R.id.shape2);
shape3 = (ImageView) findViewById(R.id.shape3);
shape4 = (ImageView) findViewById(R.id.shape4);
guessShape = (ImageView) findViewById(R.id.guessShape);
exit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
finish();
System.exit(0);
}
});
//add each imageView to the shapes[] array
shapes[0] = shape1;
shapes[1] = shape2;
shapes[2] = shape3;
shapes[3] = shape4;
//store all the shapes in an array
int[] images = new int[]{R.drawable.img_0, R.drawable.img_1, R.drawable.img_2, R.drawable.img_3, R.drawable.img_4,
R.drawable.img_5, R.drawable.img_6, R.drawable.img_7, R.drawable.img_8, R.drawable.img_9, R.drawable.img_10,
R.drawable.img_11, R.drawable.img_12, R.drawable.img_13, R.drawable.img_14, R.drawable.img_15, R.drawable.img_16,
R.drawable.img_17};
//store all the guessShapes in an array
int[] outlines = new int[]{R.drawable.outline_0, R.drawable.outline_1, R.drawable.outline_2,
R.drawable.outline_3, R.drawable.outline_4, R.drawable.outline_5, R.drawable.outline_6,
R.drawable.outline_7, R.drawable.outline_8, R.drawable.outline_9, R.drawable.outline_10,
R.drawable.outline_11, R.drawable.outline_12, R.drawable.outline_13, R.drawable.outline_14,
R.drawable.outline_15, R.drawable.outline_16, R.drawable.outline_17};
//generate 4 random images from the array's and ensure that they don't match each other
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 18; i++) {
list.add(new Integer(i));
}
Collections.shuffle(list);
int whichImg = (int) Math.round((Math.random() * 4));
int img1 = list.get(0);
int img2 = list.get(1);
int img3 = list.get(2);
int img4 = list.get(3);
if (whichImg == 1) {
whichImg = img1;
} else if (whichImg == 2) {
whichImg = img2;
} else if (whichImg == 3) {
whichImg = img3;
} else {
whichImg = img4;
}
int outlineID = outlines[whichImg];
//set the shape in each imageview
guessShape.setBackgroundResource(outlineID);
shape1.setBackgroundResource(images[img1]);
shape2.setBackgroundResource(images[img2]);
shape3.setBackgroundResource(images[img3]);
shape4.setBackgroundResource(images[img4]);
//ensures that 1/4 shape has the guess shape correspondence
final Object currentBackground = guessShape.getBackground().getConstantState();
//for loop to have the guess shape and 1/4 shapes to match
for (int i = 0; i < 18; i++) {
if (currentBackground.equals(getResourceID("outline_" + i, "drawable", getApplicationContext()))) {
int random = new Random().nextInt(shapes.length);
shapes[random].setBackgroundResource(getResourceID("img_" + i, "drawable", getApplicationContext()));
}
//set tags for each view
guessShape.setTag("gShape");
shape1.setTag("S_1");
shape2.setTag("S_2");
shape3.setTag("S_3");
shape4.setTag("S_4");
}
}
//method to get the ID of an image in drawable folder
protected final static int getResourceID(final String resName, final String resType, final Context ctx)
{
final int ResourceID =
ctx.getResources().getIdentifier(resName, resType,
ctx.getApplicationInfo().packageName);
if (ResourceID == 0)
{
throw new IllegalArgumentException
(
"No resource string found with name " + resName
);
}
else
{
return ResourceID;
}
}
}
Although you were not clear enough.
Try this, First make a class that implements onTouchListener
private final class MyTouchListener implements OnTouchListener {
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
ClipData data = ClipData.newPlainText("", "");
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(
view);
view.startDrag(data, shadowBuilder, view, 0);
view.setVisibility(View.INVISIBLE);
return true;
} else {
return false;
}
}
}
Then define a drag listener
class MyDragListener implements OnDragListener {
Drawable enterShape = getResources().getDrawable(
R.drawable.shape_droptarget);
Drawable normalShape = getResources().getDrawable(R.drawable.shape);
#Override
public boolean onDrag(View v, DragEvent event) {
int action = event.getAction();
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
// do nothing
break;
case DragEvent.ACTION_DRAG_ENTERED:
v.setBackgroundDrawable(enterShape);
break;
case DragEvent.ACTION_DRAG_EXITED:
v.setBackgroundDrawable(normalShape);
break;
case DragEvent.ACTION_DROP:
// Dropped, reassign View to ViewGroup
View view = (View) event.getLocalState();
ViewGroup owner = (ViewGroup) view.getParent();
owner.removeView(view);
LinearLayout container = (LinearLayout) v;
container.addView(view);
view.setVisibility(View.VISIBLE);
break;
case DragEvent.ACTION_DRAG_ENDED:
v.setBackgroundDrawable(normalShape);
default:
break;
}
return true;
}
}
Now simply use these lines
findViewById(R.id.myimage1).setOnTouchListener(new MyTouchListener());
and
findViewById(R.id.bottomleft).setOnDragListener(new MyDragListener());
Here are some tutorials that might help you
Tutorialpoint
Link 2
Related
I read article "Listview slide to remove" and now want to implement "Listview to Highlight" think, so basically I want to change the background color of the selected row. The problem is when I highlight one row it automatically highlight another invisible row. (I need to scroll down to see it)
Here is my code (actually not mine):
MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view_deletion);
mListView = (ListView) findViewById(R.id.listview);
mainView = (LinearLayout) findViewById(R.id.listViewBackground1);
final ArrayList<String> cheeseList = new ArrayList<String>();
for (int i = 0; i < Cheeses.sCheeseStrings.length; ++i) {
cheeseList.add(Cheeses.sCheeseStrings[i]);
}
mAdapter = new StableArrayAdapter(this,R.layout.opaque_text_view, cheeseList, mTouchListener);
mListView.setAdapter(mAdapter);
}
private View.OnTouchListener mTouchListener = new View.OnTouchListener() {
float mDownX;
private int mSwipeSlop = -1;
#Override
public boolean onTouch(final View v, MotionEvent event) {
if (mSwipeSlop < 0) {
mSwipeSlop = ViewConfiguration.get(ListViewRemovalAnimation.this).
getScaledTouchSlop();
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (mItemPressed) {
return false;
}
mItemPressed = true;
mDownX = event.getX();
break;
case MotionEvent.ACTION_CANCEL:
v.setTranslationX(0);
mItemPressed = false;
break;
case MotionEvent.ACTION_MOVE:
{
float x = event.getX() + v.getTranslationX();
float deltaX = x - mDownX;
float deltaXAbs = Math.abs(deltaX);
if(deltaX > 0.0) {
mainView.setBackgroundColor(Color.GREEN);
}
else {
mainView.setBackgroundColor(Color.RED);
}
if (!mSwiping) {
if (deltaXAbs > mSwipeSlop) {
mSwiping = true;
mListView.requestDisallowInterceptTouchEvent(true);
}
}
if (mSwiping) {
v.setTranslationX((x - mDownX));
}
}
break;
case MotionEvent.ACTION_UP:
{if (mSwiping) {
float x = event.getX() + v.getTranslationX();
float deltaX = x - mDownX;
float deltaXAbs = Math.abs(deltaX);
float fractionCovered;
float endX;
final boolean remove;
final boolean removeOr;
if (deltaXAbs > v.getWidth() / 4) {
// Greater than a quarter of the width - animate it out
fractionCovered = deltaXAbs / v.getWidth();
endX = deltaX < 0 ? -v.getWidth() : v.getWidth();
remove = true;
} else {
// Not far enough - animate it back
fractionCovered = 1 - (deltaXAbs / v.getWidth());
endX = 0;
remove = false;
}
removeOr = (deltaX > 0 ? true : false);
long duration = (int) ((1 - fractionCovered) * SWIPE_DURATION);
mListView.setEnabled(false);
v.animate().setDuration(duration).translationX(endX).
withEndAction(new Runnable() {
#Override
public void run() {
v.setTranslationX(0);
if (remove) {
//int position = mListView.getPositionForView(v);
//mAdapter.remove(mAdapter.getItem(position));
animateRemoval(mListView, v, removeOr);
} else {
mSwiping = false;
mListView.setEnabled(true);
}
}
});
}
}
mItemPressed = false;
break;
default:
return false;
}
return true;
}
};
private void animateRemoval(final ListView listview, View viewToRemove, boolean removeOr) {
int firstVisiblePosition = listview.getFirstVisiblePosition(); //first visible position in listview
for (int i = 0; i < listview.getChildCount(); ++i) { // iterate 11 visible elements
View child = listview.getChildAt(i); // current visible element
if (child != viewToRemove) { // if the current item is not the one we need to remove
int position = firstVisiblePosition + i; // relative index
long itemId = mAdapter.getItemId(position); // global index (constant)
mItemIdTopMap.put(itemId, child.getTop()); // putto the map
}
}
int position = mListView.getPositionForView(viewToRemove); // position to remove from listview (relative)
if(removeOr == false) mAdapter.remove(mAdapter.getItem(position));
else {
//Log.w("----", "sample");
viewToRemove.setBackgroundColor(Color.GREEN);
}
//
//
//
//SAVE TO THE MAP AND REMOVE FROM ADAPTER
//
//
//
final ViewTreeObserver observer = listview.getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
observer.removeOnPreDrawListener(this); // remove previous callback
boolean firstAnimation = true; // flag for animation algo
int firstVisiblePosition = listview.getFirstVisiblePosition(); //first visible view index
for (int i = 0; i < listview.getChildCount(); ++i) { //iterate 11 visible elements
final View child = listview.getChildAt(i); // current view (by child)
int position = firstVisiblePosition + i; // relative index of item
long itemId = mAdapter.getItemId(position); // global index of item (constant)
Integer startTop = mItemIdTopMap.get(itemId); // top position of global item
int top = child.getTop(); // top position of current item
/*
If we deleted the element from visible listview area, then we have new element
from non-visible listview area. That is the situation when starTop == null (if
top position of global item "itemId" was in unvisible area before deletion. )
*/
if (startTop != null) { // item was in visible area before the deletion
if (startTop != top) { // if startop != top (when the deleted element was after the current)
int delta = startTop - top; // initial top
child.setTranslationY(delta); // set init top
child.animate().setDuration(MOVE_DURATION).translationY(0); // animate to 0
if (firstAnimation) { // if it is the first animation
child.animate().withEndAction(new Runnable() { // call end action
public void run() {
mSwiping = false; // so we can swipe again
mListView.setEnabled(true); // enable listview touch events
}
});
firstAnimation = false; //
}
}
}
else {
int childHeight = child.getHeight() + listview.getDividerHeight(); // height of listview child view
startTop = top + childHeight; // new top for currently unvisible element
int delta = startTop - top; // initial top
child.setTranslationY(delta); // set init top
child.animate().setDuration(MOVE_DURATION).translationY(0); // animate to top 0
/*
if it is the first animation. It happens whwn we removed last visible element from listview.
So we didn't use firstAnimation flag.
*/
if (firstAnimation) { // if it is the first animation
child.animate().withEndAction(new Runnable() { // call end action
public void run() {
mSwiping = false; // so we can swipe again
mListView.setEnabled(true); // enable listview touch events
}
});
firstAnimation = false; //
}
}
}
mItemIdTopMap.clear(); // free memory
return true;
}
});
}
StableArrayAdapter:
public class StableArrayAdapter extends ArrayAdapter<String> {
HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
View.OnTouchListener mTouchListener;
public StableArrayAdapter(Context context, int textViewResourceId,
List<String> objects, View.OnTouchListener listener) {
super(context, textViewResourceId, objects);
mTouchListener = listener;
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i), i);
}
}
#Override
public long getItemId(int position) {
String item = getItem(position);
return mIdMap.get(item);
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
view.setOnTouchListener(mTouchListener);
return view;
}
}
All you should need to do is tell the ListView to use a different background for selected items:
https://developer.android.com/reference/android/widget/AbsListView.html#attr_android:listSelector
I have created a DialogFragment class that I need to show from within a onDragListener. I tried a regular AlertDialog but couldn't get the activity context to be static. I tried adding this to my onDragListener class and to my CustomLayoutClass but it says that getSupportFragmentManager() cannot be referenced from a static method or that it cannot be resolved.
public static void showScoopDialog() {
FragmentManager fm = getSupportFragmentManager();
ScoopSizeDialog editNameDialogFragment = ScoopSizeDialog.newInstance("Some Title");
editNameDialogFragment.show(fm, "fragment_edit_name");
}
This is my custom onDragListener class. I need to show a dialog with edittext when the user drops an image:
public class ChoiceDragListener implements View.OnDragListener {
boolean DEBUG = true;
Context context;
public String TAG = "Drag Layout:";
public ChoiceDragListener(Context context) {
this.context = context;
}
#Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
if(DEBUG) Log.v("here","drag started");
break;
case DragEvent.ACTION_DRAG_ENTERED:
break;
case DragEvent.ACTION_DRAG_LOCATION:
int mCurX = (int) event.getX();
int mCurY = (int) event.getY();
if (DEBUG) Log.v("Cur(X, Y) : " ,"here ::" + mCurX + ", " + mCurY );
break;
case DragEvent.ACTION_DRAG_EXITED:
if (DEBUG)
Log.v("here","drag exits");
break;
case DragEvent.ACTION_DROP:
//handle the dragged view being dropped over a drop view
View view = (View) event.getLocalState();
ClipData cd = event.getClipData();
ClipData.Item item = cd.getItemAt(0);
String resp = item.coerceToText(context).toString();
//view dragged item is being dropped on
ImageView dropTarget = (ImageView) v;
//view being dragged and dropped
ImageView dropped = (ImageView) view;
dropped.setEnabled(false);
//if an item has already been dropped here, there will be a tag
Object tag = dropTarget.getTag();
CreateProd.nsList.add(dropped.getTag().toString());
Log.d(TAG, dropped.getTag().toString() + "added to list");
//if there is already an item here, set it back visible in its original place
if (tag != null) {
//the tag is the view id already dropped here
int existingID = (Integer)tag;
//set the original view visible again
((Activity) context).findViewById(existingID).setVisibility(View.VISIBLE);
}
break;
case DragEvent.ACTION_DRAG_ENDED:
if (DEBUG) Log.i("drag event", "ended::" + ChoiceTouchListener.offsetX + "," + ChoiceTouchListener.offsetY);
/**
* returning false so that goes to parentView onDrag function
*/
return false;
//break;
default:
break;
}
return true;
}
}
And this is my custom layout:
public class DragLayout extends RelativeLayout {
boolean DEBUG = true;
AnimationDrawable blenderAnim;
Handler handlerAnim2;
Context context;
private int dimensionInPixel = 200;
int screenWidth,screenHeight;
static float up_x=0,up_y=0;
boolean mIsScrolling = false;
public DragLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
this.context = context;
//not to include in main program
getDimensionsofScreen();
setLayout();
setViews();
}
private void setLayout() {
// set according to parent layout (not according to current layout)
RelativeLayout.LayoutParams rLp = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
rLp.topMargin = 2 * (screenHeight / 25); // calculating 1/10 of 4/5
// screen
this.setLayoutParams(rLp);
}
void setViews() {
ImageView img2 = new ImageView(context);
int dimensionInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensionInPixel, getResources().getDisplayMetrics());
RelativeLayout.LayoutParams rLp = new RelativeLayout.LayoutParams(
(screenWidth / 5), (screenHeight / 5));
rLp.topMargin = (screenHeight / 10);
rLp.leftMargin = (4*screenWidth / 10);
rLp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
img2.setLayoutParams(rLp);
img2.getLayoutParams().height = dimensionInDp;
img2.getLayoutParams().width = dimensionInDp;
img2.setImageDrawable(getResources().getDrawable(R.drawable.blender_anim));
img2.setOnDragListener(new ChoiceDragListener(context));
this.addView(img2);
blenderAnim = (AnimationDrawable)img2.getDrawable();
blenderAnim.setOneShot(true);
blenderAnim.stop();
}
public ArrayList<Integer> getDimensionsofScreen() {
//metrics that holds the value of height and width
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();;
ArrayList<Integer> vals = new ArrayList<Integer>();
vals.add(displayMetrics.widthPixels);
vals.add(displayMetrics.heightPixels);
screenHeight = displayMetrics.heightPixels;
screenWidth = displayMetrics.widthPixels;
return vals;
}
#SuppressLint("NewApi")
#Override
public boolean onDragEvent(DragEvent event) {
int mCurX = (int) event.getX();
int mCurY = (int) event.getY();
if (event.getAction() == DragEvent.ACTION_DRAG_STARTED || event.getAction() == DragEvent.ACTION_DRAG_ENTERED) {
if (blenderAnim.isRunning()) {
blenderAnim.stop();
} else {
blenderAnim.run();
handlerAnim2 = new Handler();
handlerAnim2.postDelayed(
new Runnable() {
#Override
public void run() {
blenderAnim.stop();
}},
getAnimationDuration(blenderAnim));
}
}
if (event.getAction() == DragEvent.ACTION_DROP || event.getAction() == DragEvent.ACTION_DRAG_EXITED) {
if (blenderAnim.isRunning()) {
blenderAnim.stop();
} else {
blenderAnim.run();
handlerAnim2 = new Handler();
handlerAnim2.postDelayed(
new Runnable(){
#Override
public void run() {
blenderAnim.stop();
}},
getAnimationDuration(blenderAnim));
}
Log.v("here", "it is :: " + mCurX + ", " + mCurY);
View view1 = (View) event.getLocalState();
view1.setVisibility(View.VISIBLE);
ObjectAnimator animationx = ObjectAnimator.ofFloat(view1,"translationX", mCurX - ChoiceTouchListener.offsetX-(screenWidth / 10),0.0f);
ObjectAnimator animationy = ObjectAnimator.ofFloat(view1, "translationY", mCurY - ChoiceTouchListener.offsetY - (screenHeight / 10), 0.0f);
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(500);
animSet.playTogether(animationx,animationy);
animSet.start();
}
if (event.getAction() == DragEvent.ACTION_DROP || event.getAction() == DragEvent.ACTION_DRAG_ENDED){
if (blenderAnim.isRunning()) {
blenderAnim.stop();
}
}
return true;
}
private int getAnimationDuration(AnimationDrawable src) {
int dur = 0;
for (int i = 0; i<src.getNumberOfFrames(); i++) {
dur += src.getDuration(i);
}
return dur;
}
private void showScoopDialog() {
FragmentManager fm = getSupportFragmentManager();
ScoopSizeDialog editNameDialogFragment = ScoopSizeDialog.newInstance("Some Title");
editNameDialogFragment.show(fm, "fragment_edit_name");
}
}
I am having nearly 500+ images in Imageview inside Horizontalscrollview. If i am selecting an image then I am marking it as selected. If I am selecting any other images in the view, it should be un-select and newly clicked image should have to be selected. How could I can achieve it?
for (int i = 0; i < Home.arr_category_item_list.size(); i++) {
ImageView circleImageView = new ImageView(getActivity());
imageLoader.get(Home.arr_category_item_list.get(i).get(Variables.EST_CATEGORY_ITEM_IMAGE), ImageLoader.getImageListener(circleImageView, R.drawable.defaultimage, R.drawable.defaultimage));
circleImageView.setTag(Integer.parseInt(Home.arr_category_item_list.get(i).get(Variables.EST_CATEGORY_ITEM_ID)));
circleImageView.setLayoutParams(params);
lnr_category_item.addView(circleImageView);
}
Please check the image attached. At the bottom of the screen there is an Image view. So user will have option to select only one image at a time.
Now this is some really old code, hope it still works.
Note: there may be a thing or two missing, but you can get the idea from this implementation
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import yourpackage.R;
//Creataed by Bojan Kseneman on 14.8.2013
public class CustomCheckBox extends ImageView {
private boolean isChecked;
private boolean isImageShown;
private boolean useCustomClickListener;
//private String android_xmlns = "http://schemas.android.com/apk/res/android";
private String app_xmlns;
private int checkboxOnResID;
private int checkboxOffResID;
private int checkboxDisabledOnResID;
private int checkboxDisabledOffResID;
//private int imageHeight;
//private int imageWidth;
public CustomCheckBox(Context context, AttributeSet attrs) {
super(context, attrs);
app_xmlns = new StringBuilder("http://schemas.android.com/apk/res/" + context.getPackageName()).toString();
init(attrs);
}
private void init(AttributeSet attrs) {
checkboxOnResID = attrs.getAttributeResourceValue(app_xmlns, "resourceChecked", R.drawable.round_checkbox_on);
checkboxOffResID = attrs.getAttributeResourceValue(app_xmlns, "resourceNotChecked", R.drawable.round_checkbox_off);
checkboxDisabledOnResID = attrs.getAttributeResourceValue(app_xmlns, "resourceDisabledOn", R.drawable.round_checkbox_off);
checkboxDisabledOffResID = attrs.getAttributeResourceValue(app_xmlns, "resourceDisabledOff", R.drawable.round_checkbox_off);
useCustomClickListener = attrs.getAttributeBooleanValue(app_xmlns, "customClickEvent", false);
if (useCustomClickListener)
this.setOnTouchListener(new CboxTouchListener());
else {
this.setOnTouchListener(new NormalClickListener());
}
if (!hasOnClickListener()) {
/**
* assign a new onClick listener so we get desired onClick sound
* effect (because we call it) this is opposite to how android
* behaves, where you don't hear the sound if there is not
* onClickListener assigned
*/
this.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
}
private boolean hasOnClickListener() {
try {
if (android.os.Build.VERSION.SDK_INT >= 14) {
//the information is inside ListenerInfo
java.lang.reflect.Field listenerInfoField = null;
listenerInfoField = Class.forName("android.view.View").getDeclaredField("mListenerInfo");
if (listenerInfoField != null)
listenerInfoField.setAccessible(true);
Object mOnClickListener = null;
mOnClickListener = listenerInfoField.get(this); //get from view object, in this case this is this
// get the field mOnClickListener, that holds the listener and cast it to a listener
java.lang.reflect.Field listenerField = null;
listenerField = Class.forName("android.view.View$ListenerInfo").getDeclaredField("mOnClickListener");
//View.OnClickListener myListener = (View.OnClickListener) listenerField.get(myLiObject);
return (listenerField.get(mOnClickListener) != null);
}
else {
//directly in View
java.lang.reflect.Field f = Class.forName("android.view.View").getDeclaredField("mOnClickListener");
return (f.get(this) != null);
}
}
catch (Exception e) {
return false;
}
}
// private void setScaledDownImage(int resID) {
// this.setImageBitmap(CommonMethods.decodeSampledBitmapFromResource(getContext(), resID, imageWidth, imageHeight));
// }
public boolean isChecked() {
return (isChecked && this.isEnabled());
}
public void setChecked(boolean isChecked) {
if (this.isEnabled())
setCheckedIgnoreEnabled(isChecked);
else
this.setEnabled(false);
}
public void setCheckedIgnoreEnabled(boolean isChecked) {
if ((this.isChecked != isChecked) || !isImageShown) {
this.isChecked = isChecked;
if (isChecked)
setImageResource(checkboxOnResID);
else
setImageResource(checkboxOffResID);
}
}
#Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
if (enabled)
setChecked(isChecked);
else {
int resID = isChecked ? checkboxDisabledOnResID : checkboxDisabledOffResID;
setImageResource(resID);
}
}
public void setCheckedAndEnabled(boolean isChecked, boolean isEnabled) {
setCheckedIgnoreEnabled(isChecked);
setEnabled(isEnabled);
}
public void toggle() {
setChecked(!isChecked);
}
public void toggleWithClick() {
toggle();
this.performClick();
}
public void toggleWithSilentClick() {
//v.playSoundEffect(android.view.SoundEffectConstants.CLICK);
boolean currentState = this.isSoundEffectsEnabled();
this.setSoundEffectsEnabled(false);
toggleWithClick();
this.setSoundEffectsEnabled(currentState);
}
private class CboxTouchListener extends ImageBoundClickListener {
#Override
public void doSomething() {
super.doSomething();
setChecked(!isChecked);
CustomCheckBox.this.performClick();
}
}
private class NormalClickListener extends MyOnClickListener {
#Override
public void doSomething() {
super.doSomething();
setChecked(!isChecked);
CustomCheckBox.this.performClick();
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//this.imageWidth = MeasureSpec.getSize(widthMeasureSpec);
//this.imageHeight = MeasureSpec.getSize(heightMeasureSpec);
if (!isImageShown) {
setChecked(isChecked);
isImageShown = !isImageShown;
}
}
}
I used this click listener, since I was using some round images and I didn't want to trigger the click events when the user clicked on the transparent part of the image.
public abstract class ImageBoundClickListener implements android.view.View.OnTouchListener {
private String TAG = "ImageBoundsTouchListener";
private boolean shouldTriggerAction = false;
Rect allowedArea;
#Override
public boolean onTouch(View v, MotionEvent event) {
//let's us detect only clicks on the part where actual image is and not where the ImageView is
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
float[] eventXY = new float[] { event.getX(), event.getY() };
allowedArea = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
android.graphics.Matrix invertMatrix = new android.graphics.Matrix();
ImageView iv = (ImageView) v;
iv.getImageMatrix().invert(invertMatrix);
invertMatrix.mapPoints(eventXY);
int x = (int) eventXY[0];
int y = (int) eventXY[1];
Drawable imgDrawable = iv.getDrawable();
Bitmap bitmap = ((BitmapDrawable) imgDrawable).getBitmap();
//Limit x,y within the bitmap
if (x < 0)
x = 0;
else if (x > (bitmap.getWidth() - 1))
x = bitmap.getWidth() - 1;
if (y < 0)
y = 0;
else if (y > bitmap.getHeight() - 1)
y = bitmap.getHeight() - 1;
int touchedRGB = bitmap.getPixel(x, y);
//is transparent?
shouldTriggerAction = (touchedRGB == 0) ? false : true;
return true;
case MotionEvent.ACTION_MOVE:
if (!allowedArea.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY()))
//the user went out of the user area
shouldTriggerAction = false;
return true;
case MotionEvent.ACTION_UP:
//finger is no longer on screen
if (shouldTriggerAction)
doSomething();
return true;
default:
return false;
}
}
public void doSomething() {
}
}
I apologize for my English. I have a problem.
I use a listeners LongClick and TouchListener.
In the long click - the view is removed and the parent view is inserted into the other parent.
Touch stops working, because there was a change parent.
How do I keep TouchListener to View?
static boolean drag = false;
static View parent;
static OnLongClickListener olcl = new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
if(!drag) {
parent = (View) v.getParent();
int[] loc = {0, 0};
v.getLocationOnScreen(loc);
((ViewGroup) parent).removeView(v);
Main.mainRelative.addView(v);
RelativeLayout.LayoutParams par = (LayoutParams) v.getLayoutParams();
par.leftMargin = loc[0];
par.topMargin = loc[1];
v.setLayoutParams(par);
drag = true;
return true;
}
return false;
}
};
static OnTouchListener otl = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(v.getParent() != null && v.getParent() == Main.mainRelative) {
//!!!!!!!!!!!!!
RelativeLayout.LayoutParams par = (LayoutParams) v.getLayoutParams();
par.leftMargin = (int) (event.getRawX() - v.getWidth()/2);
par.topMargin = (int) (event.getRawY() - v.getHeight()/1.2);
v.setLayoutParams(par);
for(int y = 0; y < Main.radioGroupLeftMain.getChildCount(); y++) {
RadioButton rb = (RadioButton) ((ViewGroup) Main.radioGroupLeftMain.getChildAt(y)).getChildAt(0);
if(checkHit((int)event.getRawX(), (int)event.getRawY(), rb)) {
rb.setChecked(true);
} else {
rb.setChecked(false);
}
if(event.getAction() == MotionEvent.ACTION_UP) {
try { ((ViewGroup) v.getParent()).removeView(v); } catch(Exception e) {};
if(v.getVisibility() == View.VISIBLE) {
((ViewGroup) parent).addView(v);
}
drag = false;
}
}
}
return false;
}
};
public static boolean checkHit(int x, int y, View v) {
int[] loc = {0, 0};
v.getLocationOnScreen(loc);
Rect rv = new Rect(loc[0], loc[1], loc[0]+v.getWidth(), loc[1]+v.getHeight());
return rv.contains(x, y);
}
when your are going to add view Main.mainRelative.addView(v);
before this create new View, initialize with this view v like View vv = v
then again set touch listener vv.setOnTouchLIstener(ot1);
try this it should work...
I have a drag and drop game. The user should choose the correct shape to drag and drop onto the box. I followed this tutorial here When the user has dragged the wrong object, it won't be displaying WRONG ANSWER yet. The warning should displayed when he drops it onto the basket object. I have tried this:
TextView objBasket, tx, timer;
int trial = 0;
TextView obj[] = new TextView[4];
int[] images = {
R.drawable.stage4_object1, // Correct Answer a
R.drawable.stage4_object2,
R.drawable.stage4_object3,
R.drawable.stage4_object4
};
List<TextView> iv = new ArrayList<TextView>();
String[] tagList = {"a","b","c","d"};
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.stage4_1);
// I created a custom countdown timer c/o Say
counter = new MyCount(30000,1000);
counter.start();
initControls();
getCorrectObject();
}
private void getCorrectObject() {
// TODO Auto-generated method stub
List<Integer> objects = new ArrayList<Integer>();
for(int arr : images){
objects.add(arr);
}
// Shuffle the collection
Collections.shuffle(objects);
iv.add((TextView) findViewById(R.id.txtStage4_object1));
iv.add((TextView) findViewById(R.id.txtStage4_object2));
iv.add((TextView) findViewById(R.id.txtStage4_object3));
iv.add((TextView) findViewById(R.id.txtStage4_object4));
Collections.shuffle(iv);
iv.get(0).setBackgroundResource(images[0]);
iv.get(1).setBackgroundResource(images[1]);
iv.get(2).setBackgroundResource(images[2]);
iv.get(3).setBackgroundResource(images[3]);
iv.get(0).setOnTouchListener(new ChoiceTouchListener());
iv.get(1).setOnTouchListener(new ChoiceTouchListener());
iv.get(2).setOnTouchListener(new ChoiceTouchListener());
iv.get(3).setOnTouchListener(new ChoiceTouchListener());
for (int i = 0; i < tagList.length; i++) {
iv.get(i).setTag(tagList[i]);
}
}
#SuppressLint("NewApi")
private class ChoiceTouchListener implements OnTouchListener {
#SuppressLint("NewApi")
#Override
public boolean onTouch(View v, MotionEvent motionEvent) {
// TODO Auto-generated method stub
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
//setup drag
ClipData data = ClipData.newPlainText("", "");
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
//start dragging the item touched
v.startDrag(data, shadowBuilder, v, 0);
return true;
}
else {
return false;
}
}
}
#SuppressLint("NewApi")
private class ChoiceDragListener implements OnDragListener {
#Override
public boolean onDrag(View v, DragEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
//no action necessary
break;
case DragEvent.ACTION_DRAG_ENTERED:
//no action necessary
break;
case DragEvent.ACTION_DRAG_EXITED:
//no action necessary
break;
case DragEvent.ACTION_DROP:
//handle the dragged view being dropped over a drop view
View view = (View) event.getLocalState();
//stop displaying the view where it was before it was dragged
view.setVisibility(View.INVISIBLE);
//view dragged item is being dropped on
TextView dropTarget = (TextView) v;
//view being dragged and dropped
TextView dropped = (TextView) view;
for (int i = 0; i < iv.size(); i++) {
final int k = i;
String tmp = "a";
if (tmp.equals(iv.get(k).getTag())) {
Log.i("result","CORRECT ANSWER: "+ tmp);
goToNextQuestion();
} else {
Log.i("result","WRONG ANSWER: "+ iv.get(k).getTag());
trial++;
guessedWrong();
playWrongSound();
}
}
break;
case DragEvent.ACTION_DRAG_ENDED:
//no action necessary
break;
default:
break;
}
return true;
}
}
But it won't go to the next question whenever I choose the correct object. What am I missing in here? I really need help to finish this game. Thanks in advance.
I think that I see two problems with your program.
You created your ChoiceDragListener class but you didn't register it with any of those items you wish to drag around. This appears to be missing from your getCorrectObject method.
iv.get(0).setOnDragListener(new ChoiceDragListener ());
iv.get(1).setOnDragListener(new ChoiceDragListener ());
iv.get(2).setOnDragListener(new ChoiceDragListener ());
iv.get(3).setOnDragListener(new ChoiceDragListener ());
The other problem that I see is with your ACTION_DROP case from your switch statement. First you get the TextView that the user has dropped but then you begin to cycle through all of your text views anyways. The code inside the ACTION_DROP case should look more like:
View view = (View) event.getLocalState();
view.setVisibility(View.INVISIBLE);
TextView dropTarget = (TextView) v;
TextView dropped = (TextView) view;
String temp = "a";
if(temp.equals(view.getTag()){
goToNextQuestion();
}else{
guessedWrong()
}