GoodsAdapter.kt单个产品条目的adapter,添加和减少的逻辑的实现,包括特效的实现
package com.example.takeout.ui.adapter
import android.graphics.Color
import android.graphics.Paint
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.*
import android.widget.BaseAdapter
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.FragmentActivity
import com.example.takeout.R
import com.example.takeout.model.beans.GoodsInfo
import com.example.takeout.ui.activity.BusinessActivity
import com.example.takeout.ui.fragment.GoodsFragment
import com.example.takeout.utils.PriceFormater
import com.example.takeout.utils.TakeoutApp
import com.squareup.picasso.Picasso
import org.jetbrains.anko.find
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter
class GoodsAdapter(val context: FragmentActivity?, val goodsFragment: GoodsFragment) : BaseAdapter(), StickyListHeadersAdapter {
val host = "http://127.0.0.1:8090/image?name="
val DURATION: Long = 1000 //持续时间
var goodsList: List<GoodsInfo> = ArrayList()
fun setDatas(goodsInfoList: List<GoodsInfo>) {
this.goodsList = goodsInfoList
notifyDataSetChanged()
}
inner class GoodsItemHolder(itemView: View) : View.OnClickListener {
override fun onClick(v: View?) {
var isAdd: Boolean = false
when (v?.id) {
R.id.ib_add -> {
isAdd = true
doAddOperation()
}
R.id.ib_minus -> doMinusOperation()
}
processRedDotCount(isAdd)
}
private fun processRedDotCount(isAdd: Boolean) {
//找到此商品属于的类别
val typeId = goodsInfo.typeId
//找到此类别在左侧列表中的位置(遍历)
val typePosition = goodsFragment.goodsFragmentPresenter.getTypePositionByTypeId(typeId)
//最后找出tvRedDotCount
val goodsTypeInfo = goodsFragment.goodsFragmentPresenter.goodstypeList.get(typePosition)
var redDotCount = goodsTypeInfo.redDotCount
if (isAdd) {
redDotCount++
} else {
redDotCount--
}
goodsTypeInfo.redDotCount = redDotCount
//刷新左侧列表
goodsFragment.goodsTypeAdapter.notifyDataSetChanged()
}
private fun doMinusOperation() {
//改变count值
var count = goodsInfo.count
if (count == 1) {
//最后一次点击减号执行动画集
val hideAnimationSet: AnimationSet = getHideAnimation()
tvCount.startAnimation(hideAnimationSet)
btnMinus.startAnimation(hideAnimationSet)
//删除缓存
// TakeoutApp.sInstance.deleteCacheSelectedInfo(goodsInfo.id)
}else{
//更新缓存
// TakeoutApp.sInstance.updateCacheSelectedInfo(goodsInfo.id, Constants.MINUS)
}
count--
//改变数据层
goodsInfo.count = count
notifyDataSetChanged()
}
private fun doAddOperation() {
//改变count值
var count = goodsInfo.count
if (count == 0) {
//第一次点击加号执行动画集
val showAnimationSet: AnimationSet = getShowAnimation()
tvCount.startAnimation(showAnimationSet)
btnMinus.startAnimation(showAnimationSet)
//添加缓存
// TakeoutApp.sInstance.addCacheSelectedInfo(CacheSelectedInfo(goodsInfo.sellerId,goodsInfo.typeId,goodsInfo.id,1))
}else{
//更新缓存
// TakeoutApp.sInstance.updateCacheSelectedInfo(goodsInfo.id, Constants.ADD)
}
count++
//改变数据层
goodsInfo.count = count
notifyDataSetChanged()
//抛物线
//1.克隆+号,并且添加到acitivty上
var ib = ImageButton(context)
//大小,位置、背景全部相同
ib.setBackgroundResource(R.mipmap.button_add)
// btnAdd.width
val srcLocation = IntArray(2)
btnAdd.getLocationInWindow(srcLocation)
Log.e("location", srcLocation[0].toString() + ":" + srcLocation[1])
ib.x = srcLocation[0].toFloat()
ib.y = srcLocation[1].toFloat()
(goodsFragment.activity as BusinessActivity).addImageButton(ib, btnAdd.width, btnAdd.height)
//2.执行抛物线动画(水平位移,垂直加速位移)
val destLocation = (goodsFragment.activity as BusinessActivity).getCartLocation()
val parabolaAnim: AnimationSet = getParabolaAnimation(ib, srcLocation, destLocation)
ib.startAnimation(parabolaAnim)
//3.动画完成后回收克隆的+号
}
/**
* 抛物线动画
*/
private fun getParabolaAnimation(ib: ImageButton, srcLocation: IntArray, destLocation: IntArray): AnimationSet {
val parabolaAnim: AnimationSet = AnimationSet(false)
parabolaAnim.duration = DURATION
val translateX = TranslateAnimation(
Animation.ABSOLUTE, 0f,
Animation.ABSOLUTE, destLocation[0].toFloat() - srcLocation[0].toFloat(),
Animation.ABSOLUTE, 0.0f,
Animation.ABSOLUTE, 0.0f)
translateX.duration = DURATION
parabolaAnim.addAnimation(translateX)
val translateY = TranslateAnimation(
Animation.ABSOLUTE, 0F,
Animation.ABSOLUTE, 0F,
Animation.ABSOLUTE, 0f,
Animation.ABSOLUTE, destLocation[1].toFloat() - srcLocation[1].toFloat())
translateY.setInterpolator(AccelerateInterpolator())
translateY.duration = DURATION
parabolaAnim.addAnimation(translateY)
parabolaAnim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationEnd(animation: Animation?) {
val viewParent = ib.parent
if (viewParent != null) {
(viewParent as ViewGroup).removeView(ib)
}
}
override fun onAnimationRepeat(animation: Animation?) {
}
override fun onAnimationStart(animation: Animation?) {
}
})
return parabolaAnim
}
/**
* 隐藏动画
*/
private fun getHideAnimation(): AnimationSet {
var animationSet: AnimationSet = AnimationSet(false)
animationSet.duration = DURATION
val alphaAnim: Animation = AlphaAnimation(1f, 0.0f)
alphaAnim.duration = DURATION
animationSet.addAnimation(alphaAnim)
val rotateAnim: Animation = RotateAnimation(720.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)
rotateAnim.duration = DURATION
animationSet.addAnimation(rotateAnim)
val translateAnim: Animation = TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 2.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f)
translateAnim.duration = DURATION
animationSet.addAnimation(translateAnim)
return animationSet
}
/**
* 动画
*/
private fun getShowAnimation(): AnimationSet {
var animationSet: AnimationSet = AnimationSet(false)
animationSet.duration = DURATION
//透明度
val alphaAnim: Animation = AlphaAnimation(0.0f, 1.0f)
alphaAnim.duration = DURATION
animationSet.addAnimation(alphaAnim)
//旋转
val rotateAnim: Animation = RotateAnimation(0.0f, 720.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)
rotateAnim.duration = DURATION
animationSet.addAnimation(rotateAnim)
val translateAnim: Animation = TranslateAnimation(
Animation.RELATIVE_TO_SELF, 2.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f)
translateAnim.duration = DURATION
animationSet.addAnimation(translateAnim)
return animationSet
}
val ivIcon: ImageView
val tvName: TextView
val tvForm: TextView
val tvMonthSale: TextView
val tvNewPrice: TextView
val tvOldPrice: TextView
val btnAdd: ImageButton
val btnMinus: ImageButton
val tvCount: TextView
lateinit var goodsInfo: GoodsInfo
init {
ivIcon = itemView.find(R.id.iv_icon)
tvName = itemView.find(R.id.tv_name)
tvForm = itemView.find(R.id.tv_form)
tvMonthSale = itemView.find(R.id.tv_month_sale)
tvNewPrice = itemView.find(R.id.tv_newprice)
tvOldPrice = itemView.find(R.id.tv_oldprice)
tvCount = itemView.find(R.id.tv_count)
btnAdd = itemView.find(R.id.ib_add)
btnMinus = itemView.find(R.id.ib_minus)
btnAdd.setOnClickListener(this)
btnMinus.setOnClickListener(this)
}
fun bindData(goodsInfo: GoodsInfo) {
this.goodsInfo = goodsInfo
//图片路径http://127.0.0.1:8090/image?name=takeout/businessimg/goods/0.jpg
Picasso.with(context).load(host + goodsInfo.icon).into(ivIcon)
tvName.text = goodsInfo.name
// tvForm.text = goodsInfo.form
tvMonthSale.text = "月售${goodsInfo.monthSaleNum}份"
tvNewPrice.text = PriceFormater.format(goodsInfo.newPrice.toFloat())
// tvNewPrice.text = "$${goodsInfo.newPrice}"
tvOldPrice.text = "¥${goodsInfo.oldPrice}"
tvOldPrice.paint.flags = Paint.STRIKE_THRU_TEXT_FLAG
if (goodsInfo.oldPrice > 0) {
tvOldPrice.visibility = View.VISIBLE
} else {
tvOldPrice.visibility = View.GONE
}
tvCount.text = goodsInfo.count.toString()
if (goodsInfo.count > 0) {
tvCount.visibility = View.VISIBLE
btnMinus.visibility = View.VISIBLE
} else {
tvCount.visibility = View.INVISIBLE
btnMinus.visibility = View.INVISIBLE
}
}
}
override fun getCount(): Int {
return goodsList.size
}
override fun getItem(position: Int): Any {
return goodsList.get(position)
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
var itemView: View
val goodsItemHolder: GoodsItemHolder
if (convertView == null) {
itemView = LayoutInflater.from(context).inflate(R.layout.item_goods, parent, false)
goodsItemHolder = GoodsItemHolder(itemView)
itemView.tag = goodsItemHolder
} else {
itemView = convertView
goodsItemHolder = convertView.tag as GoodsItemHolder
}
goodsItemHolder.bindData(goodsList.get(position))
return itemView
}
override fun getHeaderView(position: Int, convertView: View?, parent: ViewGroup?): View {
val goodsInfo: GoodsInfo = goodsList.get(position)
val typeName = goodsInfo.typeName
val textView: TextView = LayoutInflater.from(context).inflate(R.layout.item_type_header, parent, false) as TextView
textView.text = typeName
textView.setTextColor(Color.BLACK)
return textView
}
override fun getHeaderId(position: Int): Long {
val goodsInfo: GoodsInfo = goodsList.get(position)
return goodsInfo.typeId.toLong()
}
}
BusinessActivity.kt主界面逻辑的动画交互
package com.example.takeout.ui.activity
import android.content.Context
import android.os.Bundle
import android.util.TypedValue
import android.widget.ImageButton
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentPagerAdapter
import com.example.takeout.R
import com.example.takeout.ui.fragment.CommentsFragment
import com.example.takeout.ui.fragment.GoodsFragment
import com.example.takeout.ui.fragment.SellerFragment
import kotlinx.android.synthetic.main.activity_business.*
class BusinessActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_business)
//微调底部的导航栏适配
if (checkDeviceHasNavigationBar(this)) {
fl_Container.setPadding(0, 0, 0, 48.dp2px())
}
vp.adapter = BusinessFragmentPagerAdapter()
tabs.setupWithViewPager(vp)
}
val fragments = listOf<Fragment>(GoodsFragment(), SellerFragment(), CommentsFragment())
val titles = listOf<String>("商品", "商家", "评论")
/**
* 把转化功能添加到Int类中作为扩展函数
*/
fun Int.dp2px(): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
toFloat(), resources.displayMetrics
).toInt()
}
//获取是否存在NavigationBar
fun checkDeviceHasNavigationBar(context: Context): Boolean {
var hasNavigationBar = false
val rs = context.getResources()
val id = rs.getIdentifier("config_showNavigationBar", "bool", "android")
if (id > 0) {
hasNavigationBar = rs.getBoolean(id)
}
try {
val systemPropertiesClass = Class.forName("android.os.SystemProperties")
val m = systemPropertiesClass.getMethod("get", String::class.java)
val navBarOverride = m.invoke(systemPropertiesClass, "qemu.hw.mainkeys") as String
if ("1" == navBarOverride) {
hasNavigationBar = false
} else if ("0" == navBarOverride) {
hasNavigationBar = true
}
} catch (e: Exception) {
}
return hasNavigationBar
}
inner class BusinessFragmentPagerAdapter : FragmentPagerAdapter(supportFragmentManager) {
override fun getPageTitle(position: Int): CharSequence {
return titles.get(position)
}
override fun getItem(position: Int): Fragment {
return fragments.get(position)
}
override fun getCount(): Int {
return titles.size
}
}
fun addImageButton(ib: ImageButton, width: Int, height: Int) {
fl_Container.addView(ib, width, height)
}
fun getCartLocation(): IntArray {
val destLocation = IntArray(2)
imgCart.getLocationInWindow(destLocation)
return destLocation
}
}
GoodsTypeRvAdapter.kt左侧的type类型随着右侧的条目的增加和减少显示数字小红点
package com.example.takeout.ui.adapter
import android.graphics.Color
import android.graphics.Typeface
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.RecyclerView
import com.example.takeout.R
import com.example.takeout.model.beans.GoodsTypeInfo
import com.example.takeout.ui.fragment.GoodsFragment
import org.jetbrains.anko.find
class GoodsTypeRvAdapter(val context: FragmentActivity?, val goodsFragment: GoodsFragment) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var goodsTypeList: List<GoodsTypeInfo> = listOf()
fun setDatas(list: List<GoodsTypeInfo>) {
this.goodsTypeList = list
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val itemView = LayoutInflater.from(context).inflate(R.layout.item_type, parent, false)
return GoodsTypeItemHolder(itemView)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val goodsTypeItemHolder = holder as GoodsTypeItemHolder
goodsTypeItemHolder.bindData(goodsTypeList.get(position), position)
}
override fun getItemCount(): Int {
return goodsTypeList.size
}
var selectPosition = 0 //选中的位置
inner class GoodsTypeItemHolder(val item: View) : RecyclerView.ViewHolder(item) {
val tvType: TextView
val tvRedDotCount: TextView
var mPosition: Int = 0
lateinit var goodsTypeInfo: GoodsTypeInfo
init {
tvType = item.find<TextView>(R.id.type)
tvRedDotCount = item.find<TextView>(R.id.tvRedDotCount)
item.setOnClickListener {
selectPosition = mPosition
notifyDataSetChanged()
//step2:右侧列表跳转到该类型中第一个商品
val typeId = goodsTypeInfo.id
//遍历所有商品,找到此position
val position = goodsFragment.goodsFragmentPresenter.getGoodsPositionByTypeId(typeId)
//右侧粘性listview更新位置
goodsFragment.slhlv.setSelection(position)
}
}
fun bindData(goodsTypeInfo: GoodsTypeInfo, position: Int) {
mPosition = position
this.goodsTypeInfo = goodsTypeInfo
if (position == selectPosition) {
//选中的为白底加粗黑字,
item.setBackgroundColor(Color.WHITE)
tvType.setTextColor(Color.BLACK)
tvType.setTypeface(Typeface.DEFAULT_BOLD)
} else {
//未选中是灰色背景 普通字体
item.setBackgroundColor(Color.parseColor("#b9dedcdc"))
tvType.setTextColor(Color.GRAY)
tvType.setTypeface(Typeface.DEFAULT)
}
tvType.text = goodsTypeInfo.name
tvRedDotCount.text = goodsTypeInfo.redDotCount.toString()
if (goodsTypeInfo.redDotCount > 0) {
tvRedDotCount.visibility = View.VISIBLE
} else {
tvRedDotCount.visibility = View.GONE
}
}
}
}
效果如下: