ViewPager starting at wrong place? - android

I want to display letters on screen and enable swiping with ViewPager, however, the first letter starts at position first+1.
I have an array of drawables like this
private static int[] images = {R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d};
public static int position = 0;
And based on the position, I set the image to be shown in ImageView
letter.setImageDrawable(getResources().getDrawable(images[position]));
The getPosition code
#Override
public Fragment getItem(int position) {
LetterViewFragment.position = position;
return new LetterViewFragment();
}
Now the initial view shows the second image as initial view, and when I swipe right, I see the second image again. But if I swipe back from third image back to first, I see the first image.
I've found similar questions that had the same problem like this one
but there's no answer.
Thanks!

Try this code that can help you manage the latter at position which starts at position 1,
letter.setImageResource(images[position - 1]);

Try to change you code like below:
letter.setImageDrawable(images[position-1]);

Related

Snap center onItemClick in cyclic Recyclerview android

Description: I am working on one demo with the functionality that user can select an option from the item of horizontal Recyclerview. In this, I got stuck in below queries.
Queries:
1: How to make Recyclerview cyclic?
For example, I have 10 items named 1,2,3,4,5,6,7,8,9,10. Now if user scrolls the recyclerview then he/she will be able to scroll it endlessly. i.e 1,2,3,4,5...9,10,1,2...9,10,1,2,3..9,10 like this.
To achieve this I have used this answer. Somehow it worked but only in forward direction.
2: How to give Snap center to the particular item which is selected by the user?
For example: As shown in the image, if the user clicks on '15' then that item will come to the center. Same as if the user clicks on '07' then it should come to the center position.
I have implemented this demo. But it doesn't work on click on the item.
The code which I have done so far is as below:
Layout Manager:
final CenterZoomLayoutManager mLayoutManager = new CenterZoomLayoutManager(mContext,
CenterZoomLayoutManager.HORIZONTAL, false);// To get centered item zoom
recyclerview.setLayoutManager(mLayoutManager);
Adapter object:
mAdapter = new CustomAdapter(mContext, arrayList, new RecyclerViewClickListener() {
#Override
public void recyclerViewListClicked(View v, int position) {
}
});
recyclerview.setAdapter(mAdapter);
Any help is appreciated!
Thanks.
CarouselView may fulfill your requirements. Please check following GitHub links for the same.
https://android-arsenal.com/details/1/1481
https://github.com/nicklockwood/iCarousel
https://www.pocketmagic.net/a-3d-carousel-view-for-android/
https://github.com/clkasd/CarouselViewProject
How do I create a circular (endless) RecyclerView?
There is no way of making it infinite, but there is a way to make it
look like infinite.
in your adapter override getCount() to return something big like
Integer.MAX_VALUE:
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
in getItem() and getView() modulo divide (%) position by real item
number:
#Override
public Fragment getItem(int position) {
int positionInList = position % fragmentList.size();
return fragmentList.get(positionInList);
}
at the end, set current item to something in the middle (or else, it
would be endless only in downward direction).
// scroll to middle item
recyclerView.getLayoutManager().scrollToPosition(Integer.MAX_VALUE / 2);
For snapping
use SnapHelper or scrollToPositionWithOffset, where offset is (width/2 - itemWidth/2)
I can use this library
You can solve your problem by personalizing this library. By selecting each item, you can use the ScrollToX function to navigate to that item.
https://github.com/mahdimoaz/RecyclerViewHorizontalCenterSelected

how to get RecyclerView highlighed selection changed from outside of RecyclerView?

I have made horizontal RecyclerView to show images where you select different actions by touching image. I have also highlighted current active selection by using background drawable and set that on onBindViewHolder.
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.itemView.setSelected(selectedPos == position);
holder.imageView.setImageResource(horizontalList.get(position).imageId);
then i have button which is not part RecyclerView so you can also roll selection in recyclerview to next one by pressing it.
It's working fine except highlighting doesn't change when pressing button.
I can test that when selecting currently selected item, i get my instructions activity opened otherwise different activity will be opened.
So how i can get that current selected item highlight when pressing a button??
update 1.
I have in my activity under myButtonOnClick
int mItemCount = horizontalAdapter.getItemCount() - 1;
horizontalAdapter.notifyItemChanged(selectedItem);
if (selectedItem == mItemCount) {
selectedItem = 0;
} else {
selectedItem += 1;
}
horizontalAdapter.notifyItemChanged(selectedItem);
which doesn't do much.
update 2.
Found the problem which was at my onBindViewHolder as i declared there different variable which messed things up.
so horizontalAdapter.notifyItemChanged(selectedItem); worked just fine and my
onBindViewHolder now i have holder.itemView.setSelected(selectedItem == position);
so manipulate same variable from both button and recyclerview to get things right.
You can add an OnScrollListener to your RecyclerView to observe any change in scroll state and position.
ref to this
If it doesn't help, you may paste your code inside the button.OnClickListener for further discussion.

Load only one Fragment in ViewPager

I have used ViewPager with Fragment.But it loads two pages at time.Is there any way to load only one page in viewpager ?
This might be the thing you are looking for:
mPager.setOffscreenPageLimit(n); // where n is the number of offscreen pages you want to load.
**The minimum value of it can be "1" as you said. ** check this link and also read the comments.
setOffScreenPageLimit method has a limit of minimum 1.
If you'll try to set smaller limit than this, it will use its default value which is 1.
You can try to do manual your adapter such as
public int currentIndex;
#Override
public Fragment getItem(int index) {
if(position == currentIndex){
return new EmptyFragment();
}else{
return new YourNormalFragment();
}
}
and becareful to modify
yourViewPager.setCurrentItem(index);
along with
yourAdapter.currentIndex = index;

Problems in integrating my android app

I am developing Splash screen,GridView, ListView and 4 other codes.
Since every item click in GridView namely Image,video,document and upload displays the same items in ListView(my code is like that) I am confused as to how to apply the loops in the onItemClick(AdapterView parent, View view, int position, long id) method so that i can display image code,video code,document code and uploading code in accordance with the items in GridView and ListView
To be very precise just go through the flow below
1.Image(Grid View)-----Onclick---->Item1(listview)--Onclick()-->Image Code
---->Item2(listview)--Onclick()-->Image Code
---->Item3(listview)--Onclick()-->Image Code
---->Item4(listview)--Onclick()-->Image Code
2.Video(Grid View)-----Onclick---->Item1(listview)--Onclick()-->Video Code
---->Item2(listview)--Onclick()-->Video Code
---->Item3(listview)--Onclick()-->Video Code
---->Item4(listview)--Onclick()-->Video Code
3.Document(Grid View)-----Onclick---->Item1(listview)--Onclick()-->Document Code
---->Item2(listview)--Onclick()-->Document Code
---->Item3(listview)--Onclick()-->Document Code
---->Item4(listview)--Onclick()-->DocumentCode
4.Upload(Grid View)-----Onclick---->Item1(listview)--Onclick()-->Upload Code
---->Item2(listview)--Onclick()-->Upload Code
---->Item3(listview)--Onclick()-->Upload Code
---->Item4(listview)--Onclick()-->UploadCode
Thanks in advance if anybody could help it would be fantastic
If your grid screen and list screen are seperate activities, then you can pass the "type" of the grid option that was selected by the user as an extra in the intent you are using to start the list activity. And then depending on this value, you can decide the action that is to be taken in the onItemClick.
Hope that helps.
Define the types for your operations. like,
public static final int OPTION_IMAGECODE = 1 ;
public static final int OPTION_VIDEOCODE = 2 ; ...etc
and a varaible to hold the type like, private int selectedGridOption ;
When user clicks on the grid option, populate the variable. Like,
selectedGridOption = OPTION_IMAGECODE ; if the user selectes the image type.
In your intent you use to start the list activity put this value as an extra. Like,
listActivityIntent.putExtra("Selected Option", selectedGridOption) ;
In you list activity you can retreive this value as,
getIntent().getIntExtra("Selected Option", *default_value_you_want*) ;

Getting the current position of a ViewPager

I know with the Gallery widget I was able to use getSelectedItemPosition(); to retrieve the current position, however it doesnt seem ViewPager has that.
I know I can setup a listener and retrieve the position when the page is switched. But I want the current view position.
You can use:
mViewPager.getCurrentItem()
Create a listener and set it on your viewpager:
/**
* Get the current view position from the ViewPager by
* extending SimpleOnPageChangeListener class and adding your method
*/
public class DetailOnPageChangeListener extends ViewPager.SimpleOnPageChangeListener {
private int currentPage;
#Override
public void onPageSelected(int position) {
currentPage = position;
}
public final int getCurrentPage() {
return currentPage;
}
}
Update 2019
Now you can set addOnPageChangeListener on View Pager to Observe change in Page position.
Since you wanted to setup a listener and retrieve the position when the page is switched
mViewPager.addOnPageChangeListener(object : OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) {
pagePosition.setText("" + position + "/" + galleryAdapter!!.count)
}
})
My solution would only work if you have a TabLayout linked to your ViewPager.
This is how they're linked:
tabLayout.setupWithViewPager(viewPager);
And then to get current position, you can make use of:
tabLayout.getSelectedTabPosition()
I'm telling you now its a hack, so there is no reason to downvote for that reason. Meaning, it either will be helpful to you specifically or not. Either way, the description below will provide some insight and be helpful to the community. Also, this solution is good for the older APIs that don't have ViewPager.getCurrentItem().
First, a little information. If you iterate thru all children of a ViewPager with ViewPager.getChildAt(x); and print out with toString() (or getLeft()) each child View (a page) and then do this everytime you change pages, you will notice that the children will not be in the logical order that they are displayed in when you start going back pages (paging back to the beginning). Apparently, it will remove the unneeded child from the array then append the newest child to the array. So, for example, lets say you are looking at page 2 then changed to page 3, your list of children will be in this order page 2, page 3, page 4 meaning that ViewPager.getChildAt(1); will return the current page. But, if you then change back to page 2 (from page 3) your list of children will be in this order page 2, page 3, page 1 which means that ViewPager.getChildAt(1); does not return the current page. I have not yet been able to find simple logic to weed out the current page using this information. Because the order of the pages in the array behind getChildAt is in an arbitrary order based off of how the user has been paging around.
That being said, I developed a hack work-around. I have no clue if this function will work in all in environments, but it works for my current project. I would suspect if doesn't for you, then its an issue of different API level. But I dont actually suspect any issues for other environments.
Now, onto the meat. What I noticed was that the result of ViewPager.getChildAt(x).getLeft() will have some type of horizontal pixel coordinate relative to the parent. So, I used this information to weed out which view is the current one.
private int getCurrentPageIndex(ViewPager vp){
int first,second,id1,id2,left;
id1 = first = second = 99999999;
View v;
for ( int i = 0, k = vp.getChildCount() ; i < k ; ++i ) {
left = vp.getChildAt(i).getLeft();
if ( left < second ) {
if ( left < first ) {
second = first;
id2 = id1;
first = left;
id1 = i;
} else {
second = left;
id2 = i;
}
}
}
return id2;
}
This function is probably a questionable hack because it relies on the value of getLeft() to figure it all out. But, I grab the left coordinate of each child. I then compare this to the other values and store the first and second pages, returning the second page (current page) out of the function. It seems to work beautifully.
Why (might you ask) didn't I just use onClickListenter or whatever solution? Well, I was darned determined that there was a straight forward way to do this without having to include listeners, other classes, inconclusive focus, and other bloat. Unfortunately, this solution is not exactly straight forward. But, it does do away with the bloat, other classes and listeners. If I can figure out a more straight forward way, I will be rewriting this function. Or maybe, this will provide insight for someone else to have an epiphany.

Categories

Resources