#PagerAdapter
Explore tagged Tumblr posts
lettersfrombeachhead · 2 years ago
Text
android has so many fucked-up little elements it’s ridiculous. it starts off normal (you want to make a set of linear visual elements? oh use LinearLayout! you want to make a grid of stuff? use GridLayout!) but then it gets to be so specific like why does some of this stuff even exist. if you want to make a page-style UI, you can’t just make a set of views and a swipe listener and swipe between them, you have to use a ViewPager with a PagerAdapter. if you want to make a list of stuff, you can use ListView (normal) or you can use RecyclerView and make a RecyclerViewAdapter and then a ViewHolder to go along with it (why are there three different things? because android). im going to lose my fuckign mind
1 note · View note
jacob-cs · 8 years ago
Link
original source : https://rileymacdonald.ca/2015/01/16/android-using-the-viewpager/
The Android ViewPager is a view which allows users to swipe left and right through pages of data. It uses an instance of PagerAdapter to generate pages which the ViewPager displays. Several tutorials demonstrate using the ViewPager in conjunction with a Fragment, however if you are not working directly with an Activity this can be difficult. My experience implementing a ViewPager using Android’s documentation and search results was mildly frustrating.
The following is a demonstration of how to implement Android’s ViewPager using the PagerAdapter:
Include a ViewPager in your desired layout:
<android.support.v4.view.ViewPager    xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/my_view_pager"    android:layout_width="match_parent"    android:layout_height="match_parent"> </android.support.v4.view.ViewPager>
Failing to use the support ViewPager can cause your application to have a RuntimeException and crash:
java.lang.RuntimeException: Unable to start activity android.view.InflateException: Binary XML file line #28: Error inflating class ViewPager Caused by: java.lang.ClassNotFoundException: Didn't find class "android.view.ViewPager" on path: DexPathList
Implementing the ViewPager: For this demonstration I’m using a custom view to hold the ViewPager. This custom view includes an inner subclass of PagerAdapter which will manage the ViewPager views. The class is described in the code / comments below. The comments describe the purpose / usage of the required override methods of PagerAdapter instantiateItem(), getCount(), isViewFromObject() and destroyItem(). Also included is getItemPosition() which is helpful when modifying, adding and deleting items from the dataset / ViewPager.
import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; // For this demonstration I'm using using a custom frame layout to hold the view pager. public class MyFrameLayout extends FrameLayout {    // Views    private MyViewPagerAdapter myViewPagerAdapter; // View Pager Adapter    private ViewPager myViewPager; // View Pager    // Layout inflater for creating views    private LayoutInflater inflater;    // FrameLayout Constructors    public MyFrameLayout(Context context) { super(context); }    public MyFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); }    public MyFrameLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); }    // Sample initializtion method to setup the views when ready    public void initialize() {     // Grab a reference to the ViewPager     myViewPager = (ViewPager) findViewById(R.id.my_view_pager);     // Construct a new PagerAdapter to manage the pages of the ViewPager     myViewPagerAdapter = new MyViewPagerAdapter(); // Inner class - see below     // Set the ViewPagers adapter     myViewPager.setAdapter(myViewPagerAdapter);     // Construct the layout inflater     this.inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);    }    // Inner subclass of PagerAdapter to manage the ViewPager views    class MyViewPagerAdapter extends PagerAdapter {     // Constructor        public MyViewPagerAdapter() {}        // Required Override for the ViewPager to function properly.        // The value returned here is used referenced by the ViewPager. If getCount() returns 0, no views will be created.        // This is best used with a data set. Set this to return the size of your data set.        // Using a default value of 5 to display 5 pages for this demonstration.        @Override public int getCount() { return 5; }        // Required Override for the ViewPager to function properly.        // Determines whether a page View is associated with a specific key object as returned by instantiateItem(ViewGroup, int).        @Override public boolean isViewFromObject(View view, Object o) { return view == o; }        // Required Override for the ViewPager to function properly.        // Removes a page for the given position. Called automatically by ViewPager as needed.        @Override        public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); }        // Required Override for the ViewPager to function properly.        // Creates pages for the given position automatically.        // This function will fire automatically as required. On instantiation this will fire twice, once for        // page one, once for page two. As users scroll it will fire to ensure views exist ahead and behind the active        // item. This function was confusing to me initially.        @Override        public Object instantiateItem(ViewGroup container, int position) {            // Inflate (and modify) the desired layout to add to the ViewPager.            FrameLayout item = (FrameLayout) inflater.inflate(R.layout.view_to_add_to, container, false);            // Add the inflated item to the ViewPager            container.addView(item);            // Ensure the item created and added to the container is returned            return item;        }        // Used internally by the adapter when calling notifyDataSetChanged(). This method is referenced during this        // call. Returning POSITION_NONE cases the previously created views to be destroyed and new ones created.        // This was a big gotcha for me when modifying the data set to remove or add views from the ViewPager.        @Override        public int getItemPosition(Object object) { return POSITION_NONE; }    } }
Using Datasets / Modifying, adding and removing pages / views from the ViewPager: Once you have an instance of PagerAdapter hooked to your ViewPager there is no need to call the remove() or add()methods of the view pager, the PagerAdapter handles it all. Keep the following in mind when using a dataset (whichever works best for you) with the PagerAdapter: getCount() should return the size of your dataset. instantiateItem() provides a position argument which can be used to get data from your dataset. notifyDataSetChanged() Call this after changing the associated dataset. This is the only call required to update the ViewPager pages / views, it will use the PagerAdapter instantiateItem() and destroyItem() calls automagically. getItemPosition() A bit of a trick when modifying the dataset / views in the ViewPager. Returning POSITION_NONE will remove all views from the ViewPager when a dataset change is made (and notifyDataSetChanged() is called). Since I did not use setOffscreenPageLimit() the ViewPager should only be dealing with a maximum of 3 views so I consider this OK.
I hope this helps other potentially confused developers when implementing this view!
0 notes
android-arsenal · 8 years ago
Text
DynamicPagerAdapter
The DynamicPagerAdapter extends Android's PagerAdapter to do four important things:
Has an accessible HashMap View cache using ViewHolders. The default implementaiton has caching, but it isn't enforced and users of the PagerAdapter don't get access to it.
Provides the capability to use multiple view types just like RecyclerView.
Handles data set changes in a much more friendly way, allowing items to be removed, added, etc. with less issues and effort on your end.
Includes optional discard animations. These are exposed for you to call when you want or to override and create your own.
from The Android Arsenal http://ift.tt/2osbRIa
1 note · View note
knowledgewiki · 6 years ago
Text
android share image from url using array?
I am new to android and I want share my image with the according position in my image storage array. I used an viewpage adopter so when a user swipes to the left or to the right, the imageview changes. Now I want share this which is a set of imageview code.
package anil.card.christmas.christmascard; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.net.Uri; import android.support.v4.view.PagerAdapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; import java.io.File; import java.io.FileOutputStream; class ChristmasAdopter extends PagerAdapter { Context mContext; LayoutInflater mLayoutInflater; ImageView imageView; int imagepostion; private int[] mResources = {R.drawable.cs25, R.drawable.cs2,R.drawable.dx,R.drawable.prd, R.drawable.op, R.drawable.ud, R.drawable.ok,R.drawable.cs3,R.drawable.mux,R.drawable.ch, R.drawable.cs5,R.drawable.anil, R.drawable.cs6, R.drawable.cs7, R.drawable.pk, R.drawable.cs8, R.drawable.cs9,R.drawable.gk, R.drawable.cs10, R.drawable.cs11, R.drawable.cs13, R.drawable.cs14, R.drawable.cs15, R.drawable.cs16, R.drawable.cs17, R.drawable.cs19, R.drawable.cs21, R.drawable.cs23, R.drawable.cs1, R.drawable.cs27, R.drawable.cs29, R.drawable.cs31, R.drawable.cs33, R.drawable.cs35,R.drawable.newyear,R.drawable.ny,R.drawable.mn,R.drawable.hp,R.drawable.lifenew, R.drawable.cat,R.drawable.dog,R.drawable.flower,R.drawable.ws,R.drawable.chars, R.drawable.ship,R.drawable.bells,R.drawable.gift,R.drawable.dj}; public ChristmasAdopter(Context context) { mContext = context; mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { return mResources.length; } @Override public boolean isViewFromObject(View view, Object object) { return view == ((LinearLayout) object); } @Override public Object instantiateItem(ViewGroup container, int position) { View itemView = mLayoutInflater.inflate(R.layout.pager_item, container, false); imageView = (ImageView) itemView.findViewById(R.id.imageView); imagepostion=position; imageView.setImageResource(mResources[position]); container.addView(itemView); return itemView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((LinearLayout) object); } // here is share content please tell me how i can share image which is show in imageView public void shareContent(){ Toast.makeText(mContext, ""+imagepostion, Toast.LENGTH_SHORT).show(); } private Bitmap getBitmapFromView(View view) { Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(returnedBitmap); Drawable bgDrawable =view.getBackground(); if (bgDrawable!=null) { bgDrawable.draw(canvas); } else{ canvas.drawColor(Color.WHITE); } view.draw(canvas); return returnedBitmap; } } }
1 Answer
In your ChristmasAdopter class, replace instantiateItem() with,
@Override public Object instantiateItem(ViewGroup container, int position) { View itemView = mLayoutInflater.inflate(R.layout.pager_item, container, false); imageView = (ImageView) itemView.findViewById(R.id.imageView); imagepostion=position; imageView.setImageResource(mResources[position]); imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //save image to device saveImage(); //share image code shareImageFromDevice(); } }); container.addView(itemView); return itemView; } private void saveImage(){ Bitmap bitmap = BitmapFactory.decodeResource(getResources(),mResources[position]); File image = new File(getExternalFilesDir(null), "test.png"); // After that, you just have to write the Bitmap thanks to its method compress such as: boolean success = false; // Encode the file as a PNG image. FileOutputStream outStream; try { outStream = new FileOutputStream(image); bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream); /* 100 to keep full quality of the image */ outStream.flush(); outStream.close(); success = true; } catch (IOException e) { e.printStackTrace(); } //Finally, just deal with the boolean result if needed. Such as: if (success) { Toast.makeText(getApplicationContext(), "Image saved with success", Toast.LENGTH_LONG).show(); } else { Toast.makeText(getApplicationContext(), "Error during image saving", Toast.LENGTH_LONG).show(); } } private void shareImageFromDevice(){ File file = new File(getExternalFilesDir(null), "test.png"); Uri uri=Uri.fromFile(file); Intent share = new Intent(Intent.ACTION_SEND); share.setType("image/*"); share.putExtra(Intent.EXTRA_STREAM, uri); startActivity(Intent.createChooser(share, "Share Image")); }
Archive from: https://stackoverflow.com/questions/59044874/android-share-image-from-url-using-array
from https://knowledgewiki.org/android-share-image-from-url-using-array/
0 notes
jeeteshsurana · 6 years ago
Text
tab layout in kotlin
https://ift.tt/2EP7gKN
Tab Layout in Kotlin
TabLayout Example
_________________________________________________________________________
1.fragment_shopping.xml
_________________________________________________________________________
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
        xmlns:android="https://ift.tt/nIICcg"
        xmlns:app="https://ift.tt/GEGVYd"
        xmlns:tools="https://ift.tt/LrGmb4"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
    <com.google.android.material.tabs.TabLayout
            android:id="@+id/tab_cart"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMode="fixed"
            tools:ignore="MissingConstraints"/>
    <androidx.viewpager.widget.ViewPager
            android:id="@+id/vp_cart"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            />
</androidx.appcompat.widget.LinearLayoutCompat>
________________________________________________________________________
2.Init in fragment()
_________________________________________________________________________
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.commonlibs.base.BaseFragment
import com.justcodenow.bynfor.R
import kotlinx.android.synthetic.main.fragment_shopping_cart.*
class ShoppingFragment : BaseFragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_shopping, container, false)
    }
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        init()
    }
    private fun init() {
        val fragmentAdapter = PagerAdapter(childFragmentManager)
        vp_cart.adapter = fragmentAdapter
        tab_cart.setupWithViewPager(vp_cart)
    }
}
_________________________________________________________________________
3.Adapter init()
_________________________________________________________________________
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
class PagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
    override fun getItem(position: Int): Fragment {
        return when (position) {
            0 -> {
                ItemFragment()
            }
            else -> {
                return SaveFragment()
            }
        }
    }
    override fun getCount(): Int {
        return 2
    }
    override fun getPageTitle(position: Int): CharSequence {
        return when (position) {
            0 -> "Item "
            else -> {
                return "Save "
            }
        }
    }
}
__________________________________________________________________________
via Blogger https://ift.tt/2EMmL63
0 notes
catzie · 7 years ago
Text
Android Kotlin: "overrides nothing" error appears on instantiateItem() function of PagerAdapter
Android Kotlin: “overrides nothing” error appears on instantiateItem() function of PagerAdapter
I just began learning Kotlin for work and one of the first errors I encountered is “overrides nothing” pointing at the overrides of the function instantiateItem() for my PagerAdapter
The function/method signature was like this:
override fun instantiateItem(parent: ViewGroup?, position: Int): Any {
To fix the error, I simply removed the question mark from the arguments so that it looked like:
View On WordPress
0 notes
iyarpage · 8 years ago
Text
ViewPager Tutorial: Getting Started in Kotlin
The ViewPager is a useful layout manager that helps you integrate horizontal swipe navigation in your app. It is a common way of creating slideshows, onboarding screens or tab views. Making use of the swipe gesture to navigate between ViewPager pages allows you to save screen space and create more minimal interfaces.
In this tutorial, you’ll become familiar with the ViewPager by modifying an existing app to make the UI more enjoyable. Along the way, you’ll also learn:
How the ViewPager works
How to keep it memory-efficient
How to add some nice features to your ViewPager
Note: This tutorial assumes you have previous experience with developing for Android in Kotlin. If you are unfamiliar with the language have a look at this tutorial. If you’re beginning with Android, check out some of our Getting Started and other Android tutorials.
Getting Started
Download the starter project and open it by starting Android Studio and selecting Open an existing Android Studio project:
Navigate to the sample project directory and click Open.
Take a look at the existing code before going on with the tutorial. Inside the assets directory, there is a JSON file containing some information about the top 5 most popular Android related movies ever made. :]
You can find the helper methods used to read the JSON data inside MovieHelper.kt. The Picasso library helps to easily download and display the images on the screen.
This tutorial uses fragments. If you are not familiar with fragments have a look at this tutorial. 
Build and Run the project.
The app consists of a few pages, each displaying some information about a movie. I bet the first thing you tried to do was swipe left to check out next movie! Or was it just me? For now, you can not-so-gracefully navigate between pages using the Previous and Next buttons at the bottom of the screen.
Introducing the ViewPager
Adding a ViewPager to the UI will allow the users to move forward or backward through the movies by swiping across the screen. You don’t have to deal with the slide animation and the swipe gesture detection, so the implementation is easier than you might think.
You’ll divide the ViewPager implementation into three parts:
Adding the ViewPager
Creating an Adapter for the ViewPager
Wiring up the ViewPager and the Adapter
Preparing the ViewPager
For step one, open MainActivity.kt and remove everything inside onCreate(), below this line:
val movies = MovieHelper.getMoviesFromJson("movies.json", this)
Remove the replaceFragment() method from the bottom of the class as well.
Now open activity_main.xml and replace everything inside the RelativeLayout with the following:
<android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_height="match_parent" android:layout_width="match_parent" />
Here you created the ViewPager view, which is now the only child of the RelativeLayout. Here’s how the xml file should look:
<RelativeLayout xmlns:android="http://ift.tt/1bfIhL2; xmlns:tools="http://ift.tt/2g3iXjS; android:layout_height="match_parent" android:layout_width="match_parent" tools:context="com.raywenderlich.favoritemovies.MainActivity"> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_height="match_parent" android:layout_width="match_parent" /> </RelativeLayout>
ViewPager is only available through the Android Support Library. The Android Support Library is actually a set of libraries that provide backward compatible implementations of widgets and other standard Android functionality. These libraries provide a common API that often allow the use of newer Android SDK features on devices that only support lower API levels. You should familiarize yourself with the Support Library and Support Library Packages.
Go back to MainActivity.kt and first import the ViewPager to be able to use it with this line:
import android.support.v4.view.ViewPager
Now you can add the following line at the top of the class to declare the ViewPager:
private lateinit var viewPager: ViewPager
Note: Use the keyword lateinit to avoid making the view nullable if you want to initialize it later. Read more about lateinit and other Kotlin modifiers here.
Add this line at the bottom of the onCreate() method to link your ViewPager reference to the xml view you created previously:
viewPager = findViewById(R.id.viewPager)
Implementing the PagerAdapter
Step one completed! You now have a ViewPager that doesn’t do anything particularly interesting without an Adapter that tells it what to display. If you run the app now you won’t be able to see any movies:
The ViewPager usually displays the “pages” using fragment instances, but it can also work with simple views such as ImageView if you want to display static content. In this project, you will display multiple things on each page. Fragments are here to help you.
You will connect your Fragment instances with the ViewPager using a PagerAdapter, which is an object that sits between the ViewPager and the data set containing the information you want the ViewPager to display (in this case the movies array). The PagerAdapter will create each Fragment, add the corresponding movie data to it and return it to the ViewPager.
PagerAdapter is an abstract class, so you will have an instance of one of its subclasses (FragmentPagerAdapter and FragmentStatePagerAdapter) rather than an instance of the PagerAdapter itself.
FragmentPagerAdapter or FragmentStatePagerAdapter?
There are two types of standard PagerAdapters that manage the lifecycle of each fragment: FragmentPagerAdapter and FragmentStatePagerAdapter. Both of them work well with fragments, but they are better suited for different scenarios:
The FragmentPagerAdapter stores the fragments in memory as long as the user can navigate between them. When a fragment is not visible, the PagerAdapter will detach it, but not destroy it, so the fragment instance remains alive in the FragmentManager. It will release it from memory only when the Activity shuts down. This can make the transition between pages fast and smooth, but it could cause memory issues in your app if you need many fragments.
The FragmentStatePagerAdapter makes sure to destroy all the fragments the user does not see and only keep their saved states in the FragmentManager, hence the name. When the user navigates back to a fragment, it will restore it using the saved state. This PagerAdapter requires much less memory, but the process of switching between pages can be slower.
It’s time to decide. Your list of movies has only five items, so the FragmentPagerAdapter might work after all. But what if you get bored after this tutorial and watch all Harry Potter movies? You’ll have to add 8 more items to the JSON file. What if you then decide to add your favorite TV series as well? That array can become pretty large. In this case, the FragmentStatePagerAdapter works better.
Creating a Custom FragmentStatePagerAdapter
In the project navigator pane, right-click on com.raywenderlich.favoritemovies and select New -> Kotlin File/Class. Name it MoviesPagerAdapter and select Class for Kind. Hit OK.
Replace the contents of this file with the following:
package com.raywenderlich.favoritemovies import android.support.v4.app.Fragment import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentStatePagerAdapter // 1 class MoviesPagerAdapter(fragmentManager: FragmentManager, private val movies: ArrayList<Movie>) : FragmentStatePagerAdapter(fragmentManager) { // 2   override fun getItem(position: Int): Fragment { return MovieFragment.newInstance(movies[position]) } // 3   override fun getCount(): Int { return movies.size } }
Let’s go over this step-by-step.
Your new class extends FragmentStatePagerAdapter. The constructor of the superclass requires a FragmentManager, thus your custom PagerAdapter needs it as well. You also need to provide the list of movies as a parameter.
Return the fragment associated with the object located at the specified position.
Return the number of objects in the array.
When the ViewPager needs to display a fragment, it initiates a chat with the PagerAdapter. First, the ViewPager asks the PagerAdapter how many movies are in the array by calling getCount(). Then it will call getItem(int position) whenever a new page is about to be visible. Within this method, the PagerAdapter creates a new fragment that displays the information about the movie at the correct position in the array. 
Connecting the PagerAdapter and the ViewPager
Open MainActivity.kt and add the following line at the top to declare your MoviesPagerAdapter:
private lateinit var pagerAdapter: MoviesPagerAdapter
Next add the following inside onCreate(), beneath the existing code:
pagerAdapter = MoviesPagerAdapter(supportFragmentManager, movies) viewPager.adapter = pagerAdapter
This initializes your MoviesPagerAdapter and connects it to the ViewPager. 
Note: supportFragmentManager is equivalent to the getSupportFragmentManager() method you would use in Java and viewPager.adapter = pagerAdapter is the same as viewPager.setAdapter(pagerAdapter). Read more about getters and setters in Kotlin here.
Build and run. The app should behave like the original version, but you can now navigate between movies by swiping rather than pressing buttons :].
Note: Using the FragmentStatePagerAdapter saves you from having to deal with saving the current page across a runtime configuration change, like rotating the device. The state of the Activity is usually lost in those situations and you would have to save it in the Bundle object passed as a parameter in onCreate(savedInstanceState: Bundle?). Luckily, the PagerAdapter you used does all the work for you. You can read more about the savedInstanceState object and the Activity lifecycle here.
Endless Scrolling
A nice feature you often see is being able to swipe continuously between pages in a circular manner. That is going to the last page when swiping right on the first one and going to the first one when swiping left on the last. For example, swiping between 3 pages would look like this: 
Page1 -> Page2 -> Page3 -> Page1 -> Page2
Page2 <- Page1 <- Page3 <- Page2 <- Page1
The FragmentStatePagerAdapter will stop creating new fragments when the current index reaches the number of objects returned by getCount(), so you need to change the method to return a fairly large number that the users are not very likely to reach by continuously swiping in the same direction. That way the PagerAdapter will keep creating pages until the page index reaches the value returned by getCount().
Open MoviesPagerAdapter.kt and create a new constant representing the large number by adding this line at the top of the file above the class definition:
private const val MAX_VALUE = 200
Now replace the return movies.size line inside getCount() with this:
return movies.size * MAX_VALUE
By multiplying the length of the array with MAX_VALUE, the swipe limit will grow proportionally to the number of movies in your list. This way you don’t have to worry about getCount() returning a number that is less than the number of movies as your movie list grows.
The only problem you now have is inside the Adapter’s getItem(position: Int) method. Since getCount() now returns a number larger than the size of the list, the ViewPager will try to access the movie at an index greater than the array size when the user swipes past the last movie.
Replace the code inside getItem(position: Int) with this line:
return MovieFragment.newInstance(movies[position % movies.size])
This will ensure that the ViewPager doesn’t request the element at an index larger than movies.size because the remainder after you divide the position by movies.size will always be greater than or equal to 0 and less than movies.size.
Right now the infinite scrolling works only when the user navigates forward through the array (swipes left). That is because, when your app starts, the ViewPager displays the movie at index 0. To fix this issue, open MainActivity.kt and add the following line inside onCreate() below the line where you connect the PageAdapter to the ViewPager: 
viewPager.currentItem = pagerAdapter.count / 2
This tells the ViewPager to display the movie found in the middle of the array. The user has now plenty of swiping to do in either direction before they reach an end. To ensure that the movie displayed at the beginning will still be the first one in your list, set MAX_VALUE to be an even number (in this case 200 works fine). This way, after you divide pagerAdapter.count by 2, pagerAdapter.count % movies.size = 0 (which is the first index that the ViewPager asks for when the app starts).
Build and run. You should now be able to swipe left and right a decent amount of times and the movies will start again from the beginning after you reach the last one and from the end when you reach the first one.
Adding Tabs
A TabLayout is a nice feature that makes it easy to explore and switch between pages. The TabLayout contains a tab for each page, which usually displays the page title. The user can tap on a tab to navigate directly to the desired page or can use a swipe gesture over the TabLayout to switch between pages.
If you try to add a TabLayout to your ViewPager you won’t be able to see any tabs because the layout will be automatically populated with as many tabs as the FragmentStatePagerAdapter tells it by calling the getCount() method, which now returns a pretty large number. Trying to fit that many tabs on your screen will make them really narrow.
Luckily, there is a third party library called RecyclerTabLayout that solves this problem. The library uses the RecyclerView in its implementation. You can learn more about the mysterious RecyclerView from this tutorial. To install the library, open up build.grade (Module: app) and add the following line inside dependencies:
implementation 'com.nshmura:recyclertablayout:1.5.0'
The recyclertablayout library uses an old version of the Android Support Libraries, so you’ll need to add the following to make the Gradle sync happy:
implementation 'com.android.support:recyclerview-v7:26.1.0'
Tap Sync Now on the yellow pop-up and wait until Android Studio installs the library.
Open activity_main.xml and paste the following snippet above the ViewPager:
<com.nshmura.recyclertablayout.RecyclerTabLayout android:id="@+id/recyclerTabLayout" android:layout_height="@dimen/tabs_height" android:layout_width="match_parent" />
Now add the following property to your ViewPager to align it below the RecyclerTabLayout:
android:layout_below="@id/recyclerTabLayout"
Your whole layout file should now look like this:
<RelativeLayout xmlns:android="http://ift.tt/1bfIhL2; xmlns:tools="http://ift.tt/2g3iXjS; android:layout_height="match_parent" android:layout_width="match_parent" tools:context="com.raywenderlich.favoritemovies.MainActivity"> <com.nshmura.recyclertablayout.RecyclerTabLayout android:id="@+id/recyclerTabLayout" android:layout_height="@dimen/tabs_height" android:layout_width="match_parent" /> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_below="@id/recyclerTabLayout" android:layout_height="match_parent" android:layout_width="match_parent" /> </RelativeLayout>
Open MainActivity.kt and import RecyclerTabLayout at the top of the file, like this:
import com.nshmura.recyclertablayout.RecyclerTabLayout
Now add the following at the top of the class to declare a RecyclerTabLayout instance:
private lateinit var recyclerTabLayout: RecyclerTabLayout
Add this block of code inside onCreate(), above the line where you set viewPager.currentItem:
recyclerTabLayout = findViewById(R.id.recyclerTabLayout) recyclerTabLayout.setUpWithViewPager(viewPager)
The first line connects your RecyclerTabLayout instance to the xml view and the second one links the RecyclerTabLayout to your ViewPager.
The last thing you have to do is let the RecyclerTabLayout know what titles to display on the Tabs. Open MoviesPagerAdapter.kt and add the following method inside the class:
override fun getPageTitle(position: Int): CharSequence { return movies[position % movies.size].title }
This method tells the TabLayout what to write on the tab placed at a particular position. It returns the title of the movie that corresponds with the fragment created inside getItem(position: Int).
Run the app. You should be able to see the tabs changing as you swipe through the pages. Try tapping on a tab and see how the ViewPager will scroll automatically to the corresponding movie :].
Where to Go From Here?
You can download the final project for this tutorial here.
Nice job! You’ve modified an app and gave it a nicer UI with the help of ViewPager. You’ve also added a pretty cool TabLayout and implemented the endless scroll. In addition, you learned about the PagerAdapter and had to choose which of the FragmentPagerAdapter and FragmentStatePagerAdapter is best for you application. 
If you want to read more about the ViewPager have a look at the documentation. You can try and customize the transition animation with the help of PageTransformer. Check out this tutorial for that.
Bonus challenge: You can implement dot indicators for your pages as seen in many onboarding flows. Here you can find a nice way of creating dot indicators. Note that this solution won’t work with your final ViewPager from this tutorial as it needs PagerAdapter‘s getCount() method to return the exact number of pages. You can try implementing the indicators instead of the endless scroll. This time try using the default TabLayout instead of the third party library. You can download the solution here.
Feel free to join the forum discussion below if you have any comments or questions! :]
The post ViewPager Tutorial: Getting Started in Kotlin appeared first on Ray Wenderlich.
ViewPager Tutorial: Getting Started in Kotlin published first on http://ift.tt/2fA8nUr
0 notes
shareandopen · 13 years ago
Text
為何ViewPager的PagerAdapter.notifyDataSetChanged()無作用?
=======下列為最簡單且暫時能夠解決nofifyDataSetChanged無作用的問題,但如果view pager有很多複雜的view所組成,會有效能上的問題,請注意。=======
如果沒有用過Android ViewPager的開發者們,可以先參考官方的介紹與文件說明(雖然現在官方因為推廣Fragment更推荐使用FragmentPagerAdapter,看來又要花��間了解一下了XDD)。除了官方說明之外,我之前也有介紹一些相關文章,像是如何使用Vertical View Pager、如何取得View Pager當中的child view、如何讓ViewPager有彈回效果。
回歸正題,為何直接呼叫PagerAdapter.notifyDataSetChanged()會無作用呢?主要是因為在運作當中會呼叫到getItemPosition (Object object),sdk文件說明當中也提到
Called when the host view is attempting to determine if an item's position has changed. Returns POSITION_UNCHANGED if the position of the given item has not changed or POSITION_NONE if the item is no longer present in the adapter.
如果有參考sdk文件說明的人,眼尖的人會看到這一行
The default implementation assumes that items will never change position and always returns POSITION_UNCHANGED.
預設值是POSITION_UNCHANGED,代表此item內容並沒有更新
所以這時就要對你的ViewPagerAdapter動一些手腳,這時需要改寫getItemPosition():
@Override public int getItemPosition(Object object) { // 回傳POSITION_NONE告知此item已經不在Adapter裡 return POSITION_NONE; }
因為已經改寫getItemPosition為強制回傳POSITION_NONE,如果一來,每次呼叫notifyDataSetChanged,就會重新繪製ViewPager。
這些參考方式,是從stakeoverflow學習到的,在這邊將學習心得分享給大家。
0 notes
android-arsenal · 8 years ago
Text
LoopingViewPager
A ViewPager and a PagerAdapter that can:
AutoScroll (On/Off able)
Infinite Loop (On/Off able)
ViewPager's height can be wrap_content
Adjustable auto scroll interval
Won't scroll nor loop if there is only 1 item
Works well with notifyDataSetChanged()
Supports page indicators
from The Android Arsenal http://ift.tt/2p05i4z
0 notes