各大應用市場應用首頁實現的功能樣式都差不多,無非就是倒計時和廣告。雖然以前一直都是Java的語言爲基礎開發的手機應用程序,谷歌推出的科特林語言也在應用開發的語言選擇中使用起來,以Java的語言爲基礎的安卓與科特林有語言上的一些差異,不過稍微細心的對比起來學習並開發,並非難事下圖是UI給出的界面,需要用科特林語言來進行實現:
在看界面UI之面,第一步:想到是佈局,佈局是傳遞給活動重寫方法onCreate方法內部調用的setContentView的參數值。第二步:我們需要實現又上角的倒計時【倒計時需要用到CountDownTimer(long millisInFuture,long countDownInterval),millisInFuture表示:從調用start()到onFinish()的時間段,countDownInterval表示:onTick(millisUntilFinished:Long)收到倒計時回調後的時間間隔,注意:需要在Activity onDestroy( )回調方法中執行CountDownTimer(倒計時)的回調方法取消()進行倒計時的銷燬。第三步:使用控件ViewPager實現廣告頁,並實現ViewPager滑動監聽事件OnPageChangeListener,滑動到不同位置的廣告頁順便帶動底部不同位置的長條狀態的切換。】
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/vp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
</android.support.v4.view.ViewPager>
<com.midai.goodbabymall.widget.IndicatorView
android:id="@+id/indicatorView"
android:layout_width="wrap_content"
android:layout_height="@dimen/comm_30dp"
android:layout_marginBottom="@dimen/comm_20dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true">
</com.midai.goodbabymall.widget.IndicatorView>
<TextView
android:id="@+id/skipBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="@dimen/comm_90dp"
android:minHeight="@dimen/comm_30dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginTop="@dimen/comm_20dp"
android:layout_marginRight="@dimen/comm_20dp"
android:layout_marginEnd="@dimen/comm_20dp"
android:background="@drawable/bg_rectangle_corner_2dp_solid_transpant_gray"
android:gravity="center"
android:textSize="@dimen/text_size_14sp"
android:textColor="@color/font_gray2"
android:text="5秒後跳過"
/>
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
倒計時執行過程:在onStart() - >的onClick() - > onFinish() - >取消(),在onStart()和取消()爲手動調用,的onClick()和onFinish()爲倒計時在指定的時間段和時間間隔執行過程中,結束的回調方法。
未來的毫秒數將形成對{@ link #start()}的調用,直到倒計時結束,並且調用{@link #onFinish()}。(大概念意思:從start()調用到直到倒計時完成並調用onFinish()的毫秒數)
The interval along the way to receive {@link #onTick(long)} callbacks.(大概意思:onTick()被回調的時間間隔。)
調用onStart() - > onFinish()執行過程的日誌信息(我設置的時間段是5000毫秒,時間間隔1000毫秒):
倒計時創建代碼片段,onTick回調方法中獲取到的毫秒值/ 1000拿到整數值爲秒,onFinish回調方法表示倒計時時間端結束,可以執行活動跳轉(比如跳轉到首頁)或者其他操作:
mCount = object : CountDownTimer(5000,1000){
override fun onTick(millisUntilFinished: Long) {
skipBtn.text = "${millisUntilFinished / 1000}秒後跳過"
Timber.i(javaClass.name+"onTick()當前毫秒值:"+millisUntilFinished)
}
override fun onFinish() {
skipBtn.text = "0秒後跳過"
Timber.i(javaClass.name+"onFinish()")
startActivity<MainActivity>()
finish()
}
}
mCount.start()
執行倒計時銷燬:
override fun onDestroy() {
mCount.cancel()
super.onDestroy()
}
廣告頁:爲ViewPager添加滑動監聽事件和創建PagerAdapter適配器:
class SplashActivity : BaseActivity(),ViewPager.OnPageChangeListener{
private lateinit var mAdapter : SplashAdapter
private lateinit var mCount : CountDownTimer
.........................
//todo 測試數據
val list = mutableListOf("","","")
mAdapter = SplashAdapter(mContext,list)
indicatorView.initView(list.size)
vp.adapter = mAdapter
vp.addOnPageChangeListener(this)
..............................
}
override fun onPageScrollStateChanged(state: Int) {
}
override fun onPageScrolled(position: Int, positionOffset: Float
positionOffsetPixels: Int) {
}
override fun onPageSelected(position: Int) {
vp.currentItem = position
indicatorView.updatePosition(position)
}
import android.content.Context
import android.support.v4.view.PagerAdapter
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import com.midai.goodbabymall.R
import com.midai.goodbabymall.util.GlideUtils
import timber.log.Timber
class SplashAdapter (val context: Context, val mList : MutableList<String>) : PagerAdapter() {
/**
* 該回調方法執行圖片的與預加載,一般預加載2張圖片
* getCount()=0:不執行
* getCount()=1:執行1次
* getCount>=2:執行2次
*/
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val image = ImageView(context)
image.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)
GlideUtils.setImageUri(context,image, R.mipmap.product_def_big)
container.addView(image)
Timber.i(javaClass.name+"instantiateItem");
return image
}
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view == `object`
}
override fun getCount(): Int {
return mList.size;
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
container.removeView(`object` as View)
}
}
底部滾動條切換:
import android.content.Context
import android.support.annotation.DrawableRes
import android.util.AttributeSet
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import com.midai.goodbabymall.R
/**
* 廣告頁橫條
*/
class IndicatorView : LinearLayout{
constructor(context: Context) : this(context,null)
constructor(context: Context,attributeSet: AttributeSet?) : this(context,attributeSet,0)
constructor(context: Context,attributeSet: AttributeSet?, defStyleAttr : Int) : super(context,attributeSet,defStyleAttr)
@DrawableRes var checkedResId : Int = R.drawable.indicator_rectangle_check_orange
@DrawableRes var unCheckdResId : Int = R.drawable.indicator_rectangle_check_black
private var adIndicatorIVs : MutableList<ImageView>? = null
fun initView(size : Int) {
removeAllViews()
if (size <= 1){
return
}
adIndicatorIVs = mutableListOf()
for (i in 0 until size){
// 有多少張圖片就new多少次
val layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
// 設置每個小圓點距離左邊的中間Lin
layoutParams.setMargins(14, 0, 0, 0)
val imageView = ImageView(context)
// 設置小圓點的寬高
imageView.layoutParams = ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
adIndicatorIVs!!.add(imageView)
if (i == 0) {
// 默認第一張圖片
adIndicatorIVs!![i].setBackgroundResource(checkedResId)
} else {
// 其他圖片都未選中狀態
adIndicatorIVs!![i].setBackgroundResource(unCheckdResId)
}
addView(adIndicatorIVs!![i], layoutParams)
}
}
/**
* 更新位置
*/
fun updatePosition(position: Int){
if (null != adIndicatorIVs){
for (it in 0 until adIndicatorIVs!!.size){
if (position == it){
adIndicatorIVs!![it].setBackgroundResource(checkedResId)
} else {
adIndicatorIVs!![it].setBackgroundResource(unCheckdResId)
}
}
}
}
indicator_rectangle_check_orange.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size android:height="@dimen/comm_2dp"
android:width="@dimen/comm_30dp"/>
<solid android:color="@color/main_bottom_navigator_blood_orange"/>
</shape>
indicator_rectangle_check_black.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size android:height="@dimen/comm_2dp"
android:width="@dimen/comm_30dp"/>
<solid android:color="@color/bg_black"/>
</shape>