在之前两篇文章中,介绍了Android中网球请求的实现,那么本篇文章中,我们实现下现在APP中最通用的Tabbar的实现:
Tabbar1.0
以前的项目中Tabbar是使用Gridview实现,这里贴出部分代码:
首先定义一个Tab的model类:
open class Tab(var res: Int,
var selRes: Int, var name: String,
var tag:String,var f: Fragment) {}
Activity中的布局activity_home为:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content">
<include layout="@layout/toolbar" android:id="@+id/tool"/>
<GridView android:background="@color/white" android:layout_alignParentBottom="true"
android:numColumns="4" android:id="@+id/gridGv"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout android:layout_below="@id/tool" android:layout_above="@id/gridGv"
android:id="@+id/frameLayout" android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
HomeActivity,其中当用户未登录时,则跳到LoginActivity
class HomeActivity : BaseActivity() {
internal var items = listOf(
Tab(R.mipmap.ic_home, R.mipmap.ic_home_sel, "首页", "index", HomeFragment.getInstance()),
Tab(R.mipmap.ic_product, R.mipmap.ic_product_sel, "产品", "product", ProductFragment.getInstance()),
Tab(R.mipmap.ic_cart, R.mipmap.ic_cart_sel, "购物车", "cart", CartFragment.getInstance()),
Tab(R.mipmap.ic_user, R.mipmap.ic_user_sel, "我的", "me", MeFragment.getInstance()))
var adapter: TabAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
adapter = TabAdapter(this)
adapter!!.addAll(items)
gridGv.gravity = Gravity.CENTER
gridGv.selector = ColorDrawable(Color.TRANSPARENT)
toFragment(items[0].f, R.id.frameLayout)
gridGv.adapter = adapter
initTitle("首页")
gridGv.onItemClick { adapterView, view, i, l ->
if (items[i].tag.equals("me") && TextUtils.isEmpty(Preference.with(this).token) ) {
startActivity<LoginActivity>()
return@onItemClick
}
toFragment(items[i].f, R.id.frameLayout)
initTitle(items[i].name)
adapter?.pos = i
adapter?.notifyDataSetChanged()
}
adapter!!.notifyDataSetChanged()
}
fun toFragment(f: Fragment, id: Int) {
val transaction = fragmentManager.beginTransaction()
transaction.replace(id, f)
transaction.commit()
}
}
TabAdapter
/**
* Created by vslimit on 16/1/15.
*/
class TabAdapter(context: Context) : ArrayAdapter<Tab>(context, 0) {
val inflater = LayoutInflater.from(context)
var pos: Int = 0
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val item = getItem(position)
val view = convertView ?: inflater.inflate(R.layout.item_tab_menu, parent, false)
val nameView = view.findViewById(R.id.item_text) as TextView
val imageView = view.findViewById(R.id.item_image) as ImageView
nameView.text = item.name
nameView.textColor = if (position == pos) context.resources.getColor(R.color.head_orange) else context.resources.getColor(R.color.product_name_black)
imageView.imageResource = if (position == pos) item.selRes else item.res
return view
}
这样基于Gridview已经实现了,但是,考虑到RecycleView比较流行,于是在新的版本中,使用了RecycleView来实现,并对其中的部分实现进行了优化,下面我们来看Tabbar2.0
Tabbar2.0
Tab类是预定好的,并且是有序的,因此,采用enum来实现:
package com.vslimit.kotlindemo.model
import com.vslimit.kotlindemo.R
import com.vslimit.kotlindemo.fragment.BaseFragment
import com.vslimit.kotlindemo.fragment.MainFragment
import com.vslimit.kotlindemo.fragment.ProductFragment
/**
* Created by vslimit on 16/12/2.
*/
enum class TabTagEnum (val text: String, val res: Int, val selRes: Int, val fragment: BaseFragment) {
HOME("首页", R.mipmap.ic_home, R.mipmap.ic_home_sel, MainFragment.getInstance()), PRODUCT("发现", R.mipmap.ic_product, R.mipmap.ic_product_sel, ProductFragment.getInstance()), CART("购物车", R.mipmap.ic_cart, R.mipmap.ic_cart_sel, MainFragment.getInstance()), ME("我的", R.mipmap.ic_user, R.mipmap.ic_user_sel, MainFragment.getInstance())
}
Activity布局activity_main
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".activity.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/tabRv"
android:layout_width="match_parent"
android:layout_height="49dp"
android:layout_alignParentBottom="true"
android:background="@android:color/white"/>
<View android:layout_width="match_parent" android:layout_height="1dp" android:layout_above="@id/tabRv" android:id="@+id/line" android:background="@android:color/black"/>
<FrameLayout android:layout_above="@id/line"
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
MainActivity之前使用replace,remove来进行Fragment的替换,但是,考虑到性能优化,改用hide,show的方式,可这样处理容易导致fragment重叠问题,这里使用了@YoKey 的文章中的方式进行处理,详见传送门。
package com.vslimit.kotlindemo.activity
import android.os.Bundle
import android.support.annotation.Nullable
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentTransaction
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.GridLayoutManager
import com.vslimit.kotlindemo.R
import com.vslimit.kotlindemo.model.TabTagEnum
import com.vslimit.kotlindemo.adapter.TabAdapter
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.AnkoLogger
import org.jetbrains.anko.info
class MainActivity : AppCompatActivity(), AnkoLogger {
internal var items = TabTagEnum.values().asList()
var adapter: TabAdapter? = null
override fun onCreate(@Nullable savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
initFragment(TabTagEnum.HOME.fragment)
}
val layoutManager: GridLayoutManager = GridLayoutManager(this, 4)
tabRv.layoutManager = layoutManager
adapter = TabAdapter(items) {
switchContent(items[adapter!!.pos].fragment, it.fragment)
adapter!!.pos = it.ordinal
adapter!!.notifyDataSetChanged()
}
tabRv.adapter = adapter
adapter!!.notifyDataSetChanged()
info("onCreate")
}
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
super.onRestoreInstanceState(savedInstanceState)
info("onRestoreInstanceState")
}
override fun onStart() {
super.onStart()
info("onStart")
}
override fun onResume() {
super.onResume()
info("onResume")
}
override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)
info("onSaveInstanceState")
}
override fun onPause() {
super.onPause()
info("onPause")
}
override fun onStop() {
super.onStop()
info("onStop")
}
override fun onDestroy() {
super.onDestroy()
info("onDestroy")
}
fun switchContent(from: Fragment, to: Fragment) {
val fm: FragmentManager = supportFragmentManager
//添加渐隐渐现的动画
val ft: FragmentTransaction = fm.beginTransaction()
if (!to.isAdded) {
// 先判断是否被add过
ft.hide(from).add(R.id.frameLayout, to) // 隐藏当前的fragment,add下一个到Activity中
} else {
ft.hide(from).show(to) // 隐藏当前的fragment,显示下一个
}
ft.commit()
}
fun initFragment(to: Fragment) {
val fm: FragmentManager = supportFragmentManager
//添加渐隐渐现的动画
// val ft: FragmentTransaction = fm.beginTransaction()
fm.beginTransaction().add(R.id.frameLayout, to).commit()
}
}
TabAdapter
package com.vslimit.kotlindemo.adapter
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import com.vslimit.kotlindemo.R
import com.vslimit.kotlindemo.extensions.ctx
import com.vslimit.kotlindemo.model.TabTagEnum
import kotlinx.android.synthetic.main.tab_item_menu.view.*
import org.jetbrains.anko.imageResource
import org.jetbrains.anko.layoutInflater
import org.jetbrains.anko.onClick
/**
* Created by vslimit on 16/12/2.
*/
class TabAdapter(val items: List<TabTagEnum>, val itemClick: (TabTagEnum) -> Unit) : RecyclerView.Adapter<TabAdapter.ViewHolder>() {
var pos: Int = TabTagEnum.HOME.ordinal
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = parent.ctx.layoutInflater.inflate(R.layout.tab_item_menu, parent, false)
return ViewHolder(view, itemClick)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindForecast(items[position], pos == position)
}
override fun getItemCount() = items.size
class ViewHolder(view: View, val itemClick: (TabTagEnum) -> Unit) : RecyclerView.ViewHolder(view) {
fun bindForecast(item: TabTagEnum, flag: Boolean) {
with(item) {
itemView.item_image.imageResource = if (flag) item.selRes else item.res
itemView.item_text.text = item.text
itemView.onClick { itemClick(item) }
}
}
}
}
至此,基于RecycleView的Tabbar已经实现,效果如图:
RecycleView的代码详见:https://github.com/vslimit/kotlindemo
网友评论