ImageView.setImageResource is not displaying correct drawable - java

I have this app, it's basically a 'make fun' app I made with a person's face and the ability to either shoot it with a pistol, automatic rifle, or grenade (more weapons to come :-)).
I have a Weapon class, with the following code. (I'm pretty new to java so forgive me if I failed to follow proven ways, or do things as efficiently as I should)
public class Weapon {
// Parent
public static MainActivity ma;
// Constants
public static final int BULLET_WIDTH = 97;
public static final int BULLET_HEIGHT = 92;
public static final int EXPLOD_WIDTH = 299;
public static final int EXPLOD_HEIGHT = 237;
public static final int PISTOL = 0;
public static final int RIFLE = 1;
public static final int GRENADE = 2;
protected static int[] position = {0, 0};
protected static RelativeLayout rl = null;
protected static MediaPlayer mp;
// Protected stuff
// Object variables.
protected int type;
protected int drawableEffect;
protected int soundEffect;
// Functionals
protected ImageView effectImage;
public void equipWeapon() {
// Clear any existing listeners and assign a new one.
MainActivity.mainImage.setOnTouchListener(null);
MainActivity.mainImage.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// Which weapon are we using?
switch (type) {
case Weapon.PISTOL:
case Weapon.GRENADE:
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Fire the weapon.
fireWeapon(v, event);
}
case Weapon.RIFLE:
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE: // This doesn't work ???
// Fire the weapon.
fireWeapon(v, event);
}
}
// perfomClick needed.
return v.performClick();
}
});
}
public void fireWeapon(View v, MotionEvent event) {
// Reference the layout.
Weapon.rl = (RelativeLayout)Weapon.ma.findViewById(R.id.relativeLayout);
// Define properties.
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
// Get the touch position.
Weapon.position[0] = (int)event.getX() - ((type == Weapon.PISTOL || type == Weapon.RIFLE) ? Weapon.BULLET_WIDTH:Weapon.EXPLOD_WIDTH);
Weapon.position[1] = (int)event.getY() - ((type == Weapon.PISTOL || type == Weapon.RIFLE) ? Weapon.BULLET_HEIGHT:Weapon.EXPLOD_HEIGHT);
// Set the position.
lp.setMargins(Weapon.position[0], Weapon.position[1], 0, 0);
effectImage.setLayoutParams(lp);
// Add the view to the layout.
Weapon.rl.addView(effectImage, lp);
// Play the sound.
Weapon.mp.seekTo(0);
Weapon.mp.start();
// Reload
reload();
}
public void reload() {
// Create the ImageView
this.effectImage = new ImageView(Weapon.ma);
this.effectImage.setImageResource(this.drawableEffect);
}
}
And I have a Pistol class which extends Weapon
public class Pistol extends Weapon {
public Pistol() {
// First save the type.
this.type = Weapon.PISTOL;
// Fetch the sound effect and image.
this.soundEffect = R.raw.gunshot;
this.drawableEffect = R.drawable.bullet_hole1;
// Create the media player and initialize the sound.
Weapon.mp = MediaPlayer.create(Weapon.ma, this.soundEffect);
// Create the ImageView
this.effectImage = null;
this.effectImage = new ImageView(Weapon.ma);
this.effectImage.setImageResource(this.drawableEffect);
}
}
As well as a Rifle class extending Weapon
public class Rifle extends Weapon {
public Rifle() {
// First save the type.
this.type = Weapon.RIFLE;
// Fetch the sound effect and image.
this.soundEffect = R.raw.gunshot;
this.drawableEffect = R.drawable.bullet_hole1;
// Create the media player and initialize the sound.
Weapon.mp = MediaPlayer.create(Weapon.ma, this.soundEffect);
// Create the ImageView
this.effectImage = null;
this.effectImage = new ImageView(Weapon.ma);
this.effectImage.setImageResource(this.drawableEffect);
}
}
finally, I have a Grenade class extending, yep you guessed it, Weapon as well.
public class Grenade extends Weapon {
public Grenade() {
// First save the type.
this.type = Weapon.GRENADE;
// Fetch the sound effect and image.
this.soundEffect = R.raw.grenade;
this.drawableEffect = R.drawable.boom;
// Create the media player and initialize the sound.
Weapon.mp = MediaPlayer.create(Weapon.ma, this.soundEffect);
// Create the ImageView
this.effectImage = new ImageView(Weapon.ma);
this.effectImage.setImageResource(this.drawableEffect);
}
}
I have buttons in the main view which I have registered onClick listeners to so you can switch weapons to your liking.. Here is one for example:
grenadeButton = (ImageButton)findViewById(R.id.grenadeButton);
grenadeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (MainActivity.this.weapon != Weapon.GRENADE) {
// Change the background color.
resetButtons();
v.setBackgroundResource(R.drawable.background_selected);
// Change weapons.
MainActivity.this.currentWeapon = equipWeapon(Weapon.GRENADE);
}
}
});
and the equip weapon method in MainActivity.
public Weapon equipWeapon(int type) {
Weapon weapon = null;
switch (type) {
case Weapon.PISTOL:
weapon = new Pistol();
break;
case Weapon.RIFLE:
weapon = new Rifle();
break;
case Weapon.GRENADE:
weapon = new Grenade();
break;
}
// Play a sound and save changes.
MainActivity.this.weapon = type;
MainActivity.mp.seekTo(0);
MainActivity.mp.start();
return weapon;
}
Now, I appreciate you taking the time to review all this code. I know that's a lot to digest for what I'm assuming is a simple issue. I'm also aware of the rules of this forum and I have attempted to search for this issue already, but I'm not sure if I was using the right queries, as I did not find anything related to this issue.
Here we go:
When you start the app, the pistol is automatically equipped so you can start shooting immediately. It shoots fine, I get a bullet noise, and bullet holes all over the picture of the person's face ^_^. The rifle works fine as well (but it uses the same noise and graphic as the pistol, so it could very well be failing as well. Refer below).
When I switch to the grenade, I here a lovely explosion sound, but the image displayed is still a bullet hole and not an explosion.. I have no earthly idea how to fix this and I am stumped..
When I create the grenade object I specifically assign the drawable resource to the instance variable...
this.drawableEffect = R.drawable.boom;
Yet it still displays R.drawable.bullet_hole1....
Please let me know if you need more information and ask any questions you need to..
Thank you for your time..

I'm so stupid.....
MainActivity.equipWeapon
wasn't calling
Weapon.equipWeapon....
So the weapon wasn't changing... Oy' vey...

Related

Changing TextView from different class

I want to update TextView from another class which is not an activity, but the app keeps crushing..
I hope you can help
This is the class where I want to update text after knowing game result
public class GameLogic {
...
public void gameResult() {
OnePlayerGameActivity gameActivity = new OnePlayerGameActivity();
TextView result = (TextView) gameActivity.findViewById(R.id.game_result_textView);
getPlayerChoice();
int computer = computerChoice();
if (mPlayerChoice == computer) {
mPlayerStat += 0;
mOpponentChoice += 0;
} else if (mPlayerChoice == 1) { //ROCK
switch (computer) {
case 1: //ROCK
break;
case 2: //PAPER
mOpponentStat ++;
result.setText("LOST");
break;
...
all code can be found on my GitHub
You are creating just a dummy instance of your activity which has no relation with the one in memory, instead pass the activity instance using
// in your OnePlayerGameActivity.java
// inside some method
GameLogic obj = new GameLogic (); // instance of GameLogic for demo
obj.gameResult(OnePlayerGameActivity.this); // pass instance
and change the methods signature as
public void gameResult(OnePlayerGameActivity gameActivity ) {
TextView result = (TextView) gameActivity.findViewById(R.id.game_result_textView);

Android Expandable RecyclerView different Card height

I have a RecyclerView that contains a list of cards, each of which expand into child cards.
Each card has different text. I want that when the user clicks on a child card, it will expand to show the text inside. The expansion height is based on how much text the card contains.
I tried to measure the target height by using:
view.Measure(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
And then expanding the card to the Measured Height (see here).
However, it gives the same Measured Height to all of the cards.
Here is my code, which is based on this (more specifically the Xamarin version):
This is the main Adapter, which creates and binds the parent and the child cards:
public class HalachaExpandableAdapter : ExpandableRecyclerAdapter<HalachaParentViewHolder, HalachaChildViewHolder>, View.IOnClickListener
{
LayoutInflater _inflater;
bool expand;
int targetHeight;
bool wave = false;
public HalachaExpandableAdapter(Context context, List<IParentObject> itemList) : base(context, itemList)
{
_inflater = LayoutInflater.From(context);
}
public override void OnBindChildViewHolder(HalachaChildViewHolder childViewHolder, int position, object childObject)
{
var halachaChild = (HalachaChild)childObject;
childViewHolder.halachaChildTitle.Text = halachaChild.Title.ToString();
targetHeight = childViewHolder.halachaChildCard.Height;
childViewHolder.halachaChildCard.LayoutParameters.Height = 100;
childViewHolder.halachaChildCard.SetOnClickListener(this);
expand = childViewHolder.expand;
}
public override void OnBindParentViewHolder(HalachaParentViewHolder parentViewHolder, int position, object parentObject)
{
var halacha = (HalachaItem)parentObject;
parentViewHolder._halachaTitleTextView.Text = halacha.Title();
parentViewHolder._halachaContentTextView.Text = halacha.Content;
if (halacha.ChildObjectList.Count == 1)
wave = true;
}
public void OnClick(View v)
{
if (v.Height == 100)
{
AnimationCollapse anim = new AnimationCollapse(v, targetHeight, 100);
anim.Duration = 300;
v.StartAnimation(anim);
expand = false;
}
else
{
AnimationCollapse anim = new AnimationCollapse(v, 100, v.Height);
anim.Duration = 300;
v.StartAnimation(anim);
expand = true;
}
}
public override HalachaChildViewHolder OnCreateChildViewHolder(ViewGroup childViewGroup)
{
var view = _inflater.Inflate(Resource.Layout.halachotListItem, childViewGroup, false);
return new HalachaChildViewHolder(view);
}
public override HalachaParentViewHolder OnCreateParentViewHolder(ViewGroup parentViewGroup)
{
var view = _inflater.Inflate(Resource.Layout.halachotListHeader, parentViewGroup, false);
wave = false;
return new HalachaParentViewHolder(view);
}
}
I think this is where the code is needed to be done, but if you need some of the other code of the other classes, I will gladly post them. You can also look at the links above for reference to how this works.
Hope someone can help me.
Thanks!
I finally managed to solve the problem.
I needed to change the way I measured the view's wrap_content height to this:
v.Measure(MeasureSpec.MakeMeasureSpec(v.Width, MeasureSpecMode.Exactly), MeasureSpec.MakeMeasureSpec(ViewGroup.LayoutParams.WrapContent, MeasureSpecMode.AtMost));
The rest is the same.
Thanks to this post.
I dont know why do you want to find the height of the card , instead you can just wrap the child cards height to that of text and make child card invisible , as soon as user click a card , child card s visiblity will be turned to visible and card wih its text with the same height will appear !

Avoid overlap between touch and click android in OnTouch(), in IOnTouchListener?

I am creating this app.
code of my onsingletapup.cs file
class SingleTapUp : Android.Views.GestureDetector.SimpleOnGestureListener
{
public override bool OnSingleTapUp(MotionEvent e) {
// Toast.MakeText(this,, ToastLength.Long).Show();
return true;
}
}
here is my mainactivity.cs
public class MainActivity : ActionBarActivity, View.IOnTouchListener
{
GestureDetector gestureDetector;
float _viewX;
float _viewY;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
PopulateListView(someList,anynumbertoshow)
}
private void QueueListView(Queue<FeedItem> feedItemsList, int count)
{
RelativeLayout rl = this.FindViewById<RelativeLayout>(Resource.Id.newsContainer);
if(rl.Visibility == ViewStates.Gone)
{
this.FindViewById<LinearLayout>(Resource.Id.newsList).Visibility = ViewStates.Gone;
rl.Visibility = ViewStates.Visible;
}
Paint layerPaint = new Paint();
layerPaint.AntiAlias = true;
layerPaint.FilterBitmap = true;
layerPaint.Dither = true;
// RelativeLayout parentLayout = (RelativeLayout)LayoutInflater.from(context).inflate(R.layout.myLayout, null);
rl.SetLayerType(LayerType.Hardware, layerPaint);
rl.SetClipChildren(false);
Random rnd = new Random();
//this.progressDialog.Dismiss();
for (int i = 0; i < count; i++)
{
FeedItem rss = theNewsQueue.Dequeue();
var viewObj = this.LayoutInflater.Inflate(Resource.Layout.NewTile, rl, false);
TextView tv = viewObj.FindViewById<TextView>(Resource.Id.textView2);
TextView link = viewObj.FindViewById<TextView>(Resource.Id.link);
link.Text = rss.Link;
tv.Text = rss.Title;
viewObj.Rotation = angle;
angle = rnd.Next(-3, 3);
viewObj.SetLayerType(LayerType.Hardware, layerPaint);
rl.AddView(viewObj);
gestureDetector = new GestureDetector(this, new SingleTapUp());
viewObj.SetOnTouchListener(this); //Here I am adding my listener to all my control
rl.SetLayerType(LayerType.Hardware, layerPaint);
theNewsQueue.Enqueue(rss);
rss = null;
}
}
public bool OnTouch(View v, MotionEvent e)
{
if (gestureDetector.OnTouchEvent(e))
{
//will detect a click and open in browser
return true;
}
else
{
int initialTouchX = 0, initialTouchY = 0;
int newx = 0;
var x = v.Left;
switch (e.Action)
{
case MotionEventActions.Down:
{
_viewX = e.GetX();
_viewY = e.GetY();
initialTouchX = (int)e.RawX;
initialTouchY = (int)e.RawY;
break;
}
case MotionEventActions.Up:
{
int lastX = (int)e.GetX();
int lastY = (int)e.GetY();
if ((x - newx) > 40)
{
//right Swipe
sendViewToBack(v);
}
else if ((newx - x > 40))
{
//left Swipe
sendViewToBack(v);
}
break;
}
case MotionEventActions.Move:
{
// click = false;
var left = (int)(e.RawX - _viewX);
newx = left;
var right = (int)(left + v.Width);
var top = (int)(e.RawY - _viewY);
var bottom = (int)(top + v.Height);
v.Layout(left, top, right, bottom);
break;
}
}
}
// _gestureDetector.OnTouchEvent(e);
return true;
}
public void sendViewToBack(View child)
{
var parent = (ViewGroup)child.Parent;
if (null != parent)
{
parent.RemoveView(child);
if(viewType==0)
parent.AddView(QueueListView (theNewsQueue), 0);
else
parent.AddView(QueueListView (theNewsQueue), parent.ChildCount-1);
}
}
}
Now my question is on some devices my current code is giving some abnormal behavior. Like even if I perform OnSingleTapUp() which is supposed to perform click operation but it is performing a move operation. My question is what is wrong with my code so that it is not working correctly. Any help will be greatly appreciated. Thank you.
The onTouch and onClick doesn't work together. In all the cases the onTouch is going to get the priority, in fact onClick in also sort of fine implementation of onTouch. If you want to have onClick sort of functionality, let go the original onClick and try to handle that in onTouch. You can take help of the GestureDetector.SimpleOnGestureListener in Xamarin. For an example to override the double tap you can do it like this
class MyDoubleTapListener : GestureDetector.SimpleOnGestureListener
{
public override bool OnDoubleTap(MotionEvent e)
{
//Your code here
return false;
}
}
and then in your activity
public class Test : Activity, View.IOnTouchListener
{
private GestureDetector _gestureDetector = null;
protected override void OnCreate (Bundle bundle)
{
_gestureDetector = new GestureDetector(new MyDoubleTapListener (this));
_editText.SetOnTouchListener(this);
}
public bool OnTouch(View v, MotionEvent e)
{
return _gestureDetector.OnTouchEvent(e);
}
}
GestureDetector also provides you other methods that you can overide to suit your need. Follow this, https://developer.xamarin.com/api/type/Android.Views.GestureDetector/
I couldn't get exactly what your are trying to do inside onTouch interface. Anyway there's some points you must know:
1) When you handle a touch event, onTouch method returns a boolean that indicates if event was consumed (true) or not (false). If you consume touch event related to click, click listener won't be triggered. So, make sure you are only consuming what is desired.
2) When you set listeners as onClick or onTouch to some view, it becomes clickable and touchable, respectively, if it wasn't. If you are setting this attributes to false in some part of your code make sure it's enabled again when you want to handle such events.

Android - Dynamic View Timing Issue?

I'm an Android newbie developer and having an issue with a tiny Android app I'm developing which I suspect is related to timing of dynamic view creation. It's a little scorekeeper app and it has dynamically generated player buttons and text fields, defined in a Player class. Here's an excerpt of how I'm doing this:
public Player(String name, int score, int number, boolean enabled, RelativeLayout mainScreen, List<Button> presetButtonList, Editor editor, Context context) {
super();
this.name = name;
this.score = score;
this.number = number;
this.enabled = enabled;
this.editor = editor;
// Get the lowest child on the mainScreen
Integer count = mainScreen.getChildCount(), lowestChildId = null;
Float lowestChildBottom = null;
for (int i = 0; i < count; i++) {
View child = mainScreen.getChildAt(i);
if ((lowestChildId == null || child.getY() > lowestChildBottom) &&
!presetButtonList.contains(child)) {
lowestChildId = child.getId();
lowestChildBottom = child.getY();
}
}
playerNameText = (EditText) setTextViewDefaults(new EditText(context), name);
playerNameText.setSingleLine();
// playerNameText.setMaxWidth(mainScreen.getWidth());
// playerNameText.setEllipsize(TextUtils.TruncateAt.END); //TODO: Prevent names which are too long for screen
playerNameText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable changedText) {
setName(changedText.toString());
updateScreen();
}
public void beforeTextChanged(CharSequence changedText, int start, int count, int after) {}
public void onTextChanged(CharSequence changedText, int start, int before, int count) {}
});
RLParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
if (lowestChildId != null) {
RLParams.addRule(RelativeLayout.BELOW, lowestChildId);
} else {
RLParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
RLParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
}
RLParams.setMargins(0, 10, 0, 10);
mainScreen.addView(playerNameText, RLParams);
the class further defines buttons and etc in a similar fashion, aligning tops with the name text view. I call this when a user clicks a button to add a player, and it works fine, displaying each player below the first on down the screen. The problem comes in when I'm loading a bunch of saved players at the start. Here's where i load the players:
public void loadData() {
RelativeLayout mainScreen = (RelativeLayout)findViewById(R.id.relativeLayout);
playerCount = savedData.getInt("playerCount", playerCount);
Player player;
String name;
playerList.clear();
for (int i=1; i<=playerCount; i++) {
name = savedData.getString("name" + i, null);
if (name != null) {
Log.v("name", name);
player = new Player(name, savedData.getInt("score" + i, 0), i, savedData.getBoolean("enabled" + i, false), mainScreen, presetButtonList, editor, this);
playerList.add(player);
player.updateScreen();
}
}
updateScreen();
}
Finally, I call the loadData() method when the app starts, here:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
savedData = this.getPreferences(Context.MODE_PRIVATE);
editor = savedData.edit();
presetButtonList.add((Button)findViewById(R.id.newGame));
presetButtonList.add((Button)findViewById(R.id.addPlayer));
presetButtonList.add((Button)findViewById(R.id.removePlayer));
loadData();
}
The result? When there are more than two players to load, all the players get loaded to the same spot, on top of Player 2.
I suspect somehow that the players are all being generated at the same time and thus all believing that the lowest player view is Player 1, and not checking each other. I've tried triggering the load later than onCreate() and it still happens. I also tried adding a 3 second sleep within the for loop of loadData() after each player loads to see if that helped, but no luck.
Am I making bad assumptions? What am I doing wrong and how might I fix it?
I suspect what is happening here is that you are attempting to position views that don't have IDs (it looks like you don't set them anywhere in your code). Dynamically created views don't automatically have IDs, so a call to getId() will return NO_ID (See documentation). If you want to use an ID you will have to set it yourself using View.setId().
It was a timing issue after all. I needed to wait for the main screen to load before I could add views to it. Unfortunately, it would never load until all activity on the UI thread was finished.
Thus, I needed threading. I ended up putting loadData() in a thread, like this:
new Thread(new loadDataAsync(this)).start();
class loadDataAsync implements Runnable {
MainActivity mainActivity;
public loadDataAsync(MainActivity mainActivity) {
this.mainActivity = mainActivity;
}
#Override
public void run() {
try {
Thread.sleep(700);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
loadData(mainActivity);
}
}
Then I created the players back on the UI thread after the initial sleep to give time for the UI to load.
runOnUiThread(new Runnable() {
Player player;
RelativeLayout mainScreen = (RelativeLayout)findViewById(R.id.relativeLayout);
#Override
public void run() {
player = new Player(savedData.getString("name" + playerNum, null), savedData.getInt("score" + playerNum, 0), playerNum, savedData.getBoolean("enabled" + playerNum, false), mainScreen, presetButtonList, editor, mainActivity);
playerList.add(player);
player.updateScreen();
mainScreen.invalidate();
}
});
Not the most elegant solution, but it works for now.

Drag and drop imagebuttons having issues with onDrag

I am developing an android app where the user can purchase buildings that are imagebuttons that implement the drag and drop api. My issue is that when the user buys two buildings, say colonyHutOne and colonyHutTwo, there is an issue with the x and y coordinates being saved in the onDrag. In my onDrag I pass in which building number in the onDragListener so i know what building i am dealing with in the onDrag class. This way i can save the coordinates to the appropriate building. The problem is that no matter what building number i pass into the onDrag, the most recently created building is the one that takes the coordinates. In the onDrag, it receives building number two every time even when its the first building that is being dragged (which is building number one). I have no idea if this has something to do with context that is passed to the onDrag or if it is because the onDragListeners are declared before the drag is made so it just takes the last created imagebutton. I have no idea how to get past this issue. Please help.
Here is the code for setting the on Drag listener of both buildings:
findViewById(R.id.topHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 1));
findViewById(R.id.bottomHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 1));
FrameLayout.LayoutParams param1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
newColonyHutFrame.addView(newColonyHutOne, param1);
findViewById(R.id.topHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 2));
findViewById(R.id.bottomHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 2));
FrameLayout.LayoutParams param1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
newColonyHutFrame.addView(newColonyHutTwo, param1);
Here is the onDrag class:
public class ColonyHutDrag implements OnDragListener
{
SharedPreferences prefs;
Context passedContext;
Database data;
int buildingNum = 0;
public ColonyHutDrag(Context applicationContext, int num)
{
passedContext = applicationContext;
buildingNum = num;
}//end constructor
#Override
public boolean onDrag(View v, DragEvent event)
{
float x = 0, y = 0;
switch(event.getAction())
{
case DragEvent.ACTION_DRAG_STARTED:
//drag has started
break;
case DragEvent.ACTION_DRAG_ENTERED:
//being dragged
break;
case DragEvent.ACTION_DRAG_EXITED:
//stop drag
break;
case DragEvent.ACTION_DRAG_LOCATION:
//find drag location
break;
case DragEvent.ACTION_DROP:
if (v == v.findViewById(R.id.bottomHalf))
{
//find position where dropped
x = event.getX();
y = event.getY();
//save the coordinates that the building was dropped at
data = new Database(passedContext);
data.open();
if (buildingNum == 1)
{
data.colonyHutOneXEntry(x);
data.colonyHutOneYEntry(y);
Toast.makeText(passedContext, "Going in1 -> x: " + x + " y: " + y, Toast.LENGTH_SHORT).show();
}//end if
else if (buildingNum == 2)
{
data.colonyHutTwoXEntry(x);
data.colonyHutTwoYEntry(y);
Toast.makeText(passedContext, "Going in2 -> x: " + x + " y: " + y, Toast.LENGTH_SHORT).show();
}//end else if
data.close();
//use this to fix building loadup glitch
View view = (View) event.getLocalState();
ViewGroup group = (ViewGroup) view.getParent();
group.removeView(view);
FrameLayout contain = (FrameLayout) v;
contain.addView(view);
view.setX(x - (view.getWidth()/2));
view.setY(y - (view.getHeight()/2));
view.setVisibility(View.VISIBLE);
}//end if
else
{
View view = (View) event.getLocalState();
view.setVisibility(View.VISIBLE);
}//end else
break;
default:
break;
}//end switch
return true;
}//end onDrag function
}//end ColonyHutOneDrag class
Here is the onTouchlistener for the drag and drop:
public class BuildingsClick implements OnTouchListener
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
ClipData.Item item = new ClipData.Item((CharSequence)v.getTag());
String[] mimeTypes = { ClipDescription.MIMETYPE_TEXT_PLAIN };
ClipData data = new ClipData(v.getTag().toString(), mimeTypes, item);
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
v.startDrag(data, shadowBuilder, v, 0);
v.setVisibility(View.INVISIBLE);
return false;
}//end onTouch function
}//end BuildingsClick class
I really appreciate any help. I have no idea how to fix the problem. It is almost like since the second building is being dealt with, then the first one can no longer be referenced.
Thanks guys.
Edit:
Code in BuildingsClick class
//find which building is being dragged
if (v.getTag() == "NewColonyHutOne")
{
ColonyHutDrag.setType(ColonyHutOneDrag.getType());
}//end if
else if (v.getTag() == "NewColonyHutTwo")
{
ColonyHutDrag.setType(ColonyHutTwoDrag.getType());
}//end if
Code for ColonyHutOneDrag class:
public class ColonyHutOneDrag extends ColonyHut
{
#Override
public int getType()
{
return 1;
}//end getType
}//end ColonyHutOneDrag
The code for the ColonyHutTwoDrag class is the same as the first one but returns 2.
This is the getType in ColonyHutDrag:
public void setType(int type)
{
buildingNum = type;
}//end setType
You are incorrectly as assigning the OnDragListeners again.
You can't
findViewById(R.id.topHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 1));
findViewById(R.id.bottomHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 1));
FrameLayout.LayoutParams param1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
and then
findViewById(R.id.topHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 2));
findViewById(R.id.bottomHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 2));
FrameLayout.LayoutParams param1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
The reason is because your second call overwrites your first, and you never listen for hut type of 1 to be dragged, because you passed which hut you are listening for in your constructor.
The solution to this is to change your assignment of the listener, like so:
findViewById(R.id.topHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext()));
findViewById(R.id.bottomHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext());
FrameLayout.LayoutParams param1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
We're going to make an abstract class ColonyHut, and define public int getType();.
Get rid of your constructor for ColonyHutListener as well, we won't need that. Then you're going to make a class called ColonyHutOne, if you don't already have one. With that class, you're going to want to extend ColonyHut, and define getType() like so:
public int getType()
{
return 1;
}
Then we'll define a function in your ColonyHutDrag class, called setType() like so:
public void setType(int type)
{
buildingNum = type;
}
After that you're going to want to get the ColonyHutOne as a ColonyHut, like so ColonyHut currentlySelectedHut = view.getHutFromView() in your onTouchListener, and call colonyHutDrag.setType(currentlySelectedHut.getType()) before v.startDrag() and it should work. Do the same for ColonyHutTwo, except obviously then you should make getType() return 2.
I'll leave defining view.getHutFromView(), and making colonyHutDrag visible in your BuildingsClick class. After all EVERYTHING can't be a free-be :-).

Categories

Resources