setFocus() causing two pushes to select imageview - android

I'm developing a game Android app and I have a HorizontalScrollView that is being populated with ImageViews. Each ImageView is clickable to select the level you want to play. I'm using a SavedPreference to keep track of the last played level, and using that to determine which image is on screen when you load the menu. That way, if you're on level 30, you don't have to scroll all the way from level 1 every time.
I'm using a requestFocus() to bring that ImageView onto the screen, and it works fine, except for two relatively minor (but annoying) issues.
Here is what I'm doing in my for loop that populates the { HorizontalScrollView`:
final ImageView iv = new ImageView(LevelSelect.this);
iv.setImageResource(levelImages[i]);
iv.setFocusable(true);
iv.setFocusableInTouchMode(true);
iv.setId(i);
LinearLayout ll= (LinearLayout)findViewById(R.id.levelSelectGallery);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(300, LinearLayout.LayoutParams.MATCH_PARENT);
and I make it clickable:
String str = getString(R.string.level) + i + getString(R.string.avail);
if (storage.getBoolean(str,false)) { //check if level is available (unlocked)
iv.setClickable(true);
final int finalI = i;
iv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
editor.putInt(getString(R.string.Current_Level_savepreferences), finalI); //set current level to clicked image
Intent intent = new Intent(LevelSelect.this, LevelStart.class);
LevelSelect.this.startActivity(intent); // begin LevelStart activity
}
});
} else {
iv.setImageResource(lockedImages[i]); // show locked image
}
and outside the loop, I set the focus:
//check if there is a saved level
focusLevel = storage.getInt(getString(R.string.Saved_Level), 5);
//set focus on saved level
findViewById(focusLevel).requestFocus();
This brings the focused item onto the screen, but just at the edge. I would prefer it to be centered if possible. I can live with that though. The main issue is that it seems that by setting the focus, it's now requiring two presses on the image to trigger the onClickListener. I assume the first press is changing the focus and the second is clicking. If I remove the focus related code, it only requires one press.
Is there a better way to scroll the view to the desired image, or something different I should be doing with the focusing?

Why don't you just put focusLevel inside the onClickListener? That way tapping the image focuses it automatically.

So, I haven't found a way around the double press issue when the item is focused, but I did discover a different solution that works for my situation. Instead of using the HorizontalScrollView with a LinearLayout, I've now implemented a ViewPager which centers my ImageViews for me, and also allows me to scroll to an item programatically using setCurrentItem(). I don't have to use focusing at all.
For anyone looking to do the same, Philipp's example here helped me a lot: How to implement a ViewPager with different Fragments / Layouts

Related

Right way to iterate over GridLayout children with setOnClickListener in order to animate with stateListAnimator

I have a GridLayout (central_container) with 4 clickable images and animation defined in xml (animator/press_button_animation) that describes object behavior on click (press/release).
I try to connect this animation to the images in the code.
It works fine for one of four images if it is hardcoded:
private fun initAnimation() {
val stateListAnimator = loadStateListAnimator(
this,
R.animator.press_button_animation
)
central_container.getChildAt(0).setOnClickListener {
it.stateListAnimator = stateListAnimator
}
}
What is the right way to make it work on all GridLayout children?
I've tried with for loop but it stops on last image. For example if I click one by one and reach the last one, the previous images stop to react
private fun initAnimation() {
val stateListAnimator = loadStateListAnimator(
this,
R.animator.press_button_animation
)
for (n in 0 until central_container.size) {
val img = central_container.getChildAt(n)
img.setOnClickListener {
it.stateListAnimator = stateListAnimator
}
}
}
I'm sorry for being not clear enough. After number of trials and experiments I'll try to explain more exactly.
I have 4 clickable images and expect each one to be animated on click.
The problem is that inspite of each image responds to click rigth (I checked it in debugger) but the problem is with animation. For example, first image animates well, then second image animates well. But if after the second I click on first, it is clicking but the second image is the one who animates. And so on...
Or, for example if I click images one by one by order (1-2-3-4) each one animates well. Then, if I click on 1 or 2 or 3 so the one who animates is still 4.
Seems like there is a need to "reset" animation after each click somehow or anything like that.

Tappable items within recyclerview with OnItemTouchListener

inception sounds
It might not be the best idea, but here's a 4 second gif of what I'm trying to do and the problem I've run into.
https://i.imgur.com/Z3iAyNc.gifv (sorry, embedding wasn't allowed).
I have a RecyclerView with in each item a LinearLayout with category details and a hidden LinearLayout with another recyclerView. The idea is you see the categories, and once you tap on it, it expands to show the relevant posts. Another tap on the category should open the category detail page and a tap on a post should open the relevant post detail page.
I have it working, but as you can see in the gif, I have to tap at least two times, even though I never wrote it like that. It's the same for the LinearLayout's onClickListener It's like the parent RecyclerView hijacks the first tap.
Here's a schematic rundown of my code
adapter.setOnItemTouchListener(new RecyclerItemListener.RecyclerTouchListener() {
#Override
public void onClickItem(View v, int position) {
final LinearLayout postView = (LinearLayout) v.findViewById(R.id.profileCheckinDetailsView);
// The IF statement prevents reloading the view when it is already open.
if (postView.getVisibility()==View.GONE){
RelativeLayout itemView = (RelativeLayout) v.findViewById(R.id.ItemView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
[... etc]
And beneath it there's another setOnItemTouchListener for the child RecyclerView.
Am I doing this right, and if so, how to make sure both items register the first tap as well?
Thanks in advance!
Sometimes typing out a question helps you think differently. I removed the top recyclerview's touch listener and replaced the item layout with this. Both layouts get their own onClickListener. With ((LinearLayout)v.getParent()) I managed to have them control eachother.
Much easier and more effective I believe.

Repeatable process where image can be added when a button is click

I am trying to attempt the below :
What i am trying to do is whenever a user click on a button, it will add a image to the layout(which the user can scale and move to any position within the layout). The user can repeat this process hence if the user click 6 times on the button, there should be 6 image in the layout.
i have google around, looking for some sample but ain't sure if its the correct one to use. maybe i did not use the correct keyword to search. So far i have seen is endless adapter and RecyclerView but both seen to be mainly for "ListView" type.
Anyone can suggest or share a link/example that i can read up and learn from? It will be a great help.
If you want to add image on button click set on-click listener on it. You need to get how many time the user have clicked the button.
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//get adapter and view
//get image to add
addImage(i); //to desire view
}
});

How to get button inside of RecyclerView item

How do i get a specific view inside of a RecyclerView item? For example I have a floating action button inside of a recyclerview item. The recyclerview card can swipe to trigger an event (new activity) and when the user swipes i am making the fab invisible. I want so that when the user returns back to the activity with the recyclerview, the fab is visible again.
I've tried to implement this a few ways, but for some reason it's taking the fab from the NEXT card/item and placing it on the original card/item that was swiped. This is a problem because the next card might have a different colored fab or no fab at all. What is happening is that it's taking the most recent viewholder item, even if the previous one is the one I want to deal with.
So i need a way to reference the fab in the current item. I'm currently setting it to currentFab = holder.mFab (but again, it's taking the most recent holder item even though it's not the one I pressed on). I need a way to reference the fab in a specific item.
I've tried something similar in the past, I've added the Swipe function in "onBindViewHolder ", Using a Swipe Library.
What I have made is, A CardView, Inside it there are 2 Strings, And a Button, this Button will be invisible according to specific conditions, So because it's inside onBindVewHolder, it was easy to make some edits on the button.
Here's a sample :
holder.Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.Button.setVisibility(View.GONE);
}
});
Ofcourse this isn't a "fully working code" it's just an example, Plus you didn't put any code that you have tried.

Android - dynamically update GridView views

I've got a GridView with a custom Adapter, displaying thumbnails of pictures to the user. I can select and deselect pictures (I use setAlpha(0.25) on the views to notify the user of the change), and that's all well and fine.
Now what I want to do next, is have a button on top of the gridview that clears the whole selection, i.e. call setAlpha(1.0) on all views that were changed. So far I can reset my elements in the adapter, and I can setAlpha to 1, but the view doesn't update unless I scroll it out of the display, and then get back to it, or notify the adapter of changes, which redraws all my views, which does not look too pretty if only one element was selected.
I already dynamically set and reset individual elements through the GridView's onClickListener, but can't do this for more. I even tried calling performClick on all selected items through my button, but again it only displays the changes after the views have been out of the screen and are shown again.
Here's how I simulate the clicks:
for (int i = 0; i < mAdapter.getCount(); i++) {
PictureForSelection tempPic = (PictureForSelection) mAdapter.getItem(i);
if (tempPic.isPicSelected()) {
//tempPic.setIfSelected(false);
gridview.performItemClick(mAdapter.getView(i, null, null), i, i);
}
}
EDIT:
Conclusion - don't simulate clicks like this :)
So now I skip click simulation and use this:
gridview.getChildAt(i).setAlpha((float) 1.0);
In general it does exactly what I wanted it to do, except for one case:
If I have for example 3 pictures selected, one is off screen, one is partly shown, and one is fully shown, the ones shown (even partially) don't update their views.
If all the selected pictures are displayed it works flawlessly, but if some are out of the display, the rest do not update until the adapter's getView() gets called by Android. Still, thanks #mmlooloo for getting me so far.
If anyone knows a way around this, please do share :)
After setting your alpha you can call imageview.invalidate(); this causes your imageview to redraw itself.
if notifyDataSetChanged() is not working you can try like this.
i'm not sure whether this works,
1.onclick of the button you set the gridView.setAdapter(null);
2. Then set a new CustomAdapter object to gridview with default values.

Categories

Resources