how to override the position of an onItemClick in Android - java

So I have a button, and this button switches the cell of a listview with the cell above, and vise versa for ANOTHER button which is for down (this one is for up... It doesn't matter which, I just decided to talk about this one). The whole button and list view thing is working, but my problem is when I press the up button, and then decide to press it again, it just acts as a down button. The reason for this is because it's still stuck on the same item/position of the list view, and I need to figure out a way to Override the position of the onItemClick in the code??
```
upButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//upButton onClick
Integer myTeam = position; //7 -159
Integer otherTeam = position - 1; //6 - 1678
Map<Integer, String> onClickMap = sortByValue(Constants.picklistMap);
String extraValue;
Log.e("myposition", myTeam.toString());
Log.e("otherposition", otherTeam.toString());
extraValue = onClickMap.get(myTeam); //159
String team = onClickMap.get(otherTeam);
Constants.picklistMap.put(myTeam, onClickMap.get(otherTeam));
Constants.picklistMap.put(otherTeam, extraValue); //6
Log.e("Position: ",Constants.picklistMap.get(position));
Log.e("Position - 1: ",Constants.picklistMap.get(position - 1));
if(myTeam != 0) {
dref.child("picklist").child(myTeam.toString()).setValue(Integer.parseInt(Constants.picklistMap.get(myTeam)));
dref.child("picklist").child(otherTeam.toString()).setValue(Integer.parseInt(Constants.picklistMap.get(otherTeam)));
} else {
Toast.makeText(getActivity(), "Nice try.
If you try it again, the app is going to crash as punishment ... (:",
Toast.LENGTH_LONG).show();
}
}
});
```
By overriding the position, I just mean how
position =+ 1
would make position = position + 1 in python, and I want to do the same thing in Java. The problem is I know that can't be done using the snippet of code I just used to increment the value of position!
Please help!
The reason I can't use position = position + 1 is because on the onItemClick, int position is defined, and then the onClick is created for the buttons, so I need position to be final for me to use it in the onClick, and if I got rid of final, i wouldn't be able to use it in the onClick as it can't be accessed from within an inner class when it's not final

Define which position you want to change, and use this method to update position. You can use this method in onClickListener. This should work.
private int position = 0;
private void up(ArrayList<Integer> arr){
if (position < 1 || position >= arr.size()) return;
int temp = arr.get(position - 1);
arr.set(position - 1, arr.get(position));
arr.set(position, temp);
position --;
}

Related

The animation for my programatically created button acts weird in my application

So I am facing a weird bug I cannot explain - I cannot even reproduce it sometimes.
Basic context:
I have an application, which lists objects. Every object has a name and a point value. For every object, the addCustomSpinner function creates a "ticket" (a custom view, kind-of-spinner) and shows them in a scrollview so the user can select the one needed. There are four different 'containers' for four different kind of objects - so the layout can be populated with four kind of "ticket" package.
The data for the objects are collected from a database. The addCustomSpinner is called with a for cycle for every object in the database, and - Important - before the for method, the Layout it populates with the tickets is cleared (removeAllViews).
Inside addCustomSpinner, everything is created as "new" - like the button in question.
addCustomSpinner creates this button and adds a new onClickListener. Inside onClickListener, a new boolean is created - this is used to show a different animation when the button is clicked again. On first click (boolean = true), the arrow turns 180 degrees and faces upwards, on second click (boolean = false) the arrow turns 180 degrees and faces downwards. Works like a charm, until...
The bug I am facing:
Sometimes - as I already mentioned, not every time - if I click the button for one "ticket", then leave it 'opened' and click on an another one, and leave it 'opened' also, THEN I choose to populate the layout with a different kind of "ticket" package - The arrow faces upwards by default on every ticket in every package! Sometimes - again, just sometimes - with the same pattern I can turn it back, but it happens just "by accident".
I don't understand how the animation and state of the buttons can be connected, if every created ticket is new, every button is new, every onClickListener is new, and every boolean inside onClickListener is new. And if these are connected somehow, then why can that be that every behavior is "unique" for the buttons, nothing else shows any connection - even this is just a "sometimes" bug, a pretty rare one.
Can anybody help me why this happens?
What I tried:
Well, tried to trace the issue - but since it happens just by accident, I have no clue, I just searched if I can do anything else than the boolean to add different animation for the clicks. Sadly using ObjectAnimator is not a good solution for me - not the same result at least, since my animated arrow not only rotates, but it also changes its color. Shapeshifter seemed like a good idea to create animations easily, but now as I see it, maybe a simple rotation will be my ultimate solution.
Here's the code for the button:
customButton.setOnClickListener(new View.OnClickListener() {
boolean isCustomButtonClicked = true;
#Override
public void onClick(View v) {
if (isCustomButtonClicked) {
customButton.setImageResource(R.drawable.avd_anim_arrow_blue_back);
Drawable d = customButton.getDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (d instanceof AnimatedVectorDrawable) {
animArrowAnim = (AnimatedVectorDrawable) d;
animArrowAnim.start();
}
}
routeWhoClimbed.setVisibility(View.VISIBLE);
isCustomButtonClicked = false;
} else if (!isCustomButtonClicked) {
customButton.setImageResource(R.drawable.avd_anim_arrow_blue);
Drawable d = customButton.getDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (d instanceof AnimatedVectorDrawable) {
animArrowAnim = (AnimatedVectorDrawable) d;
animArrowAnim.start();
}
}
routeWhoClimbed.setVisibility(GONE);
isCustomButtonClicked = true;
}
}
});
EDIT:
The full addCustomSpinner():
private void addCustomSpinner(Routes mRouteItemToAdd, String placeName) {
//creating a new View for my custom layout created in xml
View customRoutesView = new View(this);
LinearLayout.LayoutParams customViewParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
customRoutesView.setLayoutParams(customViewParams);
customRoutesView = LayoutInflater.from(this).inflate(
R.layout.custom_view_layout, routeLayout, false
);
//Setting up the views inside the custom view
ImageView imageViewDiffImage = customRoutesView.findViewById(R.id.routeDiffImageView);
TextView textViewRouteName = customRoutesView.findViewById(R.id.routeNameTextView);
TextView textViewRouteDiff = customRoutesView.findViewById(R.id.routeDiffTextView);
ImageButton customButton = customRoutesView.findViewById(R.id.customButton);
RadioButton climberNameOne = customRoutesView.findViewById(R.id.climberNameOne);
RadioButton climberNameTwo = customRoutesView.findViewById(R.id.climberNameTwo);
Button climbedItButton = customRoutesView.findViewById(R.id.climbed_it_button);
RadioGroup climberNameRadioGroup = customRoutesView.findViewById(R.id.climberNameRadioGroup);
RadioGroup climbingStyleRadioGroup = customRoutesView.findViewById(R.id.styleNameRadioGroup);
RelativeLayout routeWhoClimbed = customRoutesView.findViewById(R.id.routeWhoClimbedRelativeLayout);
imageViewDiffImage.setImageResource(R.mipmap.muscle);
textViewRouteName.setText(mRouteItemToAdd.name);
textViewRouteDiff.setText("Difficulty: " + (int) mRouteItemToAdd.difficulty);
climberNameOne.setText(climberName1);
climberNameTwo.setText(climberName2);
routeWhoClimbed.setVisibility(GONE);
//Here comes the button with the animated image
customButton.setOnClickListener(new View.OnClickListener() {
boolean isCustomButtonClicked = true;
#Override
public void onClick(View v) {
if (isCustomButtonClicked) {
customButton.setImageResource(R.drawable.avd_anim_arrow_blue_back);
Drawable d = customButton.getDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (d instanceof AnimatedVectorDrawable) {
animArrowAnim = (AnimatedVectorDrawable) d;
animArrowAnim.start();
}
}
routeWhoClimbed.setVisibility(View.VISIBLE);
isCustomButtonClicked = false;
} else if (!isCustomButtonClicked) {
customButton.setImageResource(R.drawable.avd_anim_arrow_blue);
Drawable d = customButton.getDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (d instanceof AnimatedVectorDrawable) {
animArrowAnim = (AnimatedVectorDrawable) d;
animArrowAnim.start();
}
}
routeWhoClimbed.setVisibility(GONE);
isCustomButtonClicked = true;
}
}
});
//Button, works like an 'OK' or something, and I have no
//problem with this
climbedItButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int checkedNameButton = climberNameRadioGroup.getCheckedRadioButtonId();
int checkedStyleButton = climbingStyleRadioGroup.getCheckedRadioButtonId();
RadioButton checkedNameRadioButton = (RadioButton) findViewById(checkedNameButton);
RadioButton checkedStyleRadioButton = (RadioButton) findViewById(checkedStyleButton);
String checkedName = (String) checkedNameRadioButton.getText();
String checkedStyle = (String) checkedStyleRadioButton.getText();
addClimbToDatabase(user.getUid(), checkedName, mRouteItemToAdd, placeName, checkedStyle);
}
});
//And finally, I add this new "ticket" with the custom view to the layout i want to show it. Again, this also works like a charm, no problem here.
routeLayout.addView(customRoutesView);
}
Ultimately, I did not manage to understand the problem throughly, but I was able to eliminate it.
So during my fixing tries I narrowed down the problem to the animated drawable state - credit to #avalerio for his pro tip, but the answer wasn't addig an id to the button. I think somehow and sometime, the state of the first animation (turning the arrow 180 degrees) stuck in the end position - causing the other views using this animatedDrawable showing it in end position on start.
.reset() did not help, since it resets the animatedVectorDrawable object, not the animation xml drawable state. My solution is a kind of workaround, but it is working: when the custom-view 'ticket' is created with the animated-drawable-imagebutton, I set the imageResource of the button to a not-animated xml drawable - this drawable is basically the start position of my animated-drawable. This way, when the 'tickets' are generated, the imagebutton is 'hardcoded' in the start position.
Not elegant, but works. BUT(!) I would really appreciate if someone could explain to me how this weird behavior is possible - just sometimes, randomly, with no pattern I can reproduce intentionally.

How to get the views which are not visible currently in the linear layout of the recycler view

I was designing an Instagram story type template. I am stuck at a very weird problem. I have used recycler view in the main activity.
MainActivity: (This is just the layout shown. I have change the orientation to Horizontal).
My layout:
Then I have designed a custom adapter and in the layout I have used a linearLayout. When clicked on each view It opens a new Activity which shows the whole story content.
Just like in Instagram when a user opens any story, the user can click on the right side of the screen to get to the next story, or left of the screen to get to the previous one. I tried to implement this same functionality. Opening the story was implemented successfully. The problem comes when I added the functionality of right and left click on the screen. I added two button; one to the right and one to the left. The problem is like, if there are currently 3 views visible, then I can navigate in between these stories only and not to the stories which are not visible in the screen because of the recycler view.
The below code is for right and left clicks
leftArrow = findViewById(R.id.leftArrow);
leftArrow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(myAdapter.currentPosition - 1 >= 0) {
int firstVis = MainActivity.linearLayoutManager.findFirstVisibleItemPosition();
MainActivity.linearLayoutManager.scrollToPosition(firstVis - 1);
rightOrLeftClicks(myAdapter.currentPosition - 1);
}
}
});
rightArrow = findViewById(R.id.rightArrow);
rightArrow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(myAdapter.currentPosition + 1 < myAdapter.localDataSet.length) {
int lastVis = MainActivity.linearLayoutManager.findLastVisibleItemPosition();
MainActivity.linearLayoutManager.scrollToPosition(lastVis + 1);
rightOrLeftClicks(myAdapter.currentPosition + 1);
}
}
});
}
Below code is of the function rightOrLeftClicks
public void rightOrLeftClicks(int position) {
finish();
Log.d("rl", "working");
nextView = MainActivity.linearLayoutManager.getChildAt(position);
Log.d("ll", "The last element is " + MainActivity.linearLayoutManager.findLastVisibleItemPosition());
if(nextView != null)myAdapter.onClickView(position, myAdapter.localDataSet[position].symptom, nextView);
}
Below code is for onClickView, It is same code for clicking any view (Story) or clicking the right or left buttons. Basically I just opened the another activity by passing an intent with the next or previous view I obtained when clicked on right or left respectively.
public static void onClickView(int position, String element, View v) {
Intent intent = new Intent(v.getContext(), MainActivity2.class);
idPosition = "";
idPosition = element;
ArrayList<String> passingContent = new ArrayList<>();
currentPosition = position;
passingContent.add(localDataSet[position].description);
passingContent.add(localDataSet[position].imageUrl);
intent.putExtra(element + "", passingContent);
v.getContext().startActivity(intent);
}
The problem is it only gives the visible views to me. Not the rest of the views. I tried auto scrolling so that the next or the previous view become visible but it doesn't seems to work. The last visible position of the child remains the same and it return a null view to me when I try to open the view just after the last visible view.
Assume there are 5 stories. Then I will see only 3 stories in the screen the rest can be seen by scrolling. When I click any of the stories. I can only navigate between 1,2 and 3. When I try to click right from story 3 to see the story 4. The current story is killed by finish() function and null is returned in the nextView variable because of which the story 4 is not loaded and I am returned to the MainActivity.
I have to navigate to all stories present in my recycler view.
Do these changes may help:
1/
I think you should use ViewPager. It automatically snaps to the item without scrollTo to index. Or keep using RecyclerView with the help of SnapHelper
2/
Modify onClickView method not to be static, and don't need View v to work. I see you just need View v just for the context. Why not just pass the context to that method. It's not proper to use a parameter like that, and that approach traps you into 3/ problem.
3/
nextView = MainActivity.linearLayoutManager.getChildAt(position);
You already know how RecyclerView works, just avoid using getChildAt because in some cases, the child you want hasn't been created yet. Base on your code, I think you don't even need to get the nextView
As told by Tam Huynh. The 1st point helped me in getting the new views in the linear layout. The views were working the fine.
There was a problem in the parameter of the function getChildAt. I have to pass the same position I was in previously. Because relatively the position(index) will not change for the child views.
index 0 -> story number 1
index 1 -> story number 2
index 2 -> story number 3
Like if there were story number 1,2 and 3 visible, the index 0 will contain 1st story, index 1 will contain 2nd and index 2 will contain 3rd story. when user clicked the right button on the 3rd story. The 4th story is first visible and now the screen have 2,3 and 4 visible. but the index of the 4th story will remain 3rd only. As now indexing will be like
index 0 -> story number 2
index 1 -> story number 3
index 2 -> story number 4
So, instead of passing position as parameter, currentPosition should be passed in getChildAt

How to set in a textview how many times a button is being clicked?

If I click a button 1 time, so it should to show number "1" in a textview. If I click again, so its should to show "2"...
#Override
public void onClick(View p1){
int id = p1.getId();
double x = 0;
//button clicked
if(id == R.id.button_contar){
x++; /*its only shows "1". When I click again, shows "1" again*/
this.mViewHolder.contados.setText(String.format("%.0f", x));
}
}
One possible approach is to initially set 0 in the textview, and with every button click you first fetch the current value in textView and then increment the value and set the new Value
int id = p1.getId();
//button clicked
if(id == R.id.button_contar){
int current = Integer.parseInt(this.mViewHolder.contados.getText().toString());
current++;
this.mViewHolder.contados.setText(String.format("%.0f", current));
}
I don't have any editor right now, so there might be some syntax errors with the above code. It will give you a rough idea on how you should solve your issue

bug z-index ViewPager with PageTransformer doesn't work with getChildDrawingOrder

I'm looking for a solution since too long now and I feel stuck. So I decided to write my first post on stackoverflow :)
I'm trying to do a CoverFlow for my app in android 4.0 and higher, after some research I decided to do that with a ViewPager, to increase the OffscreenPageLimit, and to put a negative margin and in bonus a little PageTransformer for the effect.
So my bug is about the z-index when the margin is too negative one image overlay an other, because of the drawing order, the image on the left is on the top and it's not pretty at all.
See bug here --> http://img33.imageshack.us/img33/2448/r1l1.jpg
So after some research the solution appear to be to overwrite the getChildDrawingOrder method in my ViewPager class. I did it like that :
private void setChildDrawingOrder() {
int count = getChildCount();
positions = new SparseIntArray(count);
for (int i=0, j=0 ; i<count ; i++) {
if (i == position) {
positions.put(count-1, i);
} else {
j++;
positions.put(count-1-j, i);
}
}
mNeedsToSetChildDrawingOrder = false;
}
#Override
protected int getChildDrawingOrder(int childCount, int i) {
if(i == 0 && mNeedsToSetChildDrawingOrder) setChildDrawingOrder();
return positions.get(i);
}
Where positions is an SparseIntArray, where the item on the top got the higher value (childCount-1). I fill it in the onPageSelected (method implement with OnPageChangeListener on my ViewPager) to get the position of the item that i want it to be on the top.
#Override
public void onPageSelected(int position) {
if (lastPosition != position) {
lastPosition = position;
ViewPager viewPager = ((MainActivity)mAdapterContext).getViewPager();
viewPager.setPosition(position);
}
}
I can't see where is my mistake! I also tried something with bringChildToFront in the onPageSelected without any success, probably because the PageTransformer redraw everything after the onPageSelected is called.
Any idea ?
Thanks
EDIT 15/10/13 :
I edit my code because I didn't catch what the method do very weel! It's "to get the index of the child to draw for that iteration." and not "when should I draw child i?" (thx to this post)
I also had some NullPointerException` because the count where not everytime the same so I move it into my ViewPager.
It's way better but still have some drawing bug! My positions SparseIntArray look good so I don't understand. It seems to appear kind of randomly...

Get position of an item within a ListView?

How would one find the position of a specific item within a ListView? (Populated by SimpleCursorAdapter).
The reason I ask: The listview is set to singleChoice mode. When the user closes and reopens the app, I'd like the user's selection to be remembered.
The way I've done it so far is when the user clicks on an item, the ID of the chosen item is saved to preferences. What I need to learn is how to reselect the item in the activity's onCreate method once it's been repopulated.
My code for saving the selected item's ID:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Cursor c = (Cursor) l.getItemAtPosition(position);
selectedItem = c.getLong(c.getColumnIndex("_id"));
}
(I've tried googling, but only seem to find how to get the position of the selected item)
Thanks!
You should try
//SimpleCursorAdapter adapter;
final int position = adapter.getCursor().getPosition();
API Docs:
public abstract int getPosition ()
Since: API Level 1
Returns the current position of the
cursor in the row set. The value is
zero-based. When the row set is first
returned the cursor will be at positon
-1, which is before the first row. After the last row is returned another
call to next() will leave the cursor
past the last entry, at a position of
count().
Returns
the current cursor position.
Update
To get an item's position based on the id used by the adapter:
private int getItemPositionByAdapterId(final long id)
{
for (int i = 0; i < adapter.getCount(); i++)
{
if (adapter.getItemId(i) == id)
return i;
}
return -1;
}
To get an item's position based on the underlying object's properties (member values)
//here i use `id`, which i assume is a member of a `MyObject` class,
//and this class is used to represent the data of the items inside your list:
private int getItemPositionByObjectId(final long id)
{
for (int i = 0; i < adapter.getCount(); i++)
{
if (((MyObject)adapter.getItem(i)).getId() == id)
return i;
}
return -1;
}
I do this straightforward in my own app:
long lastItem = prefs.getLong(getPreferenceName(), -1);
if (lastItem >= 0) {
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
if (lastItem == cursor.getLong(0)) {
spinner.setSelection(cursor.getPosition());
break;
}
cursor.moveToNext();
}
}
Spinner is populated with the cursor's contents, so I just look through them and compare with the selected item id. In your case that would be a ListView.
When you say, "...reselecting the item in the activity's onCreate method...", do you mean that when the user returns to the ListView activity, whatever item was previously chosen, is now currently at the top of the screen (assuming enough items appear in the list below it)?
If so, then from onListItemClick, you should also make an effort to save the value of position, since it tells you the position in the list of the selected item. This would allow you to not need to reverse-lookup the position from the _id.
Or is that for some reason not an option for your purposes? Do you really need to instead figure out the position from the _id?

Categories

Resources