One of the common features in Android applications is swiping to change texts, images, buttons or complex combinations of those. In today's tutorial, I will show you how to do that in Kotlin programming language and Android studio 3.4.1.
Firstly, create a blank Android project (remember to choose Kotlin as the language) with an empty main activity; there will be two files created, MainActivity.kt for the activity and activity_main.xml for the layout of the activity.
To be able to swipe to change fragment (you can put texts, images, buttons, etc into a fragment), we need add view android.support.v4.view.ViewPager as a place holder of the fragment. We then can pass the fragment that we want to render to the ViewPager adapter which is linked to the ViewPager view.
Let's start by creating the layout for the main activity with ViewPager view on top of a simple text view. The layout code for the main activity is shown below.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<android.support.constraint.ConstraintLayout | |
xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:tools="http://schemas.android.com/tools" | |
xmlns:app="http://schemas.android.com/apk/res-auto" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
tools:context=".MainActivity"> | |
<android.support.v4.view.ViewPager | |
android:id="@+id/vpImages" | |
android:layout_width="0dp" | |
android:layout_height="0dp" | |
app:layout_constraintBottom_toTopOf="@id/txtIntro" | |
app:layout_constraintLeft_toLeftOf="parent" | |
app:layout_constraintRight_toRightOf="parent" | |
app:layout_constraintTop_toTopOf="parent" | |
/> | |
<TextView | |
android:id="@+id/txtIntro" | |
android:layout_width="0dp" | |
android:layout_height="0dp" | |
android:text="Swipe the green area above to change fragment" | |
android:gravity="center" | |
app:layout_constraintBottom_toBottomOf="parent" | |
app:layout_constraintLeft_toLeftOf="parent" | |
app:layout_constraintRight_toRightOf="parent" | |
app:layout_constraintTop_toBottomOf="@+id/vpImages" | |
/> | |
</android.support.constraint.ConstraintLayout> |
The next step is to create the image fragment that shows the name of an image. There will be two files created, ImagesFragment.kt for the fragment and fragment_images.xml for the layout of the fragment. The image fragment class can be used to return a new image fragment instance with a new image name as the input parameter; this input parameter is then used to change the content of the only text view inside the image fragment. It is important to know that a fragment needs to be inflated to a view in onCreateView function before its children views (e.g., a text view in our case) can be accessed in onViewCreated function. Let's have a look at the image fragment class and layout.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:tools="http://schemas.android.com/tools" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
tools:context=".ImagesFragment" | |
android:background="@color/colorPrimaryDark"> | |
<TextView | |
android:id="@+id/txt_frag" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="@string/hello_blank_fragment" | |
android:layout_gravity="center" | |
android:textColor="@color/colorWhite" | |
/> | |
</FrameLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.os.Bundle | |
import android.support.v4.app.Fragment | |
import android.view.LayoutInflater | |
import android.view.View | |
import android.view.ViewGroup | |
import android.widget.TextView | |
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER | |
private const val ARG_IMAGE = "param1" | |
/** | |
* A simple [Fragment] subclass. | |
* Use the [ImagesFragment.newInstance] factory method to | |
* create an instance of this fragment. | |
*/ | |
class ImagesFragment : Fragment() { | |
private var image: String? = null | |
//private var listener: OnFragmentInteractionListener? = null | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
arguments?.let { | |
image = it.getString(ARG_IMAGE) | |
} | |
} | |
override fun onCreateView( | |
inflater: LayoutInflater, container: ViewGroup?, | |
savedInstanceState: Bundle? | |
): View? { | |
// Inflate the layout for this fragment | |
return inflater.inflate(R.layout.fragment_images, container, false) | |
} | |
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | |
super.onViewCreated(view, savedInstanceState) | |
var txt_frag:TextView = view.findViewById(R.id.txt_frag) | |
txt_frag.text = this.image.toString() | |
} | |
companion object { | |
/** | |
* Use this factory method to create a new instance of | |
* this fragment using the provided parameters. | |
* | |
* @param ARG_IMAGE Image name for the fragment. | |
* @return A new instance of fragment ImagesFragment. | |
*/ | |
@JvmStatic | |
fun newInstance(imageName: String) = | |
ImagesFragment().apply { | |
arguments = Bundle().apply { | |
putString(ARG_IMAGE, imageName) | |
} | |
} | |
} | |
} |
The next step is to create the ViewPager adapter to control which fragment will be rendered in the ViewPager view. It is important to know that there are two types of adapters for different situations, FragmentPagerAdapter (fragments are stored in memory until the activity shuts down) and FragmentStatePagerAdapter (fragments that user does not see are destroyed). The source code for the adapter is shown below.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.support.v4.app.Fragment | |
import android.support.v4.app.FragmentManager | |
import android.support.v4.app.FragmentStatePagerAdapter | |
class ViewPagerAdapter(supportFragmentManager: FragmentManager) : FragmentStatePagerAdapter(supportFragmentManager) { | |
override fun getItem(position: Int): Fragment { | |
if(position == 0) | |
return ImagesFragment.newInstance("I am the image of fragment 1") | |
else if(position == 1) | |
return ImagesFragment.newInstance("I am the image of fragment 2") | |
return ImagesFragment.newInstance("I am the image of fragment 3") | |
} | |
override fun getCount(): Int { | |
return 3 | |
} | |
} |
The final step is to go back to the main activity and create the link between the ViewPager view and the ViewPager adapter. The source code for this step is shown below.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.support.v7.app.AppCompatActivity | |
import android.os.Bundle | |
import android.support.v4.view.ViewPager | |
class MainActivity : AppCompatActivity() { | |
private lateinit var viewPager: ViewPager | |
private lateinit var pagerAdapter: ViewPagerAdapter | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_main) | |
viewPager = findViewById(R.id.vpImages) | |
pagerAdapter = ViewPagerAdapter(supportFragmentManager) | |
viewPager.adapter = pagerAdapter | |
} | |
} |
Our app is ready to run now!!!
No comments:
Post a Comment