feat : 重写 装扮商城 , 我的装扮 , 装扮赠送 页面
@@ -314,6 +314,12 @@
|
||||
<activity
|
||||
android:name=".ui.user.activity.UserCpListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".decoration.ui.activity.DressUpTabActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".ui.search.SearchUserActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".audio.AudioRecordActivity"
|
||||
android:label="@string/main_androidmanifest_017"
|
||||
|
@@ -5,8 +5,8 @@ import android.graphics.Bitmap
|
||||
import android.view.LayoutInflater
|
||||
import com.chwl.app.databinding.RoomNotifyCpBindBinding
|
||||
import com.chwl.app.ui.utils.CpUtils
|
||||
import com.chwl.app.ui.utils.isDestroyed
|
||||
import com.chwl.core.gift.bean.CpMsgBean
|
||||
import com.chwl.core.utils.LogUtils
|
||||
import com.tencent.qgame.animplayer.inter.IFetchResource
|
||||
import com.tencent.qgame.animplayer.mix.Resource
|
||||
import com.tencent.qgame.animplayer.util.ScaleType
|
||||
@@ -78,7 +78,9 @@ class RoomNotifyCpBindDialog (private val context: Context) : BaseRoomNotifyDial
|
||||
|
||||
fun checkImg() {
|
||||
if (index == 2){
|
||||
show()
|
||||
if (!context.isDestroyed()) {
|
||||
show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -193,9 +193,9 @@ public class GiftEffectView extends RelativeLayout {
|
||||
return;
|
||||
}
|
||||
if (giftInfo.getOtherViewType() == 1 && !TextUtils.isEmpty(giftInfo.getViewUrl())) {
|
||||
drawVAPEffect(giftInfo.getViewUrl());
|
||||
drawVAPEffect(giftInfo.getViewUrl().trim());
|
||||
} else if (giftInfo.isHasVggPic() && !StringUtil.isEmpty(giftInfo.getVggUrl())) {
|
||||
drawSvgaEffect(giftInfo.getVggUrl());
|
||||
drawSvgaEffect(giftInfo.getVggUrl().trim());
|
||||
} else {
|
||||
effectHandler.sendEmptyMessage(0);
|
||||
}
|
||||
@@ -205,26 +205,33 @@ public class GiftEffectView extends RelativeLayout {
|
||||
}
|
||||
|
||||
private void drawSvgaEffect(String url) {
|
||||
log("drawSvgaEffect url:" + url);
|
||||
log("drawEffect drawSvgaEffect url:" + url);
|
||||
|
||||
GlideUtils.instance().downloadFromUrl(getContext(), url, new RequestListener<File>() {
|
||||
GlideUtils.instance().downloadFromUrl2(getContext(), url, new RequestListener<File>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<File> target, boolean isFirstResource) {
|
||||
|
||||
log("drawSvgaEffect onDownloadError url:" + url);
|
||||
String message = "";
|
||||
if (e != null) {
|
||||
message = e.getMessage();
|
||||
}
|
||||
log("drawEffect drawSvgaEffect onDownloadError url:" + url + " error = "+message);
|
||||
effectHandler.sendEmptyMessage(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(File resource, Object model, Target<File> target, DataSource dataSource, boolean isFirstResource) {
|
||||
String path = "";
|
||||
if (resource != null) {
|
||||
String path = resource.getPath();
|
||||
log("drawSvgaEffect onDownloadCompleted url:" + url + " path:" + path);
|
||||
path = resource.getPath();
|
||||
drawSvgaEffectFile(path);
|
||||
} else {
|
||||
effectHandler.sendEmptyMessage(0);
|
||||
}
|
||||
log("drawEffect drawSvgaEffect onDownloadCompleted url:" + url + " path:" + path);
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -257,23 +264,33 @@ public class GiftEffectView extends RelativeLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private void drawVAPEffect(String url) {
|
||||
log("drawVAPEffect url:" + url);
|
||||
|
||||
GlideUtils.instance().downloadFromUrl(getContext(), url, new RequestListener<File>() {
|
||||
|
||||
private void drawVAPEffect(String url) {
|
||||
log("drawEffect drawVAPEffect url:" + url);
|
||||
|
||||
GlideUtils.instance().downloadFromUrl2(getContext(), url, new RequestListener<File>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<File> target, boolean isFirstResource) {
|
||||
log("drawVAPEffect onDownloadError url:" + url);
|
||||
String message = "";
|
||||
if (e != null) {
|
||||
message = e.getMessage();
|
||||
}
|
||||
log("drawEffect drawVAPEffect onDownloadError url:" + url + " error = "+message);
|
||||
effectHandler.sendEmptyMessageDelayed(0, 4000);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(File resource, Object model, Target<File> target, DataSource dataSource, boolean isFirstResource) {
|
||||
String path = "";
|
||||
if (resource != null) {
|
||||
log("drawVAPEffect onDownloadCompleted url:" + url + " path:" + resource.getPath());
|
||||
path = resource.getPath();
|
||||
vapAnimView.startPlay(resource);
|
||||
} else {
|
||||
effectHandler.sendEmptyMessage(0);
|
||||
}
|
||||
log("drawEffect drawVAPEffect onDownloadCompleted url:" + url + " path:" + path);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
@@ -46,34 +46,11 @@ import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.chwl.app.notify.GlobalNotifyManager;
|
||||
import com.chwl.app.utils.RoomBoomManager;
|
||||
import com.chwl.core.gift.bean.BoomMsgAnimBean;
|
||||
import com.chwl.core.gift.bean.BoomMsgDialogBean;
|
||||
import com.chwl.core.im.custom.bean.BoomMsgAttachment;
|
||||
import com.chwl.core.manager.AvRoomDataManager;
|
||||
import com.chwl.core.utils.LogUtils;
|
||||
import com.chwl.library.language.LanguageHelper;
|
||||
import com.example.lib_utils.UiUtils;
|
||||
import com.google.gson.Gson;
|
||||
import com.netease.nim.uikit.common.util.log.LogUtil;
|
||||
import com.netease.nimlib.chatroom.model.ChatRoomMessageImpl;
|
||||
import com.netease.nimlib.sdk.NIMSDK;
|
||||
import com.netease.nimlib.sdk.Observer;
|
||||
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage;
|
||||
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum;
|
||||
import com.netease.nimlib.sdk.msg.model.BroadcastMessage;
|
||||
import com.netease.nimlib.session.IMMessageImpl;
|
||||
import com.orhanobut.logger.Logger;
|
||||
import com.readystatesoftware.systembartint.SystemBarTintManager;
|
||||
import com.tbruyelle.rxpermissions2.RxPermissions;
|
||||
import com.trello.rxlifecycle3.android.ActivityEvent;
|
||||
import com.trello.rxlifecycle3.components.support.RxAppCompatActivity;
|
||||
import com.chwl.app.NimMiddleActivity;
|
||||
import com.chwl.app.R;
|
||||
import com.chwl.app.application.App;
|
||||
import com.chwl.app.application.IReportConstants;
|
||||
import com.chwl.app.application.ReportManager;
|
||||
import com.chwl.app.application.App;
|
||||
import com.chwl.app.avroom.activity.AVRoomActivity;
|
||||
import com.chwl.app.common.LoadingFragment;
|
||||
import com.chwl.app.common.NetworkErrorFragment;
|
||||
@@ -83,6 +60,7 @@ import com.chwl.app.common.permission.PermissionActivity;
|
||||
import com.chwl.app.common.widget.StatusLayout;
|
||||
import com.chwl.app.common.widget.dialog.DialogManager;
|
||||
import com.chwl.app.common.widget.dialog.DialogUiHelper;
|
||||
import com.chwl.app.notify.GlobalNotifyManager;
|
||||
import com.chwl.app.ui.im.avtivity.NimP2PMessageActivity;
|
||||
import com.chwl.app.ui.login.AddUserInfoActivity;
|
||||
import com.chwl.app.ui.login.LoginCodeActivity;
|
||||
@@ -94,14 +72,18 @@ import com.chwl.app.ui.widget.dialog.AllPlayEffectDialog;
|
||||
import com.chwl.app.ui.widget.dialog.AllServiceGiftLevelDialog;
|
||||
import com.chwl.app.ui.widget.dialog.AllServiceVipLevelUPDialog;
|
||||
import com.chwl.app.ui.widget.dialog.OpenNobleGlobalNoticeDialog;
|
||||
import com.chwl.app.utils.RoomBoomManager;
|
||||
import com.chwl.app.utils.UserUtils;
|
||||
import com.chwl.core.XConstants;
|
||||
import com.chwl.core.bean.BaseProtocol;
|
||||
import com.chwl.core.gift.bean.BoomMsgDialogBean;
|
||||
import com.chwl.core.im.custom.bean.BoomMsgAttachment;
|
||||
import com.chwl.core.im.custom.bean.CustomAttachment;
|
||||
import com.chwl.core.im.custom.bean.NotifyH5Info;
|
||||
import com.chwl.core.im.custom.bean.PlayEffectInfo;
|
||||
import com.chwl.core.im.custom.bean.RoomLuckySeaMsgBean;
|
||||
import com.chwl.core.im.custom.bean.TarotMsgBean;
|
||||
import com.chwl.core.manager.AvRoomDataManager;
|
||||
import com.chwl.core.manager.IMNetEaseManager;
|
||||
import com.chwl.core.manager.RoomEvent;
|
||||
import com.chwl.core.mentoring_relationship.event.GrabApprenticesEvent;
|
||||
@@ -115,8 +97,10 @@ import com.chwl.core.pay.bean.WalletInfo;
|
||||
import com.chwl.core.room.model.AvRoomModel;
|
||||
import com.chwl.core.treasurefairy.bean.FairyMsgInfoBean;
|
||||
import com.chwl.core.user.UserModel;
|
||||
import com.chwl.core.utils.LogUtils;
|
||||
import com.chwl.core.utils.net.RxHelper;
|
||||
import com.chwl.core.vip.bean.VipMessageInfo;
|
||||
import com.chwl.library.language.LanguageHelper;
|
||||
import com.chwl.library.rxbus.RxBus;
|
||||
import com.chwl.library.utils.NetworkUtils;
|
||||
import com.chwl.library.utils.ResUtil;
|
||||
@@ -125,6 +109,22 @@ import com.chwl.library.utils.UIUtils;
|
||||
import com.chwl.library.utils.codec.DESUtils;
|
||||
import com.chwl.library.utils.config.BasicConfig;
|
||||
import com.chwl.library.utils.log.MLog;
|
||||
import com.example.lib_utils.UiUtils;
|
||||
import com.google.gson.Gson;
|
||||
import com.netease.nim.uikit.StatusBarUtil;
|
||||
import com.netease.nim.uikit.common.util.log.LogUtil;
|
||||
import com.netease.nimlib.chatroom.model.ChatRoomMessageImpl;
|
||||
import com.netease.nimlib.sdk.NIMSDK;
|
||||
import com.netease.nimlib.sdk.Observer;
|
||||
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage;
|
||||
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum;
|
||||
import com.netease.nimlib.sdk.msg.model.BroadcastMessage;
|
||||
import com.netease.nimlib.session.IMMessageImpl;
|
||||
import com.orhanobut.logger.Logger;
|
||||
import com.readystatesoftware.systembartint.SystemBarTintManager;
|
||||
import com.tbruyelle.rxpermissions2.RxPermissions;
|
||||
import com.trello.rxlifecycle3.android.ActivityEvent;
|
||||
import com.trello.rxlifecycle3.components.support.RxAppCompatActivity;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
@@ -276,7 +276,7 @@ public abstract class BaseActivity extends RxAppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
public void initBlackTitleBar(String title) {
|
||||
public void initDarkTitleBar(String title) {
|
||||
mTitleBar = findViewById(R.id.title_bar);
|
||||
if (mTitleBar != null) {
|
||||
mTitleBar.setTitle(title);
|
||||
@@ -285,6 +285,21 @@ public abstract class BaseActivity extends RxAppCompatActivity
|
||||
mTitleBar.setLeftImageResource(R.drawable.icon_user_back);
|
||||
mTitleBar.setBackgroundResource(R.color.transparent);
|
||||
mTitleBar.setLeftClickListener(v -> onLeftClickListener());
|
||||
StatusBarUtil.StatusBarLightMode(this,false);
|
||||
StatusBarUtil.transparencyBar(this);
|
||||
}
|
||||
}
|
||||
public void initLightTitleBar(String title) {
|
||||
mTitleBar = findViewById(R.id.title_bar);
|
||||
if (mTitleBar != null) {
|
||||
mTitleBar.setTitle(title);
|
||||
mTitleBar.setImmersive(false);
|
||||
mTitleBar.setTitleColor(getResources().getColor(R.color.text_title_color));
|
||||
mTitleBar.setLeftImageResource(R.drawable.arrow_left);
|
||||
mTitleBar.setBackgroundResource(R.color.transparent);
|
||||
mTitleBar.setLeftClickListener(v -> onLeftClickListener());
|
||||
StatusBarUtil.StatusBarLightMode(this,true);
|
||||
StatusBarUtil.transparencyBar(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,11 @@ import android.content.DialogInterface
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
@@ -27,6 +31,7 @@ abstract class BaseDialogFragment<T : ViewBinding> : RxDialogFragment() {
|
||||
open var height = WindowManager.LayoutParams.WRAP_CONTENT
|
||||
open var gravity = Gravity.CENTER
|
||||
open var dimAmount = 0.5f
|
||||
var mActionCallBack : Action?= null
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
@@ -120,4 +125,8 @@ abstract class BaseDialogFragment<T : ViewBinding> : RxDialogFragment() {
|
||||
}
|
||||
|
||||
abstract fun init()
|
||||
|
||||
public interface Action{
|
||||
fun <D:Any>onAction(type:Int,data:D?)
|
||||
}
|
||||
}
|
108
app/src/main/java/com/chwl/app/base/BaseListFragment.kt
Normal file
@@ -0,0 +1,108 @@
|
||||
package com.chwl.app.base
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.chad.library.adapter.base.BaseQuickAdapter
|
||||
import com.chwl.app.R
|
||||
import com.chwl.app.bindadapter.BaseBindingAdapter
|
||||
import com.chwl.app.databinding.BaseListFragmentBinding
|
||||
import com.chwl.library.common.util.setVis
|
||||
import com.scwang.smartrefresh.layout.api.RefreshLayout
|
||||
import com.scwang.smartrefresh.layout.listener.OnRefreshLoadmoreListener
|
||||
|
||||
abstract class BaseListFragment<D:Any>:
|
||||
BaseViewBindingFragment<BaseListFragmentBinding>() {
|
||||
|
||||
lateinit var mAdapter: BaseBindingAdapter<*, D>
|
||||
protected var mPageSize = 20;
|
||||
protected var mPage = 1;
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
_binding = BaseListFragmentBinding.inflate(layoutInflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
|
||||
|
||||
override fun init() {
|
||||
mAdapter = getAdapter()
|
||||
|
||||
binding.rvList.layoutManager = getLayoutManager()
|
||||
binding.rvList.adapter = mAdapter
|
||||
|
||||
binding.srlLayout.setOnRefreshLoadmoreListener(object : OnRefreshLoadmoreListener {
|
||||
override fun onRefresh(refreshlayout: RefreshLayout?) {
|
||||
onRefresh()
|
||||
}
|
||||
|
||||
override fun onLoadmore(refreshlayout: RefreshLayout?) {
|
||||
onLoad()
|
||||
}
|
||||
})
|
||||
mAdapter.onItemClickListener = BaseQuickAdapter.OnItemClickListener { adapter, view, position ->
|
||||
onItemClicks(mAdapter, view, position)
|
||||
}
|
||||
mAdapter.onItemChildClickListener = BaseQuickAdapter.OnItemChildClickListener { adapter, view, position ->
|
||||
onItemChildClicks(mAdapter, view, position)
|
||||
}
|
||||
initView()
|
||||
}
|
||||
|
||||
abstract fun getAdapter(): BaseBindingAdapter<*, D>
|
||||
|
||||
protected open fun getLayoutManager(): RecyclerView.LayoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
|
||||
protected open fun hasTitle(): Boolean = false
|
||||
|
||||
protected open fun onItemClicks(
|
||||
adapter: BaseBindingAdapter<*, D>?,
|
||||
view: View?,
|
||||
position: Int
|
||||
) {}
|
||||
protected open fun onItemChildClicks(
|
||||
adapter: BaseBindingAdapter<*, D>?,
|
||||
view: View?,
|
||||
position: Int
|
||||
) {}
|
||||
|
||||
abstract fun onLoad()
|
||||
abstract fun onRefresh()
|
||||
|
||||
|
||||
abstract fun initView()
|
||||
|
||||
protected open fun stopAnim() {
|
||||
binding.srlLayout.finishLoadmore()
|
||||
binding.srlLayout.finishRefresh()
|
||||
}
|
||||
|
||||
var mTitleBar : TitleBar?=null
|
||||
open fun initWhiteTitleBar(title: String?,listener:View.OnClickListener) {
|
||||
mTitleBar = _binding?.root?.findViewById<TitleBar>(R.id.title_bar)
|
||||
if (mTitleBar != null) {
|
||||
mTitleBar?.setTitle(title)
|
||||
mTitleBar?.setImmersive(false)
|
||||
mTitleBar?.setTitleColor(resources.getColor(R.color.text_title_color))
|
||||
mTitleBar?.setLeftImageResource(R.drawable.arrow_left)
|
||||
mTitleBar?.setBackgroundResource(R.color.transparent)
|
||||
mTitleBar?.setLeftClickListener(listener)
|
||||
mTitleBar?.setVis(true)
|
||||
}
|
||||
}
|
||||
|
||||
fun initBlackTitleBar(title: String?,listener:View.OnClickListener) {
|
||||
mTitleBar = _binding?.root?.findViewById<TitleBar>(R.id.title_bar)
|
||||
if (mTitleBar != null) {
|
||||
mTitleBar?.setTitle(title)
|
||||
mTitleBar?.setImmersive(false)
|
||||
mTitleBar?.setTitleColor(resources.getColor(R.color.white))
|
||||
mTitleBar?.setLeftImageResource(R.drawable.icon_user_back)
|
||||
mTitleBar?.setBackgroundResource(R.color.transparent)
|
||||
mTitleBar?.setLeftClickListener(listener)
|
||||
mTitleBar?.setVis(true)
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,6 +4,7 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import androidx.annotation.Nullable
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.netease.nim.uikit.StatusBarUtil
|
||||
import java.lang.reflect.ParameterizedType
|
||||
|
||||
|
||||
@@ -20,6 +21,11 @@ abstract class BaseViewBindingActivity<T : ViewBinding> : BaseActivity(){
|
||||
val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java)
|
||||
binding = method.invoke(null,layoutInflater) as T
|
||||
setContentView(binding.root)
|
||||
|
||||
if (transparencyBar()) {
|
||||
StatusBarUtil.transparencyBar(this)
|
||||
}
|
||||
|
||||
init()
|
||||
}
|
||||
|
||||
@@ -29,4 +35,5 @@ abstract class BaseViewBindingActivity<T : ViewBinding> : BaseActivity(){
|
||||
protected open fun initBefore(@Nullable savedInstanceState: Bundle?) {}
|
||||
|
||||
abstract fun init()
|
||||
protected open fun transparencyBar():Boolean=false
|
||||
}
|
@@ -15,8 +15,8 @@ open class BaseBindingAdapter<VB : ViewBinding?, T>() : BaseQuickAdapter<T, Base
|
||||
//反射没有想象中的那么耗时
|
||||
val type = javaClass.genericSuperclass as ParameterizedType
|
||||
val aClass = type.actualTypeArguments[0] as Class<*>
|
||||
val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java)
|
||||
val binding = method.invoke(null, mLayoutInflater) as VB
|
||||
val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java,ViewGroup::class.java, Boolean::class.java)
|
||||
val binding = method.invoke(null, mLayoutInflater,parent,false) as VB
|
||||
val view = binding?.root?:return View(mContext)
|
||||
view.setTag(R.id.BaseQuickAdapter_databinding_support, binding)
|
||||
return view
|
||||
|
@@ -0,0 +1,99 @@
|
||||
package com.chwl.app.decoration.adapter
|
||||
|
||||
import android.view.Gravity
|
||||
import com.chwl.app.R
|
||||
import com.chwl.app.bindadapter.BaseBindingAdapter
|
||||
import com.chwl.app.bindadapter.BaseBindingViewHolder
|
||||
import com.chwl.app.databinding.ItemDressUpLayoutBinding
|
||||
import com.chwl.app.decoration.ui.activity.DressUpTabActivity
|
||||
import com.chwl.app.decoration.util.DressUpUtil
|
||||
import com.chwl.core.decoration.bean.DressUpInfo
|
||||
import com.chwl.library.common.util.isVerify
|
||||
import com.chwl.library.common.util.setVis
|
||||
import com.example.lib_utils.ktx.getString
|
||||
|
||||
class DressUpAdapter : BaseBindingAdapter<ItemDressUpLayoutBinding, DressUpInfo>() {
|
||||
|
||||
override fun convert(
|
||||
helper: BaseBindingViewHolder<ItemDressUpLayoutBinding>,
|
||||
item: DressUpInfo
|
||||
) {
|
||||
val binding = helper.binding
|
||||
setViewDef(binding)
|
||||
|
||||
|
||||
|
||||
if (item.isSelect) {
|
||||
binding.root.setBackgroundResource(R.drawable.ic_dress_item_s)
|
||||
} else {
|
||||
binding.root.setBackgroundResource(R.drawable.ic_dress_item_n)
|
||||
}
|
||||
|
||||
if (item.isNull) {
|
||||
binding.empty.setVis(true)
|
||||
binding.name.text = R.string.Not_used.getString()
|
||||
binding.name.setVis(true)
|
||||
return
|
||||
}
|
||||
|
||||
DressUpUtil.setItemPic(item,binding.picLayout)
|
||||
binding.picLayout.setVis(true)
|
||||
|
||||
|
||||
binding.name.text = item.name
|
||||
binding.name.gravity = if (item.isMy) Gravity.CENTER else Gravity.START
|
||||
binding.name.setVis(true)
|
||||
|
||||
|
||||
DressUpUtil.setTextPrice(binding.price,item)
|
||||
binding.price.setVis(!item.isMy)
|
||||
|
||||
|
||||
binding.discount.text = item.discount.toString()
|
||||
binding.discount.setVis(!item.isMy)
|
||||
|
||||
|
||||
if (item.dressType != DressUpTabActivity.TAB_USER_CARD && item.effect.isVerify()) {
|
||||
binding.btnPlay.setVis(true)
|
||||
} else {
|
||||
binding.btnPlay.setVis(false)
|
||||
}
|
||||
|
||||
if (item.isMy) {
|
||||
if (item.isHasExpired) {
|
||||
binding.limit.setVis(true)
|
||||
binding.limit.text = R.string.Expired.getString()
|
||||
} else {
|
||||
if (item.expireDays != -1) {
|
||||
binding.limit.text = R.string.sDays.getString(item.expireDays)
|
||||
} else {
|
||||
binding.limit.text = R.string.unDay.getString()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (item.dressLimitStatus != 0) {
|
||||
binding.limit.setVis(true)
|
||||
} else {
|
||||
binding.limit.setVis(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
helper.addOnClickListener(R.id.btnPlay)
|
||||
|
||||
}
|
||||
|
||||
private fun setViewDef(binding : ItemDressUpLayoutBinding) {
|
||||
// binding.bg.setVis(false)
|
||||
// binding.picBg.setVis(false)
|
||||
binding.picLayout.setVis(false)
|
||||
// binding.name.setVis(false)
|
||||
binding.price.setVis(false)
|
||||
binding.discount.setVis(false)
|
||||
binding.empty.setVis(false)
|
||||
binding.btnPlay.setVis(false)
|
||||
binding.limit.setVis(false)
|
||||
}
|
||||
}
|
@@ -37,7 +37,7 @@ public class MyUserCardWearAdapter extends BaseAdapter<UserCardWearInfo> {
|
||||
ItemMyUserCardWearBinding binding = (ItemMyUserCardWearBinding) helper.getBinding();
|
||||
binding.ivUserCardWearMp4.setLoop(Integer.MAX_VALUE);
|
||||
|
||||
GlideUtils.instance().downloadFromUrl(binding.ivUserCardWearMp4.getContext(), item.getPic(), new RequestListener<File>() {
|
||||
GlideUtils.instance().downloadFromUrl2(binding.ivUserCardWearMp4.getContext(), item.getPic(), new RequestListener<File>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<File> target, boolean isFirstResource) {
|
||||
ImageLoadUtils.loadImage(mContext, item.getPic(), binding.ivUserCardWear);
|
||||
|
137
app/src/main/java/com/chwl/app/decoration/ui/DressUpDialog.kt
Normal file
@@ -0,0 +1,137 @@
|
||||
package com.chwl.app.decoration.ui
|
||||
|
||||
import android.view.Gravity
|
||||
import com.chwl.app.R
|
||||
import com.chwl.app.base.BaseDialogFragment
|
||||
import com.chwl.app.databinding.DialogDressUpBinding
|
||||
import com.chwl.app.decoration.util.DressUpUtil
|
||||
import com.chwl.core.bean.response.ServiceResult
|
||||
import com.chwl.core.decoration.bean.DressUpInfo
|
||||
import com.chwl.core.utils.net.RxHelper
|
||||
import com.chwl.library.common.util.ClickUtils.click
|
||||
import com.chwl.library.common.util.doToast
|
||||
import com.chwl.library.net.rxnet.RxNet
|
||||
import com.example.lib_utils.ktx.dp
|
||||
import com.example.lib_utils.ktx.getString
|
||||
import com.hjq.toast.ToastUtils
|
||||
import io.reactivex.Single
|
||||
import retrofit2.http.Field
|
||||
import retrofit2.http.FormUrlEncoded
|
||||
import retrofit2.http.POST
|
||||
|
||||
class DressUpDialog : BaseDialogFragment<DialogDressUpBinding>() {
|
||||
|
||||
override var width = 284.dp
|
||||
override var height = 353.dp
|
||||
override var dimAmount = 0.3f
|
||||
override var gravity = Gravity.CENTER
|
||||
|
||||
|
||||
var mDressUpInfo : DressUpInfo? = null
|
||||
var mTargetUid = -1L
|
||||
|
||||
override fun init() {
|
||||
|
||||
mDressUpInfo?.let {
|
||||
binding.name.text = it.name
|
||||
if (it.vipLimit == 0 && it.obtainWay == 1){
|
||||
DressUpUtil.setTextPrice(binding.price,it)
|
||||
}else{
|
||||
if (it.obtainWay != 1) {
|
||||
binding.price.text = R.string.obtainWayAction.getString()
|
||||
}else if (it.vipLimit != 0) {
|
||||
binding.price.text = R.string.vipLimit.getString(it.vipLimit)
|
||||
}
|
||||
}
|
||||
|
||||
DressUpUtil.setItemPic(it,binding.picLayout)
|
||||
|
||||
}
|
||||
|
||||
binding.btnBuy.text = if (mTargetUid != -1L) R.string.fairy_give.getString() else R.string.buy.getString()
|
||||
|
||||
binding.btnBuy.click {
|
||||
mDressUpInfo?.let {
|
||||
if (mTargetUid != -1L) {
|
||||
postShopGive(it.dressType,it.id,mTargetUid)
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess{
|
||||
ToastUtils.show(R.string.doSuccess)
|
||||
dismiss()
|
||||
}
|
||||
.doOnError {
|
||||
it?.message?.doToast()
|
||||
}
|
||||
.subscribe()
|
||||
} else {
|
||||
postShopBuy(it.dressType,it.id)
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess{
|
||||
ToastUtils.show(R.string.doSuccess)
|
||||
dismiss()
|
||||
}
|
||||
.doOnError {
|
||||
it?.message?.doToast()
|
||||
}
|
||||
.subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
binding.btnCancel.click {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun postShopBuy(dressType: Int,id: Int): Single<String> {
|
||||
return api.postShopBuy(dressType,id)
|
||||
.compose(RxHelper.handleStringData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
|
||||
private fun postShopGive(dressType: Int,id: Int,targetUid:Long): Single<String> {
|
||||
return api.postShopGive(dressType,id,targetUid)
|
||||
.compose(RxHelper.handleStringData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
private val api: Api = RxNet.create(Api::class.java);
|
||||
interface Api {
|
||||
|
||||
/**
|
||||
* 购买装扮
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@FormUrlEncoded
|
||||
@POST("/dress/shop/buy")
|
||||
fun postShopBuy(
|
||||
@Field("dressType") dressType: Int,
|
||||
@Field("id") id: Int
|
||||
): Single<ServiceResult<String>>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 赠送装扮
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@FormUrlEncoded
|
||||
@POST("/dress/shop/give")
|
||||
fun postShopGive(
|
||||
@Field("dressType") dressType: Int,
|
||||
@Field("id") id: Int,
|
||||
@Field("targetUid") targetUid: Long,
|
||||
): Single<ServiceResult<String>>
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,213 @@
|
||||
package com.chwl.app.decoration.ui.activity
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.alibaba.fastjson.JSON
|
||||
import com.chwl.app.R
|
||||
import com.chwl.app.base.BaseViewBindingActivity
|
||||
import com.chwl.app.databinding.ActivityDressUpTabBinding
|
||||
import com.chwl.app.databinding.TabDressUpLayoutBinding
|
||||
import com.chwl.app.decoration.ui.DressUpDialog
|
||||
import com.chwl.app.decoration.ui.fragment.DressUpMyFragment
|
||||
import com.chwl.app.decoration.ui.fragment.DressUpStoreFragment
|
||||
import com.chwl.app.decoration.util.DressUpUtil
|
||||
import com.chwl.app.event.DressUpEvent
|
||||
import com.chwl.app.ui.search.SearchUserActivity
|
||||
import com.chwl.app.ui.utils.loadAvatar
|
||||
import com.chwl.app.utils.AvatarHelper.loadAvatarFrame
|
||||
import com.chwl.core.auth.AuthModel
|
||||
import com.chwl.core.decoration.bean.DressUpInfo
|
||||
import com.chwl.core.home.bean.TabInfo
|
||||
import com.chwl.core.user.UserModel
|
||||
import com.chwl.library.common.util.ClickUtils.click
|
||||
import com.chwl.library.common.util.setVis
|
||||
import com.chwl.library.utils.ResUtil
|
||||
import com.chwl.library.widget.tab.SmartTabLayout2
|
||||
import com.chwl.library.widget.tab.TabTitleProvider
|
||||
import com.chwl.library.widget.tab.util.FragmentPageAdapter
|
||||
import com.example.lib_utils.ktx.getString
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
class DressUpTabActivity : BaseViewBindingActivity<ActivityDressUpTabBinding>() {
|
||||
|
||||
private var mDressUpInfo : DressUpInfo ? = null
|
||||
|
||||
|
||||
|
||||
companion object{
|
||||
const val TAB_HEAD_WEAR = 0
|
||||
const val TAB_CAR = 1
|
||||
const val TAB_NAMEPLATE = 2
|
||||
const val TAB_USER_CARD = 3
|
||||
const val TAB_CHAT_BUBBLE = 4
|
||||
const val TAB_USER_INFO_BG = 5
|
||||
|
||||
fun start(context: Context,isMy:Boolean) {
|
||||
val intent = Intent(context, DressUpTabActivity::class.java)
|
||||
intent.putExtra("isMy",isMy)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private val isMy : Boolean by lazy { intent.getBooleanExtra("isMy",false) }
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
EventBus.getDefault().register(this)
|
||||
}
|
||||
|
||||
override fun transparencyBar() = true
|
||||
|
||||
override fun init() {
|
||||
|
||||
if (isMy) {
|
||||
binding.infoLayout.setVis(true)
|
||||
binding.btnMyDressUp.setVis(false)
|
||||
binding.avatar.loadAvatar(UserModel.get().cacheLoginUserInfo?.avatar)
|
||||
initDarkTitleBar(R.string.decoration_view_mydecorationactivity_01.getString())
|
||||
} else {
|
||||
binding.infoLayout.setVis(false)
|
||||
binding.btnMyDressUp.setVis(true)
|
||||
initDarkTitleBar(R.string.decoration_view_decorationstoreactivity_01.getString())
|
||||
}
|
||||
|
||||
initTab()
|
||||
initListener()
|
||||
|
||||
if (isMy) {
|
||||
UserModel.get().getUserInfo(AuthModel.get().currentUid)
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
it?.userHeadwear?.let { head->
|
||||
loadAvatarFrame(
|
||||
binding.avatarHead,
|
||||
head.getFirstUrl(),
|
||||
head.type
|
||||
)
|
||||
}
|
||||
}.subscribe()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
val fgLists = arrayListOf<Fragment>()
|
||||
val tabList = arrayListOf<TabInfo>()
|
||||
private fun initTab() {
|
||||
|
||||
tabList.clear()
|
||||
tabList.add(TabInfo(TAB_CAR, ResUtil.getString(R.string.decoration_view_decorationstoreactivity_04),R.drawable.ic_dress_tab_car))
|
||||
tabList.add(TabInfo(TAB_HEAD_WEAR, ResUtil.getString(R.string.decoration_view_decorationstoreactivity_03),R.drawable.ic_dress_tab_head))
|
||||
tabList.add(TabInfo(TAB_NAMEPLATE, ResUtil.getString(R.string.decoration_view_decorationstoreactivity_05),R.drawable.ic_dress_tab_nameplate))
|
||||
tabList.add(TabInfo(TAB_USER_CARD, ResUtil.getString(R.string.decoration_view_decorationstoreactivity_06),R.drawable.ic_dress_tab_card))
|
||||
tabList.add(TabInfo(TAB_CHAT_BUBBLE, ResUtil.getString(R.string.decoration_view_decorationstoreactivity_07),R.drawable.ic_dress_tab_chat))
|
||||
tabList.add(TabInfo(TAB_USER_INFO_BG, ResUtil.getString(R.string.userInfoBg),R.drawable.ic_dress_tab_homepage))
|
||||
|
||||
fgLists.clear()
|
||||
tabList.forEach {
|
||||
if (isMy) {
|
||||
fgLists.add(DressUpMyFragment.newInstance(it.id))
|
||||
} else {
|
||||
fgLists.add(DressUpStoreFragment.newInstance(it.id))
|
||||
}
|
||||
}
|
||||
|
||||
binding.tabLayout.setCustomTabView(SmartTabLayout2.TabProvider { container, position, pageTitle ->
|
||||
val tabView = TabDressUpLayoutBinding.inflate(this@DressUpTabActivity.layoutInflater,container,false)
|
||||
tabView.tabText.text = tabList.get(position).name
|
||||
tabView.tabImg.setImageResource(tabList.get(position).res)
|
||||
// tabView.root.layoutParams = LinearLayout.LayoutParams(
|
||||
// LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT
|
||||
// )
|
||||
return@TabProvider tabView.root
|
||||
})
|
||||
|
||||
val pageAdapter = FragmentPageAdapter(this,fgLists)
|
||||
binding.tabLayout.setViewPager(binding.viewPage,pageAdapter,object : TabTitleProvider {
|
||||
override fun getPageTitle(position: Int): CharSequence? {
|
||||
return tabList.get(position).name
|
||||
}
|
||||
})
|
||||
|
||||
binding.viewPage.offscreenPageLimit = 6
|
||||
binding.viewPage.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
selectTab(position)
|
||||
mDressUpInfo = null
|
||||
binding.bottomView.visibility = View.INVISIBLE
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
private fun initListener() {
|
||||
binding.btnBuy.click {
|
||||
mDressUpInfo?.let {
|
||||
val dressUpDialog = DressUpDialog()
|
||||
dressUpDialog.mDressUpInfo = it
|
||||
dressUpDialog.show(context)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
binding.btnGive.click {
|
||||
mDressUpInfo?.let {
|
||||
SearchUserActivity.start(context,JSON.toJSONString(it))
|
||||
}
|
||||
}
|
||||
|
||||
binding.btnMyDressUp.click {
|
||||
DressUpTabActivity.start(context,true)
|
||||
}
|
||||
|
||||
binding.playLayout.click {
|
||||
binding.playLayout.setVis(false)
|
||||
binding.playLayout.removeAllViews()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private fun selectTab(pos: Int) {
|
||||
for (i in 0 until tabList.size) {
|
||||
val tabAt = binding.tabLayout.getTabAt(i)
|
||||
val tabView = TabDressUpLayoutBinding.bind(tabAt)
|
||||
tabView.tabBg.setBackgroundResource(if (pos == i) R.drawable.ic_dress_tab_bg_s else R.drawable.ic_dress_tab_bg_n)
|
||||
tabView.tabText.alpha = if (pos == i) 1f else 0.5f
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onDressUpEvent(event: DressUpEvent) {
|
||||
val data = event.data
|
||||
when (event.action) {
|
||||
DressUpEvent.Action.Select -> {
|
||||
mDressUpInfo = data
|
||||
binding.bottomView.setVis(true)
|
||||
DressUpUtil.setTextPrice(binding.price,data)
|
||||
if (isMy) {
|
||||
if (data.dressType == TAB_HEAD_WEAR) {
|
||||
binding.avatarHead.loadUrl(data.effect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DressUpEvent.Action.Play -> {
|
||||
DressUpUtil.play(data,binding.playLayout)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
EventBus.getDefault().unregister(this)
|
||||
}
|
||||
}
|
@@ -0,0 +1,490 @@
|
||||
package com.chwl.app.decoration.ui.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.chwl.app.R
|
||||
import com.chwl.app.base.BaseListFragment
|
||||
import com.chwl.app.bindadapter.BaseBindingAdapter
|
||||
import com.chwl.app.common.EmptyViewHelper
|
||||
import com.chwl.app.decoration.adapter.DressUpAdapter
|
||||
import com.chwl.app.decoration.ui.activity.DressUpTabActivity
|
||||
import com.chwl.app.decoration.util.DressUpUtil
|
||||
import com.chwl.app.event.DressUpEvent
|
||||
import com.chwl.core.auth.AuthModel
|
||||
import com.chwl.core.bean.response.ServiceResult
|
||||
import com.chwl.core.decoration.bean.DressUpInfo
|
||||
import com.chwl.core.decoration.bean.ShopMine
|
||||
import com.chwl.core.decoration.car.bean.CarInfo
|
||||
import com.chwl.core.decoration.headwear.bean.ChatBubbleInfo
|
||||
import com.chwl.core.decoration.headwear.bean.UserCardWearInfo
|
||||
import com.chwl.core.decoration.nameplate.bean.NamePlateInfo
|
||||
import com.chwl.core.manager.AvRoomDataManager
|
||||
import com.chwl.core.manager.IMNetEaseManager
|
||||
import com.chwl.core.user.UserModel
|
||||
import com.chwl.core.utils.net.RxHelper
|
||||
import com.chwl.library.common.util.doToast
|
||||
import com.chwl.library.common.util.isVerify
|
||||
import com.chwl.library.common.util.setMargin
|
||||
import com.chwl.library.net.rxnet.RxNet
|
||||
import com.example.lib_utils.ktx.getString
|
||||
import io.reactivex.Single
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import retrofit2.http.Field
|
||||
import retrofit2.http.FormUrlEncoded
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Query
|
||||
|
||||
class DressUpMyFragment : BaseListFragment<DressUpInfo>() {
|
||||
|
||||
companion object {
|
||||
fun newInstance(dressType: Int): DressUpMyFragment {
|
||||
val args = Bundle()
|
||||
args.putInt("dressType", dressType)
|
||||
val fragment = DressUpMyFragment()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
|
||||
private val mDressType: Int by lazy { requireArguments().getInt("dressType") }
|
||||
private var mPosition = -1
|
||||
|
||||
|
||||
override fun initView() {
|
||||
|
||||
mAdapter.setEmptyView(
|
||||
EmptyViewHelper.createEmptyTextViewHeight(
|
||||
context,
|
||||
R.string.empty_data.getString()
|
||||
)
|
||||
)
|
||||
binding.rvList.setMargin(start = 10, end = 10)
|
||||
|
||||
mPosition = -1
|
||||
mAdapter.setNewData(arrayListOf())
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (!mAdapter?.data.isVerify()){
|
||||
onRefresh()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAdapter(): BaseBindingAdapter<*, DressUpInfo> {
|
||||
return DressUpAdapter()
|
||||
}
|
||||
|
||||
override fun getLayoutManager(): RecyclerView.LayoutManager {
|
||||
return GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
|
||||
}
|
||||
|
||||
|
||||
override fun onLoad() {
|
||||
loadDataByType(false)
|
||||
}
|
||||
|
||||
|
||||
|
||||
override fun onRefresh() {
|
||||
loadDataByType(true)
|
||||
}
|
||||
|
||||
private fun loadDataByType(isRefresh: Boolean) {
|
||||
|
||||
if (isRefresh){
|
||||
mPage = 1
|
||||
}
|
||||
|
||||
when (mDressType) {
|
||||
|
||||
DressUpTabActivity.TAB_CHAT_BUBBLE -> {
|
||||
getChatBubbleInfoList()
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
it?.let {
|
||||
val newData = mutableListOf<DressUpInfo>()
|
||||
it.forEach {
|
||||
newData.add(DressUpUtil.tranData(it))
|
||||
}
|
||||
setData(newData)
|
||||
}
|
||||
}.doOnError {
|
||||
stopAnim()
|
||||
it?.message?.doToast()
|
||||
}.subscribe()
|
||||
}
|
||||
|
||||
DressUpTabActivity.TAB_USER_CARD -> {
|
||||
getMyUserCardWearList()
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
it?.let {
|
||||
val newData = mutableListOf<DressUpInfo>()
|
||||
it.forEach {
|
||||
newData.add(DressUpUtil.tranData(it))
|
||||
}
|
||||
setData(newData)
|
||||
}
|
||||
}.doOnError {
|
||||
stopAnim()
|
||||
it?.message?.doToast()
|
||||
}.subscribe()
|
||||
}
|
||||
|
||||
DressUpTabActivity.TAB_NAMEPLATE -> {
|
||||
getNamePlateList()
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
it?.let {
|
||||
val newData = mutableListOf<DressUpInfo>()
|
||||
it.nameplateList.forEach {
|
||||
newData.add(DressUpUtil.tranData(it))
|
||||
}
|
||||
setData(newData)
|
||||
}
|
||||
}.doOnError {
|
||||
stopAnim()
|
||||
it?.message?.doToast()
|
||||
}.subscribe()
|
||||
}
|
||||
|
||||
DressUpTabActivity.TAB_HEAD_WEAR , DressUpTabActivity.TAB_USER_INFO_BG -> {
|
||||
getShopMine()
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
it?.let {
|
||||
val newData = mutableListOf<DressUpInfo>()
|
||||
it.forEach {
|
||||
newData.add(DressUpUtil.tranData(it))
|
||||
}
|
||||
setData(newData)
|
||||
}
|
||||
}.doOnError {
|
||||
stopAnim()
|
||||
it?.message?.doToast()
|
||||
}.subscribe()
|
||||
}
|
||||
|
||||
DressUpTabActivity.TAB_CAR -> {
|
||||
getUserCarsV2()
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
it?.let {
|
||||
val newData = mutableListOf<DressUpInfo>()
|
||||
it.forEach {
|
||||
newData.add(DressUpUtil.tranData(it))
|
||||
}
|
||||
setData(newData)
|
||||
}
|
||||
}.doOnError {
|
||||
stopAnim()
|
||||
it?.message?.doToast()
|
||||
}.subscribe()
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun userByType(
|
||||
data: DressUpInfo,
|
||||
adapter: BaseBindingAdapter<*, DressUpInfo>?,
|
||||
position: Int
|
||||
) {
|
||||
when (mDressType) {
|
||||
|
||||
DressUpTabActivity.TAB_CHAT_BUBBLE -> {
|
||||
userChatBubble(data.dressId)
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
//更新用户信息
|
||||
UserModel.get().updateCurrentUserInfo().subscribe()
|
||||
setSelect(adapter, position)
|
||||
}
|
||||
.doOnError {
|
||||
it?.message?.doToast()
|
||||
}.subscribe()
|
||||
}
|
||||
|
||||
DressUpTabActivity.TAB_USER_CARD -> {
|
||||
userMyUserCardWear(data.dressId)
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
//更新用户信息
|
||||
UserModel.get().updateCurrentUserInfo().subscribe()
|
||||
setSelect(adapter, position)
|
||||
}
|
||||
.doOnError {
|
||||
it?.message?.doToast()
|
||||
}.subscribe()
|
||||
}
|
||||
|
||||
DressUpTabActivity.TAB_NAMEPLATE -> {
|
||||
useMyNamePlate(data.id,data.word)
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
if (AvRoomDataManager.get().mCurrentRoomInfo != null) {
|
||||
// 更新房间信息
|
||||
IMNetEaseManager.get().updateMyRoomRole()
|
||||
}
|
||||
//更新用户信息
|
||||
UserModel.get().updateCurrentUserInfo().subscribe()
|
||||
setSelect(adapter, position)
|
||||
}
|
||||
.doOnError {
|
||||
it?.message?.doToast()
|
||||
}.subscribe()
|
||||
}
|
||||
|
||||
DressUpTabActivity.TAB_HEAD_WEAR , DressUpTabActivity.TAB_USER_INFO_BG-> {
|
||||
postOptDress(data.dressType, data.dressId)
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
//更新用户信息
|
||||
UserModel.get().updateCurrentUserInfo().subscribe()
|
||||
setSelect(adapter, position)
|
||||
}
|
||||
.doOnError {
|
||||
it?.message?.doToast()
|
||||
}.subscribe()
|
||||
}
|
||||
|
||||
DressUpTabActivity.TAB_CAR -> {
|
||||
driveThisCar(data.dressId)
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
//更换座驾状态,需要更新缓存
|
||||
UserModel.get().onlyUpdateLoginUserInfoCache()
|
||||
setSelect(adapter, position)
|
||||
}
|
||||
.doOnError {
|
||||
it?.message?.doToast()
|
||||
}.subscribe()
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setData(newData:MutableList<DressUpInfo>) {
|
||||
if (mPage == 1) {
|
||||
val find = newData.indexOfFirst { it.isSelect() }
|
||||
newData.add(0,DressUpUtil.getEmpty(find == -1))
|
||||
mPosition= if (find==-1) 0 else find+1
|
||||
mAdapter.setNewData(newData)
|
||||
} else {
|
||||
mAdapter.addData(newData)
|
||||
}
|
||||
|
||||
if (newData.size >= mPageSize) {
|
||||
mPage++
|
||||
binding.srlLayout.isEnableLoadmore = true
|
||||
} else {
|
||||
binding.srlLayout.isEnableLoadmore = false
|
||||
}
|
||||
stopAnim()
|
||||
}
|
||||
|
||||
private fun setSelect(adapter: BaseBindingAdapter<*, DressUpInfo>?, position: Int) {
|
||||
if (mPosition != -1) {
|
||||
adapter?.data?.getOrNull(mPosition)?.isSelect = false
|
||||
adapter?.notifyItemChanged(mPosition)
|
||||
}
|
||||
|
||||
mPosition = position
|
||||
adapter?.data?.getOrNull(mPosition)?.isSelect = true
|
||||
adapter?.notifyItemChanged(mPosition)
|
||||
R.string.doSuccess.doToast()
|
||||
}
|
||||
|
||||
override fun onItemChildClicks(
|
||||
adapter: BaseBindingAdapter<*, DressUpInfo>?,
|
||||
view: View?,
|
||||
position: Int
|
||||
) {
|
||||
view?.id?.let {
|
||||
when (it) {
|
||||
R.id.btnPlay -> {
|
||||
adapter?.data?.getOrNull(position)?.let { data ->
|
||||
EventBus.getDefault().post(DressUpEvent(DressUpEvent.Action.Play, data))
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemClicks(
|
||||
adapter: BaseBindingAdapter<*, DressUpInfo>?,
|
||||
view: View?,
|
||||
position: Int
|
||||
) {
|
||||
adapter?.data?.getOrNull(position)?.let { data ->
|
||||
EventBus.getDefault().post(DressUpEvent(DressUpEvent.Action.Select, data))
|
||||
if (!data.isSelect() && !data.isHasExpired){
|
||||
userByType(data,adapter, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun getShopMine(): Single<List<ShopMine>> {
|
||||
return api.getShopMine(mDressType,mPage,mPageSize)
|
||||
.compose(RxHelper.handleBeanData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
private fun postOptDress(dressType: Int,dressId: Int): Single<String> {
|
||||
return api.postOptDress(dressType,dressId)
|
||||
.compose(RxHelper.handleStringData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
private fun getUserCarsV2(): Single<List<CarInfo>> {
|
||||
return api.requestMyCarsV2(AuthModel.get().currentUid)
|
||||
.compose(RxHelper.handleBeanData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
private fun driveThisCar(carId: Int): Single<String> {
|
||||
val ticket = AuthModel.get().ticket
|
||||
val uid = AuthModel.get().currentUid
|
||||
return api.driveThisCar(ticket, uid, carId)
|
||||
.compose(RxHelper.handleStringData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
private fun getNamePlateList(): Single<NamePlateInfo> {
|
||||
return api.getNamePlateList(AuthModel.get().currentUid.toString(), mPage.toString(), mPageSize.toString())
|
||||
.compose(RxHelper.handleBeanData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
private fun useMyNamePlate(id: Int,word: String): Single<String> {
|
||||
val ticket = AuthModel.get().ticket
|
||||
val uid = AuthModel.get().currentUid
|
||||
return api.useMyNamePlate(ticket, uid.toString(), id.toString(),word)
|
||||
.compose(RxHelper.handleStringData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
private fun userMyHeadWear(id: Int): Single<String> {
|
||||
val ticket = AuthModel.get().ticket
|
||||
val uid = AuthModel.get().currentUid
|
||||
return api.userMyHeadWear(ticket, uid.toString(), id.toString())
|
||||
.compose(RxHelper.handleStringData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
private fun getMyUserCardWearList(): Single<List<UserCardWearInfo>> {
|
||||
return api.getMyUserCardWearList(mPage,mPageSize)
|
||||
.compose(RxHelper.handleBeanData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
private fun userMyUserCardWear(id: Int): Single<String> {
|
||||
return api.userMyUserCardWear(id.toString())
|
||||
.compose(RxHelper.handleStringData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
|
||||
private fun getChatBubbleInfoList(): Single<List<ChatBubbleInfo>> {
|
||||
return api.getChatBubbleInfoList(mPage,mPageSize)
|
||||
.compose(RxHelper.handleBeanData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
private fun userChatBubble(id: Int): Single<String> {
|
||||
return api.userChatBubble(id.toString())
|
||||
.compose(RxHelper.handleStringData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
|
||||
private val api: Api = RxNet.create(Api::class.java);
|
||||
|
||||
interface Api {
|
||||
|
||||
/**
|
||||
* 获取 我的装扮 : dressType : 5-个人主页背景
|
||||
*/
|
||||
@GET("/dress/shop/mine")
|
||||
fun getShopMine(@Query("dressType") dressType: Int,@Query("page") page: Int,@Query("pageSize") pageSize: Int): Single<ServiceResult<List<ShopMine>>>
|
||||
|
||||
/**
|
||||
* 购买装扮
|
||||
*/
|
||||
@GET("/dress/shop/optDress")
|
||||
fun postOptDress(@Query("dressType") dressType: Int, @Query("dressId") id: Int): Single<ServiceResult<String>>
|
||||
|
||||
/**
|
||||
* 使用座驾
|
||||
*
|
||||
* @param ticket 用户的ticket
|
||||
* @param uid 用户的uid
|
||||
* @param carId 座驾的id,id=0 则表示不使用座驾,id!=0 表示使用该carId的座驾
|
||||
*/
|
||||
@POST("/car/carport/use")
|
||||
@FormUrlEncoded
|
||||
fun driveThisCar(@Field("ticket") ticket: String?, @Field("uid") uid: Long, @Field("carId") carId: Int): Single<ServiceResult<String>>
|
||||
|
||||
/**
|
||||
* 获取自己的车库V2
|
||||
*
|
||||
* @param uid -
|
||||
* @return -
|
||||
*/
|
||||
@GET("car/carport/v2/list")
|
||||
fun requestMyCarsV2(@Query("uid") uid: Long): Single<ServiceResult<List<CarInfo>>>
|
||||
|
||||
/**
|
||||
* 使用头饰
|
||||
*/
|
||||
@POST("v1/user/headwear/use")
|
||||
fun userMyHeadWear(@Query("ticket") ticket: String?,@Query("uid") uid: String?, @Query("headwearId") headwear_id: String?): Single<ServiceResult<String>>
|
||||
|
||||
/**
|
||||
* 获取铭牌列表
|
||||
*/
|
||||
@POST("nameplate/userNameplateList")
|
||||
fun getNamePlateList(@Query("uid") uid: String?, @Query("page") page: String?, @Query("pageSize") pageSize: String?): Single<ServiceResult<NamePlateInfo?>?>
|
||||
|
||||
@POST("nameplate/useNameplate")
|
||||
fun useMyNamePlate(@Query("uid") uid: String?, @Query("ticket") ticket: String?, @Query("userNameplateId") id: String?, @Query("word") word: String?): Single<ServiceResult<String>>
|
||||
|
||||
|
||||
/**
|
||||
* 分页获取用户资料卡装扮列表
|
||||
*/
|
||||
@GET("userInfoCard/listByPage")
|
||||
fun getMyUserCardWearList(@Query("page") page: Int, @Query("pageSize") pageSize: Int): Single<ServiceResult<List<UserCardWearInfo>>>
|
||||
|
||||
/**
|
||||
* 使用资料卡装扮
|
||||
*/
|
||||
@GET("userInfoCard/optUserInfoCard")
|
||||
fun userMyUserCardWear(@Query("cardId") cardId: String?): Single<ServiceResult<String>>
|
||||
|
||||
|
||||
/**
|
||||
* 分页获取用户聊天气泡列表
|
||||
*/
|
||||
@GET("userChatBubble/listByPage")
|
||||
fun getChatBubbleInfoList(@Query("page") page: Int, @Query("pageSize") pageSize: Int): Single<ServiceResult<List<ChatBubbleInfo>>>
|
||||
|
||||
/**
|
||||
* 使用聊天气泡
|
||||
*/
|
||||
@FormUrlEncoded
|
||||
@POST("userChatBubble/optUserChatBubble")
|
||||
fun userChatBubble(@Field("bubbleId") cardId: String?): Single<ServiceResult<String>>
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,170 @@
|
||||
package com.chwl.app.decoration.ui.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.chwl.app.R
|
||||
import com.chwl.app.base.BaseListFragment
|
||||
import com.chwl.app.bindadapter.BaseBindingAdapter
|
||||
import com.chwl.app.common.EmptyViewHelper
|
||||
import com.chwl.app.decoration.adapter.DressUpAdapter
|
||||
import com.chwl.app.decoration.util.DressUpUtil
|
||||
import com.chwl.app.event.DressUpEvent
|
||||
import com.chwl.core.bean.response.ServiceResult
|
||||
import com.chwl.core.decoration.bean.DecorationInfo
|
||||
import com.chwl.core.decoration.bean.DressUpInfo
|
||||
import com.chwl.core.utils.net.RxHelper
|
||||
import com.chwl.library.common.util.doToast
|
||||
import com.chwl.library.common.util.setMargin
|
||||
import com.chwl.library.net.rxnet.RxNet
|
||||
import com.example.lib_utils.ktx.getString
|
||||
import io.reactivex.Single
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import retrofit2.http.Field
|
||||
import retrofit2.http.FormUrlEncoded
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Query
|
||||
|
||||
class DressUpStoreFragment: BaseListFragment<DressUpInfo>() {
|
||||
|
||||
private var mPosition = -1
|
||||
|
||||
companion object {
|
||||
fun newInstance(dressType: Int): DressUpStoreFragment {
|
||||
val args = Bundle()
|
||||
args.putInt("dressType", dressType)
|
||||
val fragment = DressUpStoreFragment()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
|
||||
private val mDressType: Int by lazy { requireArguments().getInt("dressType") }
|
||||
|
||||
override fun initView() {
|
||||
|
||||
binding.srlLayout.isEnableRefresh = false
|
||||
binding.srlLayout.isEnableLoadmore = false
|
||||
|
||||
mAdapter.setEmptyView(EmptyViewHelper.createEmptyTextViewHeight(context, R.string.empty_data.getString()))
|
||||
binding.rvList.setMargin(start = 10, end = 10)
|
||||
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mPosition = -1
|
||||
onLoad()
|
||||
}
|
||||
|
||||
override fun getAdapter(): BaseBindingAdapter<*, DressUpInfo> {
|
||||
return DressUpAdapter()
|
||||
}
|
||||
|
||||
override fun getLayoutManager(): RecyclerView.LayoutManager {
|
||||
return GridLayoutManager(context,2,RecyclerView.VERTICAL,false)
|
||||
}
|
||||
|
||||
|
||||
override fun onLoad() {
|
||||
getShopList()
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
it?.let {
|
||||
val newData = mutableListOf<DressUpInfo>()
|
||||
it.forEach {
|
||||
newData.add(DressUpUtil.tranData(it))
|
||||
}
|
||||
mAdapter.setNewData(newData)
|
||||
}
|
||||
}
|
||||
.doOnError {
|
||||
it?.message?.doToast()
|
||||
}
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
|
||||
}
|
||||
|
||||
override fun onItemChildClicks(adapter: BaseBindingAdapter<*, DressUpInfo>?, view: View?, position: Int) {
|
||||
view?.id?.let {
|
||||
when (it) {
|
||||
R.id.btnPlay -> {
|
||||
adapter?.data?.getOrNull(position)?.let { data->
|
||||
EventBus.getDefault().post(DressUpEvent(DressUpEvent.Action.Play,data))
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemClicks(adapter: BaseBindingAdapter<*, DressUpInfo>?, view: View?, position: Int) {
|
||||
adapter?.data?.getOrNull(position)?.let { data ->
|
||||
|
||||
if (mPosition != -1) {
|
||||
adapter?.data?.getOrNull(mPosition)?.isSelect = false
|
||||
adapter?.notifyItemChanged(mPosition)
|
||||
}
|
||||
|
||||
mPosition = position
|
||||
adapter?.data?.getOrNull(mPosition)?.isSelect = true
|
||||
adapter?.notifyItemChanged(mPosition)
|
||||
|
||||
EventBus.getDefault().post(DressUpEvent(DressUpEvent.Action.Select, data))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun getShopList(): Single<List<DecorationInfo>> {
|
||||
return api.getShopList(mDressType)
|
||||
.compose(RxHelper.handleBeanData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
private val api: Api = RxNet.create(Api::class.java);
|
||||
interface Api {
|
||||
/**
|
||||
* 获取装扮商城列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GET("/dress/shop/list")
|
||||
fun getShopList(@Query("dressType") dressType: Int): Single<ServiceResult<List<DecorationInfo>>>
|
||||
|
||||
/**
|
||||
* 购买装扮
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@FormUrlEncoded
|
||||
@POST("/dress/shop/buy")
|
||||
fun postShopBuy(
|
||||
@Field("dressType") dressType: Int,
|
||||
@Field("id") id: Int
|
||||
): Single<ServiceResult<String>>
|
||||
|
||||
/**
|
||||
* 赠送装扮
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@FormUrlEncoded
|
||||
@POST("/dress/shop/give")
|
||||
fun postShopGive(
|
||||
@Field("dressType") dressType: Int,
|
||||
@Field("id") id: Int,
|
||||
@Field("targetUid") targetUid: Long,
|
||||
): Single<ServiceResult<String>>
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
260
app/src/main/java/com/chwl/app/decoration/util/DressUpUtil.kt
Normal file
@@ -0,0 +1,260 @@
|
||||
package com.chwl.app.decoration.util
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import com.chwl.app.R
|
||||
import com.chwl.app.avroom.widget.GalleryLayoutManager.LayoutParams
|
||||
import com.chwl.app.decoration.ui.activity.DressUpTabActivity
|
||||
import com.chwl.app.decoration.ui.activity.DressUpTabActivity.Companion.TAB_HEAD_WEAR
|
||||
import com.chwl.app.decoration.ui.activity.DressUpTabActivity.Companion.TAB_USER_CARD
|
||||
import com.chwl.app.ui.utils.loadAnim2
|
||||
import com.chwl.app.ui.utils.loadImage
|
||||
import com.chwl.core.decoration.bean.DecorationInfo
|
||||
import com.chwl.core.decoration.bean.DressUpInfo
|
||||
import com.chwl.core.decoration.bean.ShopMine
|
||||
import com.chwl.core.decoration.car.bean.CarInfo
|
||||
import com.chwl.core.decoration.headwear.bean.ChatBubbleInfo
|
||||
import com.chwl.core.decoration.headwear.bean.UserCardWearInfo
|
||||
import com.chwl.core.decoration.nameplate.bean.NamePlateInfo
|
||||
import com.chwl.library.common.util.isVerify
|
||||
import com.chwl.library.common.util.setViewWH
|
||||
import com.chwl.library.common.util.setVis
|
||||
import com.chwl.library.widget.SVGAView
|
||||
import com.chwl.library.widget.text.DrawableTextView
|
||||
import com.example.lib_utils.ktx.getColor
|
||||
import com.example.lib_utils.ktx.getString
|
||||
import com.example.lib_utils.spannable.SpannableTextBuilder
|
||||
import com.tencent.qgame.animplayer.AnimView
|
||||
import com.tencent.qgame.animplayer.util.ScaleType
|
||||
|
||||
class DressUpUtil {
|
||||
companion object {
|
||||
|
||||
fun getEmpty(use:Boolean): DressUpInfo {
|
||||
val outData = DressUpInfo()
|
||||
outData.dressId = 0
|
||||
outData.isMy = true
|
||||
outData.isNull = true
|
||||
outData.isSelect = use
|
||||
return outData
|
||||
}
|
||||
|
||||
fun tranData(inData: DecorationInfo): DressUpInfo {
|
||||
|
||||
val outData = DressUpInfo()
|
||||
|
||||
outData.dressLimitStatus = inData.dressLimitStatus
|
||||
outData.id = inData.id
|
||||
outData.discount = inData.discount
|
||||
outData.originalPrice = inData.dressPrice
|
||||
outData.buyDay = inData.dressDay
|
||||
outData.price = inData.discountPrice.toInt()
|
||||
outData.name = inData.name
|
||||
outData.pic = inData.pic
|
||||
outData.effect = inData.effect
|
||||
outData.effectType = inData.effectType
|
||||
outData.dressType = inData.dressType
|
||||
outData.vipLimit = inData.vipLimit
|
||||
outData.dressId = inData.dressId
|
||||
outData.obtainWay = inData.obtainWay
|
||||
|
||||
return outData
|
||||
}
|
||||
|
||||
// 个人主页 , 头饰
|
||||
fun tranData(inData: ShopMine): DressUpInfo {
|
||||
|
||||
val outData = DressUpInfo()
|
||||
outData.isMy = true
|
||||
outData.isSelect = inData.isUsed
|
||||
outData.name = inData.name
|
||||
outData.pic = inData.pic
|
||||
outData.effect = inData.effect
|
||||
outData.effectType = inData.effectType
|
||||
outData.dressType = inData.dressType
|
||||
outData.dressId = inData.dressId
|
||||
outData.obtainWay = inData.obtainWay
|
||||
|
||||
outData.hasExpired = inData.hasExpired
|
||||
outData.expireDays = inData.expireDays
|
||||
|
||||
return outData
|
||||
}
|
||||
|
||||
fun tranData(inData: ChatBubbleInfo): DressUpInfo {
|
||||
|
||||
val outData = DressUpInfo()
|
||||
outData.isMy = true
|
||||
outData.isSelect = inData.isHasUsed
|
||||
outData.name = inData.name
|
||||
outData.pic = inData.bubbleUrl
|
||||
outData.dressType = DressUpTabActivity.TAB_CHAT_BUBBLE
|
||||
if (inData.bubbleId.isVerify()) {
|
||||
outData.dressId = inData.bubbleId.toInt()
|
||||
}
|
||||
outData.hasExpired = inData.isHasExpired
|
||||
outData.expireDays = inData.expireDays
|
||||
|
||||
return outData
|
||||
}
|
||||
|
||||
fun tranData(inData: UserCardWearInfo): DressUpInfo {
|
||||
|
||||
val outData = DressUpInfo()
|
||||
outData.isMy = true
|
||||
outData.isSelect = inData.isUsed
|
||||
outData.name = inData.name
|
||||
outData.pic = inData.pic
|
||||
outData.effect = inData.pic
|
||||
outData.effectType = DressUpInfo.EffectType.MP4
|
||||
outData.dressType = DressUpTabActivity.TAB_USER_CARD
|
||||
if (inData.cardId.isVerify()) {
|
||||
outData.dressId = inData.cardId.toInt()
|
||||
}
|
||||
|
||||
outData.hasExpired = inData.isHasExpired
|
||||
outData.expireDays = inData.expireDays
|
||||
|
||||
return outData
|
||||
}
|
||||
|
||||
fun tranData(inData: NamePlateInfo.NameplateListBean): DressUpInfo {
|
||||
|
||||
val outData = DressUpInfo()
|
||||
outData.isMy = true
|
||||
outData.isSelect = inData.isUsing
|
||||
outData.name = inData.nameplateName
|
||||
outData.word = inData.word
|
||||
outData.pic = inData.nameplateImage
|
||||
outData.dressType = DressUpTabActivity.TAB_NAMEPLATE
|
||||
outData.dressId = inData.nameplateId
|
||||
outData.id = inData.id
|
||||
|
||||
outData.hasExpired = inData.isExpired
|
||||
outData.expireDays = inData.expireDays
|
||||
|
||||
return outData
|
||||
}
|
||||
|
||||
fun tranData(inData: CarInfo): DressUpInfo {
|
||||
|
||||
val outData = DressUpInfo()
|
||||
outData.isMy = true
|
||||
outData.isSelect = inData.using == 1
|
||||
outData.name = inData.name
|
||||
outData.pic = inData.pic
|
||||
if (inData.viewUrl.isVerify()) {
|
||||
outData.effect = inData.viewUrl
|
||||
outData.effectType = inData.otherViewType
|
||||
}else{
|
||||
outData.effect = inData.effect
|
||||
outData.effectType = inData.otherViewType
|
||||
}
|
||||
outData.dressType = DressUpTabActivity.TAB_CAR
|
||||
outData.dressId = inData.carId
|
||||
|
||||
outData.hasExpired = inData.status != CarInfo.STATUS_USER_CAN_USE
|
||||
|
||||
// val cTime = System.currentTimeMillis()
|
||||
// val dTime = inData.expireDays - cTime
|
||||
// val dDay = TimeUnit.MICROSECONDS.toDays(dTime)
|
||||
// if (dDay < TimeUnit.DAYS.toMillis(1)) {
|
||||
// // < 1 天
|
||||
// } else {
|
||||
// // dDay天后过期
|
||||
// }
|
||||
|
||||
outData.expireDays = inData.days
|
||||
|
||||
return outData
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun setTextPrice(textView: DrawableTextView, item: DressUpInfo) {
|
||||
val message = R.string.s_sDays_s.getString(item.price, item.buyDay, item.originalPrice)
|
||||
SpannableTextBuilder(textView).appendText(message)
|
||||
.setTextStyle(
|
||||
text = item.price.toString(),
|
||||
textStyle = Typeface.BOLD
|
||||
).setTextStyle(
|
||||
text = item.buyDay.toString(),
|
||||
textStyle = Typeface.NORMAL
|
||||
).setTextStyle(
|
||||
text = item.originalPrice.toString(),
|
||||
textColor = R.color.color_d9e7f7.getColor(),
|
||||
delLine = true
|
||||
).apply()
|
||||
textView.setVis(true)
|
||||
}
|
||||
|
||||
fun setItemPic(data:DressUpInfo,layout: ViewGroup) {
|
||||
if (data.dressType == DressUpTabActivity.TAB_USER_CARD) {
|
||||
//此时传回的是mp4..
|
||||
// layout.setViewWH()
|
||||
play(data,layout,true)
|
||||
} else {
|
||||
layout.removeAllViews()
|
||||
val pic = ImageView(layout.context)
|
||||
layout.addView(pic)
|
||||
if (data.dressType == DressUpTabActivity.TAB_CAR) {
|
||||
pic.setViewWH(129,129)
|
||||
}else if (data.dressType == DressUpTabActivity.TAB_HEAD_WEAR) {
|
||||
pic.setViewWH(117,117)
|
||||
}else if (data.dressType == DressUpTabActivity.TAB_NAMEPLATE) {
|
||||
pic.setViewWH(98,28)
|
||||
}else if (data.dressType == DressUpTabActivity.TAB_CHAT_BUBBLE) {
|
||||
pic.setViewWH(90,46)
|
||||
}else if (data.dressType == DressUpTabActivity.TAB_USER_INFO_BG) {
|
||||
pic.setViewWH(127,125)
|
||||
}
|
||||
pic.loadImage(data.pic)
|
||||
}
|
||||
}
|
||||
|
||||
fun play(data:DressUpInfo,layout: ViewGroup,isItem :Boolean = false){
|
||||
if (data.effect.isVerify()) {
|
||||
|
||||
var animView : AnimView?=null
|
||||
var svgaView : SVGAView?=null
|
||||
|
||||
layout.setVis(true)
|
||||
layout.removeAllViews()
|
||||
|
||||
if (data.effectType == DressUpInfo.EffectType.MP4) {
|
||||
animView = AnimView(layout.context)
|
||||
layout.addView(animView)
|
||||
animView.setLoop(Int.MAX_VALUE)
|
||||
animView.setScaleType(ScaleType.FIT_XY)
|
||||
} else {
|
||||
svgaView = SVGAView(layout.context)
|
||||
layout.addView(svgaView)
|
||||
svgaView.loops = Int.MAX_VALUE
|
||||
svgaView.setScaleType(ImageView.ScaleType.FIT_XY)
|
||||
}
|
||||
|
||||
//item 时占满就行
|
||||
if (isItem) {
|
||||
animView?.setViewWH(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, false)
|
||||
svgaView?.setViewWH(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,false)
|
||||
} else {
|
||||
if (data.dressType == TAB_HEAD_WEAR) {
|
||||
animView?.setViewWH(183, 183, true)
|
||||
svgaView?.setViewWH(183, 183, true)
|
||||
}else if (data.dressType == TAB_USER_CARD) {
|
||||
animView?.setViewWH(285, 250, true)
|
||||
svgaView?.setViewWH(285, 250, true)
|
||||
} else {
|
||||
animView?.setViewWH(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, false)
|
||||
svgaView?.setViewWH(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
animView?.loadAnim2(data.effect,false)
|
||||
svgaView?.loadUrl(data.effect,true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -11,6 +11,7 @@ import com.chwl.app.R
|
||||
import com.chwl.app.base.BaseViewBindingActivity
|
||||
import com.chwl.app.base.TitleBar
|
||||
import com.chwl.app.databinding.ActivityDecorationStoreBinding
|
||||
import com.chwl.app.decoration.ui.activity.DressUpTabActivity
|
||||
import com.chwl.app.decoration.view.widgets.CarMagicIndicator
|
||||
import com.chwl.app.decoration.view.widgets.MyDecorationMagicIndicator
|
||||
import com.chwl.app.decoration.viewmodel.DecorationViewModel
|
||||
@@ -60,7 +61,7 @@ class DecorationStoreActivity : BaseViewBindingActivity<ActivityDecorationStoreB
|
||||
ResUtil.getString(R.string.decoration_view_decorationstoreactivity_02), Color.parseColor("#999999")
|
||||
) {
|
||||
override fun performAction(view: View) {
|
||||
MyDecorationActivity.start(this@DecorationStoreActivity, 0)
|
||||
DressUpTabActivity.start(this@DecorationStoreActivity,true)
|
||||
}
|
||||
})
|
||||
mPosition = intent.getIntExtra(Constants.KEY_POSITION, 0)
|
||||
|
29
app/src/main/java/com/chwl/app/event/DressUpEvent.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.chwl.app.event;
|
||||
|
||||
import com.chwl.core.decoration.bean.DressUpInfo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DressUpEvent {
|
||||
public int action;
|
||||
public DressUpInfo data;
|
||||
|
||||
public DressUpEvent() {
|
||||
}
|
||||
|
||||
public DressUpEvent(int action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public DressUpEvent(int action, DressUpInfo data) {
|
||||
this.action = action;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public @interface Action{
|
||||
int Select = 1;
|
||||
int Play = 2;
|
||||
}
|
||||
|
||||
}
|
@@ -7,7 +7,6 @@ import android.view.View;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.netease.nimlib.sdk.msg.model.IMMessage;
|
||||
import com.chwl.app.R;
|
||||
import com.chwl.app.base.BaseBindingActivity;
|
||||
import com.chwl.app.base.TitleBar;
|
||||
@@ -34,6 +33,7 @@ import com.chwl.core.utils.net.DontWarnObserver;
|
||||
import com.chwl.library.annatation.ActLayoutRes;
|
||||
import com.chwl.library.utils.ResUtil;
|
||||
import com.chwl.library.utils.SingleToastUtil;
|
||||
import com.netease.nimlib.sdk.msg.model.IMMessage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@@ -21,6 +21,7 @@ import com.chwl.app.avroom.dialog.RoomBgSetDialog
|
||||
import com.chwl.app.base.BaseActivity
|
||||
import com.chwl.app.base.BaseFragment
|
||||
import com.chwl.app.databinding.FragmentMeBinding
|
||||
import com.chwl.app.decoration.ui.activity.DressUpTabActivity
|
||||
import com.chwl.app.home.HomeViewModel
|
||||
import com.chwl.app.home.MeViewModel
|
||||
import com.chwl.app.home.activity.AssociationActivity
|
||||
@@ -39,7 +40,6 @@ import com.chwl.app.ui.webview.CommonWebViewActivity
|
||||
import com.chwl.app.utils.HomeUIManager
|
||||
import com.chwl.app.view.GenderAgeTextView
|
||||
import com.chwl.app.vip.VipCenterActivity
|
||||
import com.chwl.app.vip.VipCenterActivity.Companion.start
|
||||
import com.chwl.app.vip.VipViewModel
|
||||
import com.chwl.core.auth.AuthModel
|
||||
import com.chwl.core.initial.InitialModel
|
||||
@@ -374,7 +374,7 @@ class MeFragment : BaseFragment(), View.OnClickListener {
|
||||
R.id.tv_user_name -> {
|
||||
//todo do 测试按钮
|
||||
if (BuildConfig.DEBUG) {
|
||||
start(requireActivity(), 8)
|
||||
DressUpTabActivity.start(requireActivity(),false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -7,17 +7,18 @@ import com.bumptech.glide.load.DataSource
|
||||
import com.bumptech.glide.load.engine.GlideException
|
||||
import com.bumptech.glide.request.RequestListener
|
||||
import com.bumptech.glide.request.target.Target
|
||||
import com.chwl.app.BuildConfig
|
||||
import com.chwl.app.base.BaseViewModel
|
||||
import com.chwl.library.utils.PathHelper
|
||||
import com.chwl.core.home.model.HomeModel
|
||||
import com.chwl.core.utils.LogUtils
|
||||
import com.chwl.library.common.glide.GlideUtils
|
||||
import com.chwl.library.common.util.SPUtils
|
||||
import com.chwl.library.utils.NetworkUtils
|
||||
import com.chwl.library.utils.PathHelper
|
||||
import com.example.lib_utils.AppUtils
|
||||
import com.example.lib_utils.FileUtils2
|
||||
import com.example.lib_utils.log.ILog
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
@@ -33,18 +34,24 @@ class PreloadResourceViewModel : BaseViewModel(), ILog , RequestListener<File?>
|
||||
|
||||
private var mContext : Context? = null
|
||||
|
||||
//todo 预加载
|
||||
fun start(context: Context) {
|
||||
mContext = context
|
||||
if (BuildConfig.DEBUG) {
|
||||
// 太多请求了,影响查看控制台日志
|
||||
return
|
||||
}
|
||||
|
||||
// if (BuildConfig.DEBUG) {
|
||||
// // 太多请求了,影响查看控制台日志
|
||||
// return
|
||||
// }
|
||||
|
||||
if (isStarted) {
|
||||
return
|
||||
}
|
||||
getPreloadResourceList {
|
||||
isStarted = true
|
||||
nextTask(null)
|
||||
|
||||
viewModelScope?.launch(Dispatchers.IO) {
|
||||
getPreloadResourceList {
|
||||
isStarted = true
|
||||
nextTask(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +98,7 @@ class PreloadResourceViewModel : BaseViewModel(), ILog , RequestListener<File?>
|
||||
}
|
||||
}
|
||||
|
||||
private fun downloadTask(url: String) {
|
||||
private fun downloadTask(url: String?) {
|
||||
|
||||
// val path = PathHelper.generateResourcesFilePath(url)
|
||||
// logI("downloadTask() url:${url} path:${path}")
|
||||
@@ -104,9 +111,13 @@ class PreloadResourceViewModel : BaseViewModel(), ILog , RequestListener<File?>
|
||||
// )
|
||||
// DownloadManager.download(request, this)
|
||||
|
||||
GlideUtils.instance().downloadFromUrl(mContext,url,this)
|
||||
|
||||
|
||||
viewModelScope.launch {
|
||||
delay(500)
|
||||
LogUtils.d("预加载 -> downloadTask url = ${url?.trim()}")
|
||||
if (url != null) {
|
||||
GlideUtils.instance().downloadFromUrl2(mContext,url.trim(),this@PreloadResourceViewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLoadFailed(
|
||||
@@ -119,6 +130,7 @@ class PreloadResourceViewModel : BaseViewModel(), ILog , RequestListener<File?>
|
||||
logI("onDownloadError() url:${model} message:${e?.message}")
|
||||
nextTask(model)
|
||||
}
|
||||
LogUtils.d("预加载 onLoadFailed 失败 url = ${model}")
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -134,7 +146,7 @@ class PreloadResourceViewModel : BaseViewModel(), ILog , RequestListener<File?>
|
||||
makeDownloadRecord(model)
|
||||
nextTask(null)
|
||||
}
|
||||
|
||||
LogUtils.d("预加载 onResourceReady 成功 url = ${model}")
|
||||
return true
|
||||
}
|
||||
|
||||
|
@@ -4,16 +4,6 @@ import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.chwl.app.decoration.view.DecorationStoreActivity;
|
||||
import com.chwl.app.earn.activity.EarnRecordActivity;
|
||||
import com.chwl.app.pay.activity.GiveGoldActivity;
|
||||
import com.chwl.app.ui.feedback.FeedbackActivity;
|
||||
import com.chwl.app.ui.game_team.record.GameTeamRecordActivity;
|
||||
import com.chwl.app.ui.setting.VipSetActivity;
|
||||
import com.chwl.app.vip.VipCenterActivity;
|
||||
import com.chwl.core.module_hall.hall.bean.H5FamilyInfo;
|
||||
import com.chwl.core.module_hall.hall.bean.UserClanInfo;
|
||||
import com.trello.rxlifecycle3.components.support.RxAppCompatActivity;
|
||||
import com.chwl.app.R;
|
||||
import com.chwl.app.UIHelper;
|
||||
import com.chwl.app.audio.VoiceMatchActivity;
|
||||
@@ -22,31 +12,38 @@ import com.chwl.app.avroom.recommendcard.MyRecommendCardActivity;
|
||||
import com.chwl.app.base.BaseActivity;
|
||||
import com.chwl.app.base.DialogManagerInterface;
|
||||
import com.chwl.app.common.widget.dialog.DialogManager;
|
||||
import com.chwl.app.decoration.view.MyDecorationActivity;
|
||||
import com.chwl.app.decoration.ui.activity.DressUpTabActivity;
|
||||
import com.chwl.app.earn.activity.EarnRecordActivity;
|
||||
import com.chwl.app.home.activity.CollectionRoomActivity;
|
||||
import com.chwl.app.home.activity.VisitorListActivity;
|
||||
import com.chwl.app.home.helper.OpenRoomHelper;
|
||||
import com.chwl.app.module_hall.HallDataManager;
|
||||
import com.chwl.app.module_hall.hall.activity.ModuleClanActivity;
|
||||
import com.chwl.app.module_hall.hall.activity.ModuleHallActivity;
|
||||
import com.chwl.app.pay.activity.GiveGoldActivity;
|
||||
import com.chwl.app.radish.task.activity.TaskCenterActivity;
|
||||
import com.chwl.app.relation.cp.activity.CpHomeActivity;
|
||||
import com.chwl.app.relation.cp.activity.CpInviteRecordActivity;
|
||||
import com.chwl.app.relation.cp.activity.CpTaskActivity;
|
||||
import com.chwl.app.team.view.NimTeamMessageActivity;
|
||||
import com.chwl.app.ui.feedback.FeedbackActivity;
|
||||
import com.chwl.app.ui.game_team.record.GameTeamRecordActivity;
|
||||
import com.chwl.app.ui.login.BindPhoneActivity;
|
||||
import com.chwl.app.ui.login.ShowBindPhoneActivity;
|
||||
import com.chwl.app.ui.pay.ChargeActivity;
|
||||
import com.chwl.app.ui.setting.ModifyPwdActivity;
|
||||
import com.chwl.app.ui.user.activity.UserInfoActivity;
|
||||
import com.chwl.app.ui.webview.CommonWebViewActivity;
|
||||
import com.chwl.app.vip.VipCenterActivity;
|
||||
import com.chwl.core.DemoCache;
|
||||
import com.chwl.core.auth.AuthModel;
|
||||
import com.chwl.core.community.event.SquareTaskEvent;
|
||||
import com.chwl.core.im.custom.bean.RouterType;
|
||||
import com.chwl.core.manager.AvRoomDataManager;
|
||||
import com.chwl.core.module_hall.hall.HallModel;
|
||||
import com.chwl.core.module_hall.hall.bean.H5FamilyInfo;
|
||||
import com.chwl.core.module_hall.hall.bean.HallInfo;
|
||||
import com.chwl.core.module_hall.hall.bean.UserClanInfo;
|
||||
import com.chwl.core.room.bean.RoomInfo;
|
||||
import com.chwl.core.room.model.AvRoomModel;
|
||||
import com.chwl.core.utils.net.BeanObserver;
|
||||
@@ -55,6 +52,7 @@ import com.chwl.library.net.rxnet.callback.CallBack;
|
||||
import com.chwl.library.utils.JavaUtil;
|
||||
import com.chwl.library.utils.ResUtil;
|
||||
import com.chwl.library.utils.SingleToastUtil;
|
||||
import com.trello.rxlifecycle3.components.support.RxAppCompatActivity;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
@@ -104,27 +102,27 @@ public class RouterHandler {
|
||||
break;
|
||||
case RouterType.CAR:
|
||||
if (JavaUtil.str2int(routerValue) == 0) {
|
||||
DecorationStoreActivity.start(context, DecorationStoreActivity.TAB_CAR);
|
||||
DressUpTabActivity.Companion.start(context,false);
|
||||
} else {
|
||||
MyDecorationActivity.start(context, 1);
|
||||
DressUpTabActivity.Companion.start(context,true);
|
||||
}
|
||||
break;
|
||||
case RouterType.DECORATION:
|
||||
if (JavaUtil.str2int(routerValue) == 0) {
|
||||
DecorationStoreActivity.start(context, 0);
|
||||
DressUpTabActivity.Companion.start(context,false);
|
||||
} else {
|
||||
MyDecorationActivity.start(context, 0);
|
||||
DressUpTabActivity.Companion.start(context,true);
|
||||
}
|
||||
break;
|
||||
case RouterType.NAMEPLATE:
|
||||
if (JavaUtil.str2int(routerValue) == 0) {
|
||||
DecorationStoreActivity.start(context, DecorationStoreActivity.TAB_NAMEPLATE);
|
||||
DressUpTabActivity.Companion.start(context,false);
|
||||
} else {
|
||||
MyDecorationActivity.start(context, 2);
|
||||
DressUpTabActivity.Companion.start(context,true);
|
||||
}
|
||||
break;
|
||||
case RouterType.USER_CARD_WEAR:
|
||||
MyDecorationActivity.start(context, 3);
|
||||
DressUpTabActivity.Companion.start(context,true);
|
||||
break;
|
||||
case RouterType.TEAM:
|
||||
NimTeamMessageActivity.start(context, routerValue);
|
||||
@@ -226,10 +224,10 @@ public class RouterHandler {
|
||||
CpTaskActivity.Companion.start(context);
|
||||
break;
|
||||
case RouterType.CP_WARE:
|
||||
MyDecorationActivity.start(context, 0);
|
||||
DressUpTabActivity.Companion.start(context,true);
|
||||
break;
|
||||
case RouterType.USER_BUBBLE:
|
||||
MyDecorationActivity.start(context, 4);
|
||||
DressUpTabActivity.Companion.start(context,true);
|
||||
break;
|
||||
case RouterType.MY_ROOM:
|
||||
//我的房间,开房
|
||||
@@ -278,13 +276,13 @@ public class RouterHandler {
|
||||
if (intRouterValue < 0 || intRouterValue > 4) {
|
||||
intRouterValue = 0;
|
||||
}
|
||||
DecorationStoreActivity.start(context, intRouterValue);
|
||||
DressUpTabActivity.Companion.start(context,false);
|
||||
break;
|
||||
case RouterType.MY_DECORATION:
|
||||
if (intRouterValue < 0 || intRouterValue > 4) {
|
||||
intRouterValue = 0;
|
||||
}
|
||||
MyDecorationActivity.start(context, intRouterValue);
|
||||
DressUpTabActivity.Companion.start(context,true);
|
||||
break;
|
||||
case RouterType.MY_SET:
|
||||
UIHelper.showSettingAct(context);
|
||||
@@ -299,7 +297,7 @@ public class RouterHandler {
|
||||
GameTeamRecordActivity.Companion.start(context);
|
||||
break;
|
||||
case RouterType.MY_DRESS_ITEM:
|
||||
MyDecorationActivity.start(context, 0);
|
||||
DressUpTabActivity.Companion.start(context,true);
|
||||
break;
|
||||
default:
|
||||
SingleToastUtil.showToast(ResUtil.getString(R.string.ui_im_routerhandler_07));
|
||||
|
@@ -7,11 +7,8 @@ import android.text.style.ForegroundColorSpan;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase;
|
||||
import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter;
|
||||
import com.netease.nimlib.sdk.msg.attachment.MsgAttachment;
|
||||
import com.chwl.app.R;
|
||||
import com.chwl.app.decoration.view.MyDecorationActivity;
|
||||
import com.chwl.app.decoration.ui.activity.DressUpTabActivity;
|
||||
import com.chwl.app.ui.im.RouterHandler;
|
||||
import com.chwl.app.ui.webview.CommonWebViewActivity;
|
||||
import com.chwl.app.utils.SpannableBuilder;
|
||||
@@ -28,6 +25,9 @@ import com.chwl.core.im.custom.bean.NobleAttachment;
|
||||
import com.chwl.core.im.custom.bean.VoiceBottleShakeHeartAttachment;
|
||||
import com.chwl.core.manager.IMNetEaseManager;
|
||||
import com.chwl.library.utils.ResUtil;
|
||||
import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase;
|
||||
import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter;
|
||||
import com.netease.nimlib.sdk.msg.attachment.MsgAttachment;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
@@ -151,7 +151,7 @@ public class MsgViewHolderText extends MsgViewHolderBase {
|
||||
|
||||
} else if (mCarAttachment != null) {
|
||||
if (mCarAttachment.mSecond == CUSTOM_MESS_SUB_CAR_EXPIRE) {
|
||||
MyDecorationActivity.start(mTvMsg.getContext(), 1);
|
||||
DressUpTabActivity.Companion.start(context,true);
|
||||
}
|
||||
} else if (awardAttachment != null) {
|
||||
RouterHandler.handle(context, awardAttachment.routerType, awardAttachment.routerValue);
|
||||
|
158
app/src/main/java/com/chwl/app/ui/search/SearchUserActivity.kt
Normal file
@@ -0,0 +1,158 @@
|
||||
package com.chwl.app.ui.search
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.chwl.app.R
|
||||
import com.chwl.app.base.BaseViewBindingActivity
|
||||
import com.chwl.app.bindadapter.BaseBindingAdapter
|
||||
import com.chwl.app.bindadapter.BaseBindingViewHolder
|
||||
import com.chwl.app.common.EmptyViewHelper
|
||||
import com.chwl.app.databinding.ActivitySearchUserBinding
|
||||
import com.chwl.app.databinding.ItemSearchUserBinding
|
||||
import com.chwl.app.decoration.ui.DressUpDialog
|
||||
import com.chwl.app.ui.utils.loadAvatar
|
||||
import com.chwl.core.bean.response.ServiceResult
|
||||
import com.chwl.core.decoration.bean.DressUpInfo
|
||||
import com.chwl.core.im.friend.IMFriendModel
|
||||
import com.chwl.core.room.bean.SearchRoomInfo
|
||||
import com.chwl.core.user.UserModel
|
||||
import com.chwl.core.user.bean.UserInfo
|
||||
import com.chwl.core.utils.net.RxHelper
|
||||
import com.chwl.library.common.util.doToast
|
||||
import com.chwl.library.common.util.isVerify
|
||||
import com.chwl.library.net.rxnet.RxNet
|
||||
import com.example.lib_utils.ktx.getString
|
||||
import com.google.gson.Gson
|
||||
import io.reactivex.Single
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Query
|
||||
|
||||
class SearchUserActivity : BaseViewBindingActivity<ActivitySearchUserBinding>() {
|
||||
|
||||
companion object{
|
||||
|
||||
fun start(context: Context, data:String) {
|
||||
val intent = Intent(context, SearchUserActivity::class.java)
|
||||
intent.putExtra("json",data)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private var mDressUpInfo : DressUpInfo? = null
|
||||
private val mJson : String by lazy { intent.getStringExtra("json")?:"" }
|
||||
lateinit var mAdapter : UserAdapter
|
||||
override fun transparencyBar() = true
|
||||
|
||||
|
||||
override fun init() {
|
||||
initDarkTitleBar(R.string.search.getString())
|
||||
|
||||
if (mJson.isVerify()) {
|
||||
mDressUpInfo = Gson().fromJson(mJson,DressUpInfo::class.java)
|
||||
}
|
||||
|
||||
mAdapter= UserAdapter()
|
||||
binding.rvList.layoutManager = LinearLayoutManager(context,RecyclerView.VERTICAL,false)
|
||||
binding.rvList.adapter = mAdapter
|
||||
mAdapter.setEmptyView(EmptyViewHelper.createEmptyTextViewHeight(context,R.string.no_frenids_text.getString()))
|
||||
|
||||
mAdapter.setOnItemChildClickListener { adapter, view, position ->
|
||||
|
||||
when (view.id) {
|
||||
R.id.btnGive -> {
|
||||
val uid = mAdapter?.data?.getOrNull(position)?.uid
|
||||
if (uid != null && mDressUpInfo != null) {
|
||||
val dressUpDialog = DressUpDialog()
|
||||
dressUpDialog.mDressUpInfo = mDressUpInfo
|
||||
dressUpDialog.mTargetUid = uid
|
||||
dressUpDialog.show(context)
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
binding.etSearch.doOnTextChanged { text, start, before, count ->
|
||||
text?.let {
|
||||
doSearch(text.toString())
|
||||
}
|
||||
}
|
||||
|
||||
loadFriends()
|
||||
|
||||
}
|
||||
|
||||
private fun loadFriends() {
|
||||
val accounts = IMFriendModel.get().myFriendsAccounts
|
||||
if (accounts.isVerify()) {
|
||||
UserModel.get().loadUserInfoByUids(accounts)
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
mAdapter.setNewData(it)
|
||||
}
|
||||
.doOnError {
|
||||
it?.message?.doToast()
|
||||
}.subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
private fun doSearch(key: String) {
|
||||
roomSearch(key)
|
||||
.compose(bindToLifecycle())
|
||||
.doOnSuccess {
|
||||
if (it.isVerify()) {
|
||||
val newData = mutableListOf<UserInfo>()
|
||||
it.forEach {
|
||||
newData.add(UserInfo().apply {
|
||||
avatar = it.avatar
|
||||
uid = it.uid
|
||||
erbanNo = it.erbanNo
|
||||
nick = it.nick
|
||||
})
|
||||
mAdapter.setNewData(newData)
|
||||
}
|
||||
}
|
||||
}.doOnError {
|
||||
it?.message?.doToast()
|
||||
}.subscribe()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class UserAdapter : BaseBindingAdapter<ItemSearchUserBinding, UserInfo>() {
|
||||
|
||||
override fun convert(helper: BaseBindingViewHolder<ItemSearchUserBinding>, item: UserInfo) {
|
||||
helper.binding.let {
|
||||
it.avatar.loadAvatar(item.avatar)
|
||||
it.name.text = item.nick
|
||||
it.id.text = item.erbanNo.toString()
|
||||
|
||||
helper.addOnClickListener(it.btnGive.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun roomSearch(key: String) : Single<List<SearchRoomInfo>>{
|
||||
return api.roomSearch(key,2)
|
||||
.compose(RxHelper.handleBeanData())
|
||||
.compose(RxHelper.handleSchedulers())
|
||||
}
|
||||
|
||||
private val api: Api = RxNet.create(Api::class.java);
|
||||
|
||||
interface Api {
|
||||
@GET("/search/room")
|
||||
fun roomSearch(
|
||||
@Query("key") key: String?,
|
||||
@Query("type") type: Int
|
||||
): Single<ServiceResult<List<SearchRoomInfo>>>
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@@ -3,7 +3,6 @@ package com.chwl.app.ui.user.activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import androidx.core.content.ContentProviderCompat.requireContext
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@@ -21,18 +20,13 @@ import com.chwl.core.UriProvider
|
||||
import com.chwl.core.bean.response.ServiceResult
|
||||
import com.chwl.core.user.bean.UserCPListBean
|
||||
import com.chwl.core.utils.LogUtils
|
||||
import com.chwl.core.utils.net.DontWarnObserver
|
||||
import com.chwl.core.utils.net.RxHelper
|
||||
import com.chwl.library.net.rxnet.RxNet
|
||||
import com.chwl.library.utils.ResUtil
|
||||
import com.example.lib_utils.ktx.getString
|
||||
import com.google.gson.JsonElement
|
||||
import com.hjq.toast.ToastUtils
|
||||
import com.netease.nim.uikit.StatusBarUtil
|
||||
import com.trello.rxlifecycle3.android.ActivityEvent
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.SingleObserver
|
||||
import io.reactivex.disposables.Disposable
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Query
|
||||
@@ -59,7 +53,7 @@ class UserCpListActivity : BaseViewBindingActivity<ActivityUserCpListBinding>()
|
||||
}
|
||||
|
||||
private fun initTitle() {
|
||||
initBlackTitleBar(ResUtil.getString(R.string.My_Cp))
|
||||
initDarkTitleBar(ResUtil.getString(R.string.My_Cp))
|
||||
val titleBar = findViewById<View>(R.id.title_bar) as TitleBar
|
||||
titleBar.addAction(object : ImageAction(R.drawable.ic_cp_list_more) {
|
||||
override fun performAction(view: View?) {
|
||||
|
@@ -173,9 +173,9 @@ fun AnimView.loadAnim(url: String) {
|
||||
})
|
||||
}
|
||||
|
||||
fun AnimView.loadAnim2(url: String) {
|
||||
fun AnimView.loadAnim2(url: String,isSafe:Boolean = true) {
|
||||
if (context.isDestroyed()) return
|
||||
GlideUtils.instance().downloadFromUrl(context,url.trim(),object : RequestListener<File?> {
|
||||
GlideUtils.instance().downloadFromUrl2(context,url.trim(),object : RequestListener<File?> {
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any?,
|
||||
@@ -193,9 +193,14 @@ fun AnimView.loadAnim2(url: String) {
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
if (resource != null) {
|
||||
if (this@loadAnim2.isAttachedToWindow){
|
||||
if (isSafe) {
|
||||
if (this@loadAnim2.isAttachedToWindow){
|
||||
this@loadAnim2.startPlay(resource)
|
||||
}
|
||||
} else {
|
||||
this@loadAnim2.startPlay(resource)
|
||||
}
|
||||
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@@ -5,9 +5,7 @@ import static android.content.Context.CLIPBOARD_SERVICE;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.media.MediaRecorder;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
@@ -18,34 +16,27 @@ import androidx.annotation.NonNull;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.chwl.app.earn.activity.EarnRecordActivity;
|
||||
import com.chwl.app.ui.invite.InviteImageHelper;
|
||||
import com.chwl.app.ui.invite.ShareInviteDialog;
|
||||
import com.chwl.app.ui.invite.ShareInviteInfo;
|
||||
import com.chwl.app.ui.wallet.payment.GPaymentClient;
|
||||
import com.chwl.app.ui.wallet.payment.IPaymentClient;
|
||||
import com.chwl.app.ui.wallet.payment.PaymentIntent;
|
||||
import com.chwl.app.ui.wallet.payment.PaymentResult;
|
||||
import com.chwl.library.language.LanguageHelper;
|
||||
import com.chwl.library.utils.json.JsonUtils;
|
||||
import com.example.lib_utils.ICleared;
|
||||
import com.google.gson.Gson;
|
||||
import com.netease.nim.uikit.common.util.log.LogUtil;
|
||||
import com.orhanobut.logger.Logger;
|
||||
import com.chwl.app.UIHelper;
|
||||
import com.chwl.app.application.IReportConstants;
|
||||
import com.chwl.app.application.ReportManager;
|
||||
import com.chwl.app.avroom.activity.AVRoomActivity;
|
||||
import com.chwl.app.earn.activity.EarnRecordActivity;
|
||||
import com.chwl.app.ui.im.RouterHandler;
|
||||
import com.chwl.app.ui.im.avtivity.NimP2PMessageActivity;
|
||||
import com.chwl.app.ui.invite.InviteImageHelper;
|
||||
import com.chwl.app.ui.invite.ShareInviteDialog;
|
||||
import com.chwl.app.ui.invite.ShareInviteInfo;
|
||||
import com.chwl.app.ui.pay.ChargeActivity;
|
||||
import com.chwl.app.ui.wallet.payment.GPaymentClient;
|
||||
import com.chwl.app.ui.wallet.payment.IPaymentClient;
|
||||
import com.chwl.app.ui.wallet.payment.PaymentIntent;
|
||||
import com.chwl.app.ui.wallet.payment.PaymentResult;
|
||||
import com.chwl.app.ui.webview.event.H5NotifyClientEvent;
|
||||
import com.chwl.app.ui.webview.event.ShowNavEvent;
|
||||
import com.chwl.app.ui.webview.event.TaroPayResultEvent;
|
||||
import com.chwl.core.XConstants;
|
||||
import com.chwl.core.auth.AuthModel;
|
||||
import com.chwl.core.decoration.bean.DecorationStoreRouterType;
|
||||
import com.chwl.core.file.FileModel;
|
||||
import com.chwl.core.manager.AvRoomDataManager;
|
||||
import com.chwl.core.market_verify.MarketVerifyModel;
|
||||
import com.chwl.core.pay.PayModel;
|
||||
@@ -55,18 +46,21 @@ import com.chwl.core.room.bean.RoomInfo;
|
||||
import com.chwl.core.user.UserModel;
|
||||
import com.chwl.core.web.bean.WebJsBeanInfo;
|
||||
import com.chwl.library.common.util.DeviceUtil;
|
||||
import com.chwl.library.record.AuditRecorderConfiguration;
|
||||
import com.chwl.library.record.ExtAudioRecorder;
|
||||
import com.chwl.library.language.LanguageHelper;
|
||||
import com.chwl.library.rxbus.RxBus;
|
||||
import com.chwl.library.utils.AppMetaDataUtil;
|
||||
import com.chwl.library.utils.DeviceUuidFactory;
|
||||
import com.chwl.library.utils.SystemUtils;
|
||||
import com.chwl.library.utils.VersionUtil;
|
||||
import com.chwl.library.utils.config.BasicConfig;
|
||||
import com.chwl.library.utils.json.JsonUtils;
|
||||
import com.example.lib_utils.ICleared;
|
||||
import com.google.gson.Gson;
|
||||
import com.netease.nim.uikit.common.util.log.LogUtil;
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
@@ -79,9 +73,9 @@ public class JSInterface implements ICleared {
|
||||
private CommonWebViewActivity mActivity;
|
||||
private Context context;
|
||||
private int mPosition;
|
||||
private MediaRecorder recorder;
|
||||
private File myRecAudioFile;
|
||||
private ExtAudioRecorder extAudioRecorder;
|
||||
// private MediaRecorder recorder;
|
||||
// private File myRecAudioFile;
|
||||
// private ExtAudioRecorder extAudioRecorder;
|
||||
private GPaymentClient paymentClient;
|
||||
|
||||
public JSInterface(WebView webView, CommonWebViewActivity activity) {
|
||||
@@ -420,45 +414,45 @@ public class JSInterface implements ICleared {
|
||||
NimP2PMessageActivity.start(context, uid);
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public boolean startRecode() {
|
||||
// recorder 实例
|
||||
AuditRecorderConfiguration configuration = new AuditRecorderConfiguration.Builder()
|
||||
.uncompressed(true)
|
||||
.builder();
|
||||
extAudioRecorder = new ExtAudioRecorder(configuration);
|
||||
// 录音地址
|
||||
File sdcardDir = new File(context.getExternalFilesDir(Environment.DIRECTORY_MUSIC).getAbsolutePath() +
|
||||
File.separator + "wewawa");
|
||||
if (!sdcardDir.exists()) {
|
||||
boolean mkdirResult = sdcardDir.mkdir();
|
||||
Log.e(TAG, "startRecode: mkdirResult: " + mkdirResult);
|
||||
}
|
||||
myRecAudioFile = new File(sdcardDir.getAbsolutePath(), "wewawa-" + System.currentTimeMillis() + ".wav");
|
||||
Log.i(TAG, "startRecode: myRecAudioFile path: " + myRecAudioFile.getAbsolutePath());
|
||||
// 设置输出文件
|
||||
extAudioRecorder.setOutputFile(myRecAudioFile.getAbsolutePath());
|
||||
extAudioRecorder.prepare();
|
||||
extAudioRecorder.start();
|
||||
return true;
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public String stopRecode() {
|
||||
if (extAudioRecorder == null || myRecAudioFile == null)
|
||||
return null;
|
||||
if (!myRecAudioFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
extAudioRecorder.stop();
|
||||
extAudioRecorder.release();
|
||||
String url = FileModel.get()
|
||||
.uploadFile(myRecAudioFile.getAbsolutePath())
|
||||
.blockingGet();
|
||||
myRecAudioFile.delete();
|
||||
Log.i(TAG, "stopRecord: url: " + url);
|
||||
return url;
|
||||
}
|
||||
// @JavascriptInterface
|
||||
// public boolean startRecode() {
|
||||
// // recorder 实例
|
||||
// AuditRecorderConfiguration configuration = new AuditRecorderConfiguration.Builder()
|
||||
// .uncompressed(true)
|
||||
// .builder();
|
||||
// extAudioRecorder = new ExtAudioRecorder(configuration);
|
||||
// // 录音地址
|
||||
// File sdcardDir = new File(context.getExternalFilesDir(Environment.DIRECTORY_MUSIC).getAbsolutePath() +
|
||||
// File.separator + "wewawa");
|
||||
// if (!sdcardDir.exists()) {
|
||||
// boolean mkdirResult = sdcardDir.mkdir();
|
||||
// Log.e(TAG, "startRecode: mkdirResult: " + mkdirResult);
|
||||
// }
|
||||
// myRecAudioFile = new File(sdcardDir.getAbsolutePath(), "wewawa-" + System.currentTimeMillis() + ".wav");
|
||||
// Log.i(TAG, "startRecode: myRecAudioFile path: " + myRecAudioFile.getAbsolutePath());
|
||||
// // 设置输出文件
|
||||
// extAudioRecorder.setOutputFile(myRecAudioFile.getAbsolutePath());
|
||||
// extAudioRecorder.prepare();
|
||||
// extAudioRecorder.start();
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @JavascriptInterface
|
||||
// public String stopRecode() {
|
||||
// if (extAudioRecorder == null || myRecAudioFile == null)
|
||||
// return null;
|
||||
// if (!myRecAudioFile.exists()) {
|
||||
// return null;
|
||||
// }
|
||||
// extAudioRecorder.stop();
|
||||
// extAudioRecorder.release();
|
||||
// String url = FileModel.get()
|
||||
// .uploadFile(myRecAudioFile.getAbsolutePath())
|
||||
// .blockingGet();
|
||||
// myRecAudioFile.delete();
|
||||
// Log.i(TAG, "stopRecord: url: " + url);
|
||||
// return url;
|
||||
// }
|
||||
|
||||
@JavascriptInterface
|
||||
public void openFamilyPage(String familyId) {
|
||||
|
@@ -81,7 +81,10 @@ class BaiShunGameWebFragment : BaseViewBindingFragment<RoomGameFragmentBinding>(
|
||||
super.onPageStarted(view, url, favicon)
|
||||
isLoadError = false
|
||||
if (url == gameUrl) {
|
||||
dialogManager.showProgressDialog(requireContext())
|
||||
context?.let {
|
||||
dialogManager.showProgressDialog(it)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +165,7 @@ class BaiShunGameWebFragment : BaseViewBindingFragment<RoomGameFragmentBinding>(
|
||||
settings?.domStorageEnabled = true
|
||||
//设置开启数据库缓存
|
||||
settings?.databaseEnabled = true
|
||||
settings?.databasePath = (requireContext().applicationContext.filesDir.absolutePath)
|
||||
settings?.databasePath = (context?.applicationContext?.filesDir?.absolutePath)
|
||||
//设置⽀持缩放
|
||||
settings?.setSupportZoom(true)
|
||||
//设置⾃适应
|
||||
|
@@ -86,7 +86,7 @@ class LeaderccGameWebFragment : BaseViewBindingFragment<RoomGameFragmentBinding>
|
||||
super.onPageStarted(view, url, favicon)
|
||||
isLoadError = false
|
||||
if (url == gameUrl) {
|
||||
dialogManager.showProgressDialog(requireContext())
|
||||
dialogManager.showProgressDialog(context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ class LeaderccGameWebFragment : BaseViewBindingFragment<RoomGameFragmentBinding>
|
||||
settings?.domStorageEnabled = true
|
||||
//设置开启数据库缓存
|
||||
settings?.databaseEnabled = true
|
||||
settings?.databasePath = (requireContext().applicationContext.filesDir.absolutePath)
|
||||
settings?.databasePath = (context?.applicationContext?.filesDir?.absolutePath)
|
||||
//设置⽀持缩放
|
||||
settings?.setSupportZoom(true)
|
||||
//设置⾃适应
|
||||
|
@@ -667,7 +667,7 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
|
||||
|
||||
private void drawVAPEffect(String url) {
|
||||
|
||||
GlideUtils.instance().downloadFromUrl(getContext(), url, new RequestListener<File>() {
|
||||
GlideUtils.instance().downloadFromUrl2(getContext(), url, new RequestListener<File>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<File> target, boolean isFirstResource) {
|
||||
ImageLoadUtils.loadImage(context, userInfo.getUserInfoCardPic(), ivUserCardWear);
|
||||
|
@@ -115,7 +115,7 @@ object RoomBoomManager {
|
||||
urls.forEach { url ->
|
||||
LogUtils.dd(" RoomBoomManager startDownAnim() forEach url=$url")
|
||||
mAnimLayout?.let { animLayout ->
|
||||
GlideUtils.instance().downloadFromUrl(
|
||||
GlideUtils.instance().downloadFromUrl2(
|
||||
animLayout.context,
|
||||
url.trim(),
|
||||
object : RequestListener<File?> {
|
||||
|
@@ -135,8 +135,7 @@ class VipCenterBannerAdapter(
|
||||
|
||||
})
|
||||
|
||||
//todo do , liulishuo 下载器 换 glide 下载 , 注意 .trim() 去掉前后空格符
|
||||
GlideUtils.instance().downloadFromUrl(holder.vapAnimView.context,data.vipLogo.trim(),object : RequestListener<File?> {
|
||||
GlideUtils.instance().downloadFromUrl2(holder.vapAnimView.context,data.vipLogo.trim(),object : RequestListener<File?> {
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any?,
|
||||
|
BIN
app/src/main/res/drawable-xxhdpi/ic_derss_avatar.webp
Normal file
After Width: | Height: | Size: 872 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_dialog_bg.webp
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_dialog_line.webp
Normal file
After Width: | Height: | Size: 488 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_item_long_n.webp
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_item_long_s.webp
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_item_n.webp
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_item_s.webp
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_play.webp
Normal file
After Width: | Height: | Size: 674 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_tab_bg_n.webp
Normal file
After Width: | Height: | Size: 762 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_tab_bg_s.webp
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_tab_car.webp
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_tab_card.webp
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_tab_chat.webp
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_tab_head.webp
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_tab_homepage.webp
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_tab_nameplate.webp
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_dress_top_bg.webp
Normal file
After Width: | Height: | Size: 206 KiB |
193
app/src/main/res/layout/activity_dress_up_tab.xml
Normal file
@@ -0,0 +1,193 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#02061d">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:background="@drawable/ic_dress_top_bg"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
<com.chwl.app.base.TitleBar
|
||||
android:id="@+id/title_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_30"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:id="@+id/btnMyDressUp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:drawablePadding="2dp"
|
||||
android:gravity="center"
|
||||
android:paddingHorizontal="7dp"
|
||||
android:paddingVertical="2dp"
|
||||
android:text="@string/My_Dress"
|
||||
android:textColor="@color/color_d9e7f7"
|
||||
android:textSize="12sp"
|
||||
app:dt_drawableRightHeight="13dp"
|
||||
app:dt_drawableRightSrc="@drawable/ic_derss_avatar"
|
||||
app:dt_drawableRightWidth="13dp"
|
||||
app:dt_drawableType="shape"
|
||||
app:dt_endColor="#11215b"
|
||||
app:dt_radius="198dp"
|
||||
app:dt_startColor="#004a4f"
|
||||
app:dt_strikeColor="#75b4df"
|
||||
app:dt_strikeWidth="1dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/title_bar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/title_bar" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/infoLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/title_bar">
|
||||
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:layout_width="73dp"
|
||||
app:dt_drawableType="shape"
|
||||
app:dt_soildColor="#fbd99a"
|
||||
android:layout_gravity="center"
|
||||
app:dt_radius="150dp"
|
||||
android:layout_height="73dp"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="71dp"
|
||||
android:src="@drawable/default_avatar"
|
||||
android:layout_height="71dp"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<com.chwl.library.widget.SVGAView
|
||||
android:id="@+id/avatarHead"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<com.chwl.library.widget.tab.SmartTabLayout2
|
||||
android:id="@+id/tabLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="0dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/infoLayout"
|
||||
app:stl_distributeEvenly="true"
|
||||
app:stl_indicatorThickness="0dp"
|
||||
app:stl_indicatorWidth="0dp"
|
||||
tools:layout_height="40dp" />
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/viewPage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/bottomView"
|
||||
app:layout_constraintTop_toBottomOf="@id/tabLayout" />
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/bottomView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="66dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:dt_drawableType="shape"
|
||||
app:dt_endColor="#0f1435"
|
||||
app:dt_leftTopRadius="8dp"
|
||||
app:dt_rightTopRadius="8dp"
|
||||
app:dt_startColor="#012e4d" />
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:id="@+id/price"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dp"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="center"
|
||||
android:textColor="#f8ce1f"
|
||||
android:textStyle="bold"
|
||||
app:autoSizeStepGranularity="@dimen/picker_default_text_size"
|
||||
app:dt_drawableLeftHeight="25dp"
|
||||
app:dt_drawableLeftSrc="@drawable/ic_coin_84"
|
||||
app:dt_drawableLeftWidth="25dp"
|
||||
app:dt_drawableType="shape"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/s_sDays_s" />
|
||||
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:id="@+id/btnBuy"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:gravity="center"
|
||||
android:minWidth="74dp"
|
||||
android:minHeight="32dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="6dp"
|
||||
android:text="@string/buy"
|
||||
android:textColor="#172055"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:dt_drawableType="shape"
|
||||
app:dt_endColor="#e9a71d"
|
||||
app:dt_radius="47dp"
|
||||
app:dt_startColor="#FFE3b2"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/btnGive"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:id="@+id/btnGive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:gravity="center"
|
||||
android:minWidth="74dp"
|
||||
android:minHeight="32dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="6dp"
|
||||
android:text="@string/ui_search_searchadapter_03"
|
||||
android:textColor="#172055"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:dt_drawableType="shape"
|
||||
app:dt_endColor="#4da2ea"
|
||||
app:dt_radius="47dp"
|
||||
app:dt_startColor="#b2fcff"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/playLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black_transparent_50"
|
||||
android:gravity="center"
|
||||
android:visibility="gone"
|
||||
tools:visibility="gone" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
66
app/src/main/res/layout/activity_search_user.xml
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#02061d">
|
||||
|
||||
<com.chwl.app.base.TitleBar
|
||||
android:id="@+id/title_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_30"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:dt_drawableType="shape"
|
||||
app:dt_radius="436dp"
|
||||
app:dt_soildColor="#061337"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/etSearch"
|
||||
app:layout_constraintEnd_toEndOf="@+id/etSearch"
|
||||
app:layout_constraintStart_toStartOf="@+id/etSearch"
|
||||
app:layout_constraintTop_toTopOf="@+id/etSearch" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etSearch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="15dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@color/transparent"
|
||||
android:gravity="center"
|
||||
android:paddingVertical="10dp"
|
||||
android:paddingStart="45dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:textColor="@color/color_d9e7f7"
|
||||
android:textColorHint="@color/color_d9e7f7"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title_bar"
|
||||
tools:text="111" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginStart="15dp"
|
||||
android:src="@drawable/ic_send_search"
|
||||
app:layout_constraintBottom_toBottomOf="@id/etSearch"
|
||||
app:layout_constraintStart_toStartOf="@id/etSearch"
|
||||
app:layout_constraintTop_toTopOf="@+id/etSearch"
|
||||
app:tint="#707d97" />
|
||||
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/etSearch" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@@ -537,14 +537,14 @@
|
||||
<!-- avatar -->
|
||||
<ImageView
|
||||
android:id="@+id/ivUserHead"
|
||||
android:layout_width="@dimen/dp_82"
|
||||
android:layout_height="@dimen/dp_82"
|
||||
android:layout_width="92dp"
|
||||
android:layout_height="96dp"
|
||||
android:src="@drawable/default_avatar"
|
||||
tools:src="@color/white"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/ivHeadWear"
|
||||
app:layout_constraintEnd_toEndOf="@+id/ivHeadWear"
|
||||
app:layout_constraintStart_toStartOf="@+id/ivHeadWear"
|
||||
app:layout_constraintTop_toTopOf="@id/ivHeadWear" />
|
||||
app:layout_constraintTop_toTopOf="@id/ivHeadWear"
|
||||
tools:src="@color/white" />
|
||||
|
||||
<com.chwl.library.widget.SVGAView
|
||||
android:id="@+id/ivHeadWear"
|
||||
|
31
app/src/main/res/layout/base_list_fragment.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
<com.chwl.app.base.TitleBar
|
||||
android:id="@+id/title_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:layout_marginTop="@dimen/dp_30"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.scwang.smartrefresh.layout.SmartRefreshLayout
|
||||
android:id="@+id/srl_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title_bar">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
117
app/src/main/res/layout/dialog_dress_up.xml
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:background="@drawable/ic_dress_dialog_bg"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/picLayout"
|
||||
android:layout_width="155dp"
|
||||
android:layout_height="155dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:gravity="center"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_gif" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/color_d9e7f7"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/picLayout"
|
||||
tools:text="sssss" />
|
||||
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:id="@+id/price"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="9dp"
|
||||
android:layout_marginTop="7dp"
|
||||
android:drawablePadding="2dp"
|
||||
android:gravity="center"
|
||||
android:textColor="#f8ce1f"
|
||||
android:textSize="18sp"
|
||||
android:visibility="gone"
|
||||
app:dt_drawableLeftHeight="18dp"
|
||||
app:dt_drawableLeftSrc="@drawable/ic_gif"
|
||||
app:dt_drawableLeftWidth="18dp"
|
||||
app:dt_drawableType="shape"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/name"
|
||||
tools:text="@string/s_sDays_s"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/line"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/ic_dress_dialog_line"
|
||||
android:layout_marginHorizontal="23dp"
|
||||
android:layout_marginTop="18dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/price" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="90dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/line" />
|
||||
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:id="@+id/btnCancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="5dp"
|
||||
android:gravity="center"
|
||||
android:minWidth="74dp"
|
||||
android:minHeight="32dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="6dp"
|
||||
android:text="@string/cancel"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:dt_drawableType="shape"
|
||||
app:dt_radius="47dp"
|
||||
app:dt_soildColor="@color/black_transparent_30"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/btnBuy"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/line" />
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:id="@+id/btnBuy"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="5dp"
|
||||
android:gravity="center"
|
||||
android:minWidth="74dp"
|
||||
android:minHeight="32dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="6dp"
|
||||
android:text="@string/buy"
|
||||
android:textColor="#172055"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:dt_drawableType="shape"
|
||||
app:dt_endColor="#e9a71d"
|
||||
app:dt_radius="47dp"
|
||||
app:dt_startColor="#FFE3b2"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/btnCancel"
|
||||
app:layout_constraintTop_toBottomOf="@id/line" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@@ -44,6 +44,7 @@
|
||||
android:textColor="@color/white"
|
||||
android:textSize="10sp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
150
app/src/main/res/layout/item_dress_up_layout.xml
Normal file
@@ -0,0 +1,150 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="5dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:background="@drawable/ic_dress_item_n">
|
||||
|
||||
|
||||
<com.chwl.app.common.widget.RectRoundImageView
|
||||
android:id="@+id/picBg"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="150dp"
|
||||
android:layout_marginTop="9dp"
|
||||
android:background="#04184A"
|
||||
app:borderRadius="10dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:type="round" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:gravity="center"
|
||||
android:id="@+id/picLayout"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="150dp"
|
||||
android:layout_marginTop="9dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="9dp"
|
||||
android:lines="1"
|
||||
android:paddingVertical="6dp"
|
||||
android:textColor="#d9e7f7"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/picBg"
|
||||
tools:text="11111" />
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:id="@+id/price"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="9dp"
|
||||
android:drawablePadding="2dp"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="7dp"
|
||||
android:textColor="#f8ce1f"
|
||||
android:textSize="15sp"
|
||||
android:visibility="gone"
|
||||
app:dt_drawableLeftHeight="18dp"
|
||||
app:dt_drawableLeftSrc="@drawable/ic_coin_84"
|
||||
app:dt_drawableLeftWidth="18dp"
|
||||
app:dt_drawableType="shape"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/name"
|
||||
tools:text="@string/s_sDays_s"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:id="@+id/discount"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="3dp"
|
||||
android:gravity="center"
|
||||
android:paddingVertical="6dp"
|
||||
android:textColor="#D9E7F7"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:dt_drawableType="shape"
|
||||
app:dt_leftBottomRadius="13dp"
|
||||
app:dt_rightBottomRadius="13dp"
|
||||
app:dt_soildColor="#002840"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/price"
|
||||
tools:text="111"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="3dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/discount" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/empty"
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="55dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/picBg"
|
||||
app:layout_constraintEnd_toEndOf="@id/picBg"
|
||||
app:layout_constraintStart_toStartOf="@id/picBg"
|
||||
app:layout_constraintTop_toTopOf="@id/picBg"
|
||||
tools:background="@drawable/icon_room_bg_gif_type"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/btnPlay"
|
||||
android:layout_width="46dp"
|
||||
android:layout_height="42dp"
|
||||
android:layout_marginEnd="-8dp"
|
||||
android:layout_marginBottom="-8dp"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:paddingVertical="10dp"
|
||||
android:src="@drawable/ic_dress_play"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/picLayout"
|
||||
app:layout_constraintEnd_toEndOf="@id/picLayout"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:id="@+id/limit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="7dp"
|
||||
android:paddingVertical="2dp"
|
||||
android:textColor="#51281b"
|
||||
android:textSize="12sp"
|
||||
app:dt_drawableType="shape"
|
||||
app:dt_endColor="#E9A71D"
|
||||
app:dt_leftBottomRadius="0dp"
|
||||
app:dt_leftTopRadius="10dp"
|
||||
app:dt_rightBottomRadius="10dp"
|
||||
app:dt_rightTopRadius="0dp"
|
||||
app:dt_startColor="#FFE3B2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Limited" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
64
app/src/main/res/layout/item_search_user.xml
Normal file
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="72dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginStart="15dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textColor="@color/color_d9e7f7"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintStart_toEndOf="@+id/avatar"
|
||||
app:layout_constraintTop_toTopOf="@+id/avatar" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:alpha="0.5"
|
||||
android:textColor="@color/color_d9e7f7"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/avatar"
|
||||
app:layout_constraintStart_toEndOf="@+id/avatar" />
|
||||
|
||||
|
||||
<com.chwl.library.widget.text.DrawableTextView
|
||||
android:id="@+id/btnGive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:gravity="center"
|
||||
android:minWidth="60dp"
|
||||
android:minHeight="26dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="6dp"
|
||||
android:text="@string/ui_search_searchadapter_03"
|
||||
android:textColor="#172055"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:dt_drawableType="shape"
|
||||
app:dt_endColor="#4da2ea"
|
||||
app:dt_radius="47dp"
|
||||
app:dt_startColor="#b2fcff"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
41
app/src/main/res/layout/tab_dress_up_layout.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="85dp"
|
||||
android:layout_marginHorizontal="5dp"
|
||||
android:layout_gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/tabBg"
|
||||
android:background="@drawable/ic_dress_tab_bg_n"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/tabImg"
|
||||
android:layout_width="37dp"
|
||||
android:layout_height="37dp"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@color/white" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tabText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="15dp"
|
||||
android:gravity="center"
|
||||
android:lines="1"
|
||||
android:alpha="0.5"
|
||||
android:textColor="#D9E7F7"
|
||||
android:textSize="11sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tabImg"
|
||||
tools:text="tab" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@@ -5343,4 +5343,5 @@
|
||||
<string name="s_sDays">%s/%s يوم</string>
|
||||
<string name="sDays">%s يوم</string>
|
||||
<string name="unDay"><1 يوم</string>
|
||||
<string name="s_sDays_s">%s/%s يوم %s</string>
|
||||
</resources>
|
@@ -5139,4 +5139,5 @@ Toplam imza alın, ilgili ödülü alın
|
||||
<string name="s_sDays">%s/%s gün</string>
|
||||
<string name="sDays">%s gün</string>
|
||||
<string name="unDay"><1 gün</string>
|
||||
<string name="s_sDays_s">%s/%s gün %s</string>
|
||||
</resources>
|
||||
|
@@ -5286,5 +5286,6 @@
|
||||
<string name="s_sDays">%s/%s天</string>
|
||||
<string name="sDays">%s天</string>
|
||||
<string name="unDay"><1天</string>
|
||||
<string name="s_sDays_s">%s/%s天 %s</string>
|
||||
|
||||
</resources>
|
@@ -769,5 +769,6 @@
|
||||
<color name="color_696969">#696969</color>
|
||||
<color name="color_ff9741">#ff9741</color>
|
||||
<color name="color_ff5656">#ff5656</color>
|
||||
<color name="color_d9e7f7">#d9e7f7</color>
|
||||
|
||||
</resources>
|
||||
|
@@ -5350,6 +5350,14 @@ You cannot join again within 24 hours after leaving</string>
|
||||
<string name="sDays">%sDays</string>
|
||||
<string name="unDay"><1Days</string>
|
||||
|
||||
|
||||
<string name="Not_used">Not used</string>
|
||||
<string name="userInfoBg">userInfoBg</string>
|
||||
<string name="My_Dress">My Dress</string>
|
||||
<string name="vipLimit">VIP限制 %s</string>
|
||||
<string name="obtainWayAction">活动获取 不可购买</string>
|
||||
<string name="s_sDays_s">%s/%sDays %s</string>
|
||||
|
||||
</resources>
|
||||
|
||||
|
||||
|
@@ -16,6 +16,8 @@
|
||||
<!-- 记得移除测试用代码,正式包 别包含进去 -->
|
||||
<domain includeSubdomains="true">beta.api.molistar.xyz</domain>
|
||||
<domain includeSubdomains="true">beta.img.pekolive.com</domain>
|
||||
<domain includeSubdomains="true">image.lecheng163.com</domain>
|
||||
<domain includeSubdomains="true">image.hfighting.com</domain>
|
||||
</domain-config>
|
||||
|
||||
<domain-config cleartextTrafficPermitted="false">
|
||||
|
@@ -10,5 +10,12 @@ data class DecorationInfo(
|
||||
val iosPic: String = "",
|
||||
val name: String = "",
|
||||
val pic: String = "",
|
||||
val dressLimitStatus: Int = 0
|
||||
val dressLimitStatus: Int = 0,
|
||||
val effect: String = "", //装扮动效图片
|
||||
val effectType: Int = 0, //动效类型
|
||||
val discountPrice: Double = 0.0, //折扣价格
|
||||
val vipLevel: Int = 0, //VIP等级
|
||||
val discount: Int = 0, // 折扣百分比
|
||||
val vipLimit: Int = 0, //VIP等级限定 ,0=不限定
|
||||
val obtainWay: Int = 0 //1-普通 2-活动
|
||||
)
|
@@ -0,0 +1,45 @@
|
||||
package com.chwl.core.decoration.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DressUpInfo {
|
||||
public boolean isNull;
|
||||
public boolean isMy;
|
||||
public boolean isSelect;
|
||||
public int dressLimitStatus;
|
||||
|
||||
public String pic;
|
||||
public String name;
|
||||
public String word;
|
||||
public int price;
|
||||
public int buyDay;
|
||||
public int originalPrice;
|
||||
|
||||
public String effect; //装扮动效图片
|
||||
/**
|
||||
* 特效类型 1-mp4 2-svga
|
||||
*/
|
||||
public int effectType;
|
||||
public int dressType; // 商品类型
|
||||
public int dressId; // 商品类型
|
||||
public int discountPrice; //折扣价格
|
||||
public int vipLevel; //当前用户VIP等级
|
||||
public int discount; // 折扣百分比
|
||||
public int vipLimit; //VIP等级限定 ,0=不限定
|
||||
/**
|
||||
* //1-普通 2-活动
|
||||
*/
|
||||
public int obtainWay;
|
||||
public int id; //商品类型id
|
||||
|
||||
|
||||
public int expireDays; //剩余天数
|
||||
public boolean hasExpired; //是否过期
|
||||
|
||||
public @interface EffectType{
|
||||
int MP4 = 1;
|
||||
int SVGA = 2;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package com.chwl.core.decoration.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ShopMine {
|
||||
public int dressId; //装扮id
|
||||
public int dressType; //装扮类型
|
||||
public int obtainWay; //获取方式 1-普通 2-活动
|
||||
|
||||
public String pic;
|
||||
public String name;
|
||||
public String effect;
|
||||
public boolean used;
|
||||
public int expireDays = -1; //剩余天数
|
||||
public int effectType;
|
||||
public boolean hasExpired; //是否过期
|
||||
|
||||
|
||||
}
|
@@ -122,6 +122,7 @@ public class HeadwearModel extends BaseModel implements IHeadwearModel {
|
||||
|
||||
/**
|
||||
* 使用已经购买的头饰
|
||||
* id == 0标识不使用头饰
|
||||
*
|
||||
* @param headwearId
|
||||
* @return
|
||||
|
@@ -36,6 +36,7 @@ public class TabInfo implements Parcelable,Serializable {
|
||||
protected String name;
|
||||
protected String pict;
|
||||
protected int seq;
|
||||
protected int res;
|
||||
protected int type;
|
||||
protected boolean status;
|
||||
protected boolean istop;
|
||||
@@ -49,6 +50,12 @@ public class TabInfo implements Parcelable,Serializable {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public TabInfo(int id, String name,int res) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.res = res;
|
||||
}
|
||||
|
||||
|
||||
protected TabInfo(Parcel in) {
|
||||
id = in.readInt();
|
||||
|
@@ -7,21 +7,12 @@ import android.annotation.SuppressLint;
|
||||
import android.text.TextUtils;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.chwl.core.utils.MyUriUtils;
|
||||
import com.chwl.library.common.glide.GlideUtils;
|
||||
import com.google.gson.Gson;
|
||||
import com.netease.nim.uikit.common.util.string.StringUtil;
|
||||
import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder;
|
||||
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage;
|
||||
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum;
|
||||
import com.orhanobut.logger.Logger;
|
||||
import com.chwl.core.DemoCache;
|
||||
import com.chwl.core.auth.AuthModel;
|
||||
import com.chwl.core.base.BaseModel;
|
||||
@@ -41,12 +32,20 @@ import com.chwl.core.room.queue.bean.MicMemberInfo;
|
||||
import com.chwl.core.user.UserModel;
|
||||
import com.chwl.core.user.bean.UserInfo;
|
||||
import com.chwl.core.utils.LogUtils;
|
||||
import com.chwl.core.utils.MyUriUtils;
|
||||
import com.chwl.core.vip.bean.UserVipInfo;
|
||||
import com.chwl.library.common.glide.GlideUtils;
|
||||
import com.chwl.library.utils.ListUtils;
|
||||
import com.chwl.library.utils.NetworkUtils;
|
||||
import com.chwl.library.utils.codec.DESUtils;
|
||||
import com.chwl.library.utils.codec.MD5Utils;
|
||||
import com.chwl.library.utils.config.BasicConfig;
|
||||
import com.google.gson.Gson;
|
||||
import com.netease.nim.uikit.common.util.string.StringUtil;
|
||||
import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder;
|
||||
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage;
|
||||
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum;
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
@@ -55,7 +54,6 @@ import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
@@ -67,11 +65,6 @@ import io.reactivex.Single;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.functions.BiConsumer;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Headers;
|
||||
@@ -634,7 +627,7 @@ public class DynamicFaceModel extends BaseModel implements IDynamicFaceModel {
|
||||
String url = onlineFacesList.getZipUrl();
|
||||
|
||||
|
||||
GlideUtils.instance().downloadFromUrl(getContext(), url, new RequestListener<File>() {
|
||||
GlideUtils.instance().downloadFromUrl2(getContext(), url, new RequestListener<File>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<File> target, boolean isFirstResource) {
|
||||
Logger.d("face.zip download onLoadFailed");
|
||||
|
@@ -6,6 +6,7 @@ import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.chwl.core.manager.AvRoomDataManager;
|
||||
import com.chwl.library.utils.BitmapLruCacheHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package com.chwl.core.utils;
|
||||
package com.chwl.library.utils;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
@@ -1,8 +1,15 @@
|
||||
package com.chwl.library.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Matrix
|
||||
import android.graphics.drawable.AnimationDrawable
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
import android.util.LruCache
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.DataSource
|
||||
import com.bumptech.glide.load.engine.GlideException
|
||||
import com.bumptech.glide.request.RequestListener
|
||||
@@ -76,7 +83,7 @@ class SVGAView : SVGAImageView, ILog {
|
||||
}
|
||||
|
||||
fun loadUrl(url: String?,autoPayer:Boolean = true) {
|
||||
logD("loadUrl() url:$url")
|
||||
logD("SVGAView loadUrl() url:$url")
|
||||
if (url.isNullOrEmpty()) {
|
||||
this.resourceUrl = null
|
||||
this.setImageDrawable(null)
|
||||
@@ -84,17 +91,8 @@ class SVGAView : SVGAImageView, ILog {
|
||||
return
|
||||
}
|
||||
|
||||
if (!url.endsWith(".svga")) {
|
||||
this.resourceUrl = null
|
||||
this.setImageDrawable(null)
|
||||
onViewStateChanged(0)
|
||||
GlideUtils.instance().load(url,this)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (url == resourceUrl && drawable is SVGADrawable) {
|
||||
logD("loadUrl() 已加载 isAnimating:$isAnimating")
|
||||
logD("SVGAView loadUrl() 已加载 isAnimating:$isAnimating")
|
||||
if (!isAnimating) {
|
||||
if (autoPayer) {
|
||||
startAnimation()
|
||||
@@ -107,7 +105,7 @@ class SVGAView : SVGAImageView, ILog {
|
||||
this.resourceUrl = url
|
||||
val cacheItem = svgaCache?.get(url)
|
||||
if (cacheItem != null) {
|
||||
logD("loadUrl() 有缓存")
|
||||
logD("SVGAView loadUrl() 有缓存")
|
||||
this@SVGAView.setImageDrawable(SVGADrawable(cacheItem))
|
||||
if (autoPayer) {
|
||||
this@SVGAView.startAnimation()
|
||||
@@ -118,15 +116,15 @@ class SVGAView : SVGAImageView, ILog {
|
||||
}
|
||||
|
||||
private fun loadSVGAUrl(url: String,autoPayer:Boolean = true) {
|
||||
logD("loadSVGAUrl url:$url")
|
||||
GlideUtils.instance().downloadFromUrl(context,url,object : RequestListener<File?> {
|
||||
logD("SVGAView loadSVGAUrl url:$url")
|
||||
GlideUtils.instance().downloadFromUrl2(context,url,object : RequestListener<File?> {
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any?,
|
||||
target: Target<File?>?,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
logD("loadSVGAUrl onDownloadError url:$url")
|
||||
logD("SVGAView loadSVGAUrl onDownloadError url:$url")
|
||||
if (resourceUrl == url) {
|
||||
onViewStateChanged(-1)
|
||||
}
|
||||
@@ -142,20 +140,112 @@ class SVGAView : SVGAImageView, ILog {
|
||||
): Boolean {
|
||||
if (resource != null) {
|
||||
val path = resource.path
|
||||
logD("loadSVGAUrl onDownloadCompleted url:$url path:$path")
|
||||
if (resourceUrl == url) {
|
||||
loadSVGAFile(url, path,autoPayer)
|
||||
var isImg = false
|
||||
var outMimeType = "null"
|
||||
try {
|
||||
val options = BitmapFactory.Options()
|
||||
options.inJustDecodeBounds = true
|
||||
val decodeFile = BitmapFactory.decodeFile(path, options)
|
||||
outMimeType = options.outMimeType
|
||||
isImg = true
|
||||
|
||||
} catch (e: Exception) {
|
||||
isImg = false
|
||||
}
|
||||
|
||||
logD("SVGAView loadSVGAUrl onDownloadCompleted url:$url isImg=$isImg outMimeType=$outMimeType path:$path")
|
||||
if (!isImg) {
|
||||
loadSVGAFile(url, path, autoPayer)
|
||||
} else {
|
||||
this@SVGAView.post {
|
||||
this@SVGAView.resourceUrl = null
|
||||
onViewStateChanged(0)
|
||||
loadImage(url)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun loadImage(url: String) {
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.dontAnimate()
|
||||
.dontTransform()
|
||||
.load(url)
|
||||
.listener(object : RequestListener<Bitmap?> {
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any,
|
||||
target: Target<Bitmap?>,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
this@SVGAView.resourceUrl = null
|
||||
onViewStateChanged(0)
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onResourceReady(
|
||||
resource: Bitmap?,
|
||||
model: Any,
|
||||
target: Target<Bitmap?>,
|
||||
dataSource: DataSource,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
if (resource == null) return false
|
||||
val split: List<Drawable> = split(resource)
|
||||
val animationDrawable = AnimationDrawable()
|
||||
for (i in split.indices) {
|
||||
animationDrawable.addFrame(split[i], 200)
|
||||
}
|
||||
this@SVGAView.post(Runnable {
|
||||
this@SVGAView.setImageDrawable(animationDrawable)
|
||||
animationDrawable.isOneShot = false
|
||||
animationDrawable.start()
|
||||
})
|
||||
return false
|
||||
}
|
||||
}).submit()
|
||||
}
|
||||
|
||||
fun split(bitmap: Bitmap?): List<Drawable> {
|
||||
val pieces: MutableList<Drawable> = ArrayList()
|
||||
try {
|
||||
if (bitmap!!.width == bitmap.height) {
|
||||
pieces.add(BitmapDrawable(bitmap))
|
||||
} else {
|
||||
val matrix = Matrix()
|
||||
matrix.setScale(0.5f, 0.5f)
|
||||
|
||||
val width = bitmap.width
|
||||
val pieceWidth = bitmap.height
|
||||
val pieceHeight = bitmap.height
|
||||
val xPiece = width / pieceWidth
|
||||
for (j in 0 until xPiece) {
|
||||
val xValue = j * pieceWidth
|
||||
pieces.add(
|
||||
BitmapDrawable(
|
||||
Bitmap.createBitmap(
|
||||
bitmap, xValue, 0,
|
||||
pieceWidth, pieceHeight, matrix, true
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e: java.lang.Exception) {
|
||||
}
|
||||
return pieces
|
||||
}
|
||||
|
||||
private fun loadSVGAFile(url: String, path: String,autoPayer:Boolean = true) {
|
||||
try {
|
||||
logD("loadSVGAFile path:$path url:$url")
|
||||
logD("SVGAView loadSVGAFile path:$path url:$url")
|
||||
val inputStream = BufferedInputStream(FileInputStream(path))
|
||||
shareParser().decodeFromInputStream(
|
||||
inputStream,
|
||||
@@ -188,7 +278,7 @@ class SVGAView : SVGAImageView, ILog {
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
logD("loadSVGAFile url:$url e:${e.message}")
|
||||
logD("SVGAView loadSVGAFile url:$url e:${e.message}")
|
||||
onViewStateChanged(-1)
|
||||
}
|
||||
}
|
||||
@@ -197,16 +287,16 @@ class SVGAView : SVGAImageView, ILog {
|
||||
* @param state -1 异常、0 空、1 成功
|
||||
*/
|
||||
private fun onViewStateChanged(state: Int) {
|
||||
logD("onViewStateChanged state:$state")
|
||||
logD("SVGAView onViewStateChanged state:$state")
|
||||
}
|
||||
|
||||
fun bindCache(cache: SVGACache?) {
|
||||
logD("bindCache() cache:$cache")
|
||||
logD("SVGAView bindCache() cache:$cache")
|
||||
this.svgaCache = cache
|
||||
}
|
||||
|
||||
fun setLogTag(tag: String) {
|
||||
logD("setLogTag() newTag:$tag oldTag:$logTag")
|
||||
logD("SVGAView setLogTag() newTag:$tag oldTag:$logTag")
|
||||
this.logTag = tag
|
||||
}
|
||||
|
||||
@@ -219,23 +309,25 @@ class SVGAView : SVGAImageView, ILog {
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
logD("onDetachedFromWindow()")
|
||||
logD("SVGAView onDetachedFromWindow()")
|
||||
super.onDetachedFromWindow()
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
logD("onAttachedToWindow()")
|
||||
logD("SVGAView onAttachedToWindow()")
|
||||
super.onAttachedToWindow()
|
||||
if (resumePlayAfterAttached) {
|
||||
if (drawable is SVGADrawable) {
|
||||
if (!isAnimating) {
|
||||
logD("onAttachedToWindow() startAnimation")
|
||||
logD("SVGAView onAttachedToWindow() startAnimation")
|
||||
startAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
interface SVGACache {
|
||||
fun get(key: String): SVGAVideoEntity?
|
||||
|
||||
|
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab;
|
||||
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
public abstract class SmartTabIndicationInterpolator {
|
||||
|
||||
public static final SmartTabIndicationInterpolator SMART = new SmartIndicationInterpolator();
|
||||
public static final SmartTabIndicationInterpolator LINEAR = new LinearIndicationInterpolator();
|
||||
|
||||
static final int ID_SMART = 0;
|
||||
static final int ID_LINEAR = 1;
|
||||
|
||||
public static SmartTabIndicationInterpolator of(int id) {
|
||||
switch (id) {
|
||||
case ID_SMART:
|
||||
return SMART;
|
||||
case ID_LINEAR:
|
||||
return LINEAR;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown id: " + id);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract float getLeftEdge(float offset);
|
||||
|
||||
public abstract float getRightEdge(float offset);
|
||||
|
||||
public float getThickness(float offset) {
|
||||
return 1f; //Always the same thickness by default
|
||||
}
|
||||
|
||||
public static class SmartIndicationInterpolator extends SmartTabIndicationInterpolator {
|
||||
|
||||
private static final float DEFAULT_INDICATOR_INTERPOLATION_FACTOR = 3.0f;
|
||||
|
||||
private final Interpolator leftEdgeInterpolator;
|
||||
private final Interpolator rightEdgeInterpolator;
|
||||
|
||||
public SmartIndicationInterpolator() {
|
||||
this(DEFAULT_INDICATOR_INTERPOLATION_FACTOR);
|
||||
}
|
||||
|
||||
public SmartIndicationInterpolator(float factor) {
|
||||
leftEdgeInterpolator = new AccelerateInterpolator(factor);
|
||||
rightEdgeInterpolator = new DecelerateInterpolator(factor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getLeftEdge(float offset) {
|
||||
return leftEdgeInterpolator.getInterpolation(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getRightEdge(float offset) {
|
||||
return rightEdgeInterpolator.getInterpolation(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getThickness(float offset) {
|
||||
return 1f / (1.0f - getLeftEdge(offset) + getRightEdge(offset));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class LinearIndicationInterpolator extends SmartTabIndicationInterpolator {
|
||||
|
||||
@Override
|
||||
public float getLeftEdge(float offset) {
|
||||
return offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getRightEdge(float offset) {
|
||||
return offset;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,644 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.chwl.library.R;
|
||||
|
||||
/**
|
||||
* To be used with ViewPager to provide a tab indicator component which give constant feedback as
|
||||
* to
|
||||
* the user's scroll progress.
|
||||
* <p>
|
||||
* To use the component, simply add it to your view hierarchy. Then in your
|
||||
* {@link android.app.Activity} or {@link androidx.fragment.app.Fragment} call
|
||||
* {@link #setViewPager(ViewPager)} providing it the ViewPager this
|
||||
* layout
|
||||
* is being used for.
|
||||
* <p>
|
||||
* The colors can be customized in two ways. The first and simplest is to provide an array of
|
||||
* colors
|
||||
* via {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)}. The
|
||||
* alternative is via the {@link TabColorizer} interface which provides you complete control over
|
||||
* which color is used for any individual position.
|
||||
* <p>
|
||||
* The views used as tabs can be customized by calling {@link #setCustomTabView(int, int)},
|
||||
* providing the layout ID of your custom layout.
|
||||
* <p>
|
||||
* Forked from Google Samples > SlidingTabsBasic >
|
||||
* <a href="https://developer.android.com/samples/SlidingTabsBasic/src/com.example.android.common/view/SlidingTabLayout.html">SlidingTabLayout</a>
|
||||
*/
|
||||
public class SmartTabLayout extends HorizontalScrollView {
|
||||
|
||||
private static final boolean DEFAULT_DISTRIBUTE_EVENLY = false;
|
||||
private static final int TITLE_OFFSET_DIPS = 24;
|
||||
private static final int TITLE_OFFSET_AUTO_CENTER = -1;
|
||||
private static final int TAB_VIEW_PADDING_DIPS = 16;
|
||||
private static final boolean TAB_VIEW_TEXT_ALL_CAPS = true;
|
||||
private static final int TAB_VIEW_TEXT_SIZE_SP = 12;
|
||||
private static final int TAB_VIEW_TEXT_COLOR = 0xFC000000;
|
||||
private static final int TAB_VIEW_TEXT_MIN_WIDTH = 0;
|
||||
private static final boolean TAB_CLICKABLE = true;
|
||||
private static final int NO_TEXT_STYLE = -1;
|
||||
|
||||
protected final SmartTabStrip tabStrip;
|
||||
private int titleOffset;
|
||||
private int tabViewBackgroundResId;
|
||||
private boolean tabViewTextAllCaps;
|
||||
private ColorStateList tabViewTextColors;
|
||||
private float tabViewTextSize;
|
||||
private int tabViewTextHorizontalPadding;
|
||||
private int tabViewTextMinWidth;
|
||||
private ViewPager viewPager;
|
||||
private ViewPager.OnPageChangeListener viewPagerPageChangeListener;
|
||||
private OnScrollChangeListener onScrollChangeListener;
|
||||
private TabProvider tabProvider;
|
||||
private InternalTabClickListener internalTabClickListener;
|
||||
private OnTabClickListener onTabClickListener;
|
||||
private boolean distributeEvenly;
|
||||
private int textAppearance;
|
||||
|
||||
public SmartTabLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SmartTabLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SmartTabLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
// Disable the Scroll Bar
|
||||
setHorizontalScrollBarEnabled(false);
|
||||
|
||||
final DisplayMetrics dm = getResources().getDisplayMetrics();
|
||||
final float density = dm.density;
|
||||
|
||||
int tabBackgroundResId = NO_ID;
|
||||
boolean textAllCaps = TAB_VIEW_TEXT_ALL_CAPS;
|
||||
ColorStateList textColors;
|
||||
float textSize = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP, dm);
|
||||
int textHorizontalPadding = (int) (TAB_VIEW_PADDING_DIPS * density);
|
||||
int textMinWidth = (int) (TAB_VIEW_TEXT_MIN_WIDTH * density);
|
||||
boolean distributeEvenly = DEFAULT_DISTRIBUTE_EVENLY;
|
||||
int customTabLayoutId = NO_ID;
|
||||
int customTabTextViewId = NO_ID;
|
||||
boolean clickable = TAB_CLICKABLE;
|
||||
int titleOffset = (int) (TITLE_OFFSET_DIPS * density);
|
||||
int textStyle = NO_TEXT_STYLE;
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(
|
||||
attrs, R.styleable.stl_SmartTabLayout, defStyle, 0);
|
||||
tabBackgroundResId = a.getResourceId(
|
||||
R.styleable.stl_SmartTabLayout_stl_defaultTabBackground, tabBackgroundResId);
|
||||
textAllCaps = a.getBoolean(
|
||||
R.styleable.stl_SmartTabLayout_stl_defaultTabTextAllCaps, textAllCaps);
|
||||
textColors = a.getColorStateList(
|
||||
R.styleable.stl_SmartTabLayout_stl_defaultTabTextColor);
|
||||
textSize = a.getDimension(
|
||||
R.styleable.stl_SmartTabLayout_stl_defaultTabTextSize, textSize);
|
||||
textHorizontalPadding = a.getDimensionPixelSize(
|
||||
R.styleable.stl_SmartTabLayout_stl_defaultTabTextHorizontalPadding, textHorizontalPadding);
|
||||
textMinWidth = a.getDimensionPixelSize(
|
||||
R.styleable.stl_SmartTabLayout_stl_defaultTabTextMinWidth, textMinWidth);
|
||||
customTabLayoutId = a.getResourceId(
|
||||
R.styleable.stl_SmartTabLayout_stl_customTabTextLayoutId, customTabLayoutId);
|
||||
customTabTextViewId = a.getResourceId(
|
||||
R.styleable.stl_SmartTabLayout_stl_customTabTextViewId, customTabTextViewId);
|
||||
distributeEvenly = a.getBoolean(
|
||||
R.styleable.stl_SmartTabLayout_stl_distributeEvenly, distributeEvenly);
|
||||
clickable = a.getBoolean(
|
||||
R.styleable.stl_SmartTabLayout_stl_clickable, clickable);
|
||||
titleOffset = a.getLayoutDimension(
|
||||
R.styleable.stl_SmartTabLayout_stl_titleOffset, titleOffset);
|
||||
textStyle = a.getResourceId(R.styleable.stl_SmartTabLayout_stl_tabTextStyle, textStyle);
|
||||
a.recycle();
|
||||
|
||||
this.titleOffset = titleOffset;
|
||||
this.tabViewBackgroundResId = tabBackgroundResId;
|
||||
this.tabViewTextAllCaps = textAllCaps;
|
||||
this.tabViewTextColors = (textColors != null)
|
||||
? textColors
|
||||
: ColorStateList.valueOf(TAB_VIEW_TEXT_COLOR);
|
||||
this.tabViewTextSize = textSize;
|
||||
this.tabViewTextHorizontalPadding = textHorizontalPadding;
|
||||
this.tabViewTextMinWidth = textMinWidth;
|
||||
this.internalTabClickListener = clickable ? new InternalTabClickListener() : null;
|
||||
this.distributeEvenly = distributeEvenly;
|
||||
this.textAppearance = textStyle;
|
||||
|
||||
if (customTabLayoutId != NO_ID) {
|
||||
setCustomTabView(customTabLayoutId, customTabTextViewId);
|
||||
}
|
||||
|
||||
this.tabStrip = new SmartTabStrip(context, attrs);
|
||||
|
||||
if (distributeEvenly && tabStrip.isIndicatorAlwaysInCenter()) {
|
||||
throw new UnsupportedOperationException(
|
||||
"'distributeEvenly' and 'indicatorAlwaysInCenter' both use does not support");
|
||||
}
|
||||
|
||||
// Make sure that the Tab Strips fills this View
|
||||
setFillViewport(!tabStrip.isIndicatorAlwaysInCenter());
|
||||
|
||||
addView(tabStrip, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
|
||||
super.onScrollChanged(l, t, oldl, oldt);
|
||||
if (onScrollChangeListener != null) {
|
||||
onScrollChangeListener.onScrollChanged(l, oldl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
if (tabStrip.isIndicatorAlwaysInCenter() && tabStrip.getChildCount() > 0) {
|
||||
View firstTab = tabStrip.getChildAt(0);
|
||||
View lastTab = tabStrip.getChildAt(tabStrip.getChildCount() - 1);
|
||||
int start = (w - Utils.getMeasuredWidth(firstTab)) / 2 - Utils.getMarginStart(firstTab);
|
||||
int end = (w - Utils.getMeasuredWidth(lastTab)) / 2 - Utils.getMarginEnd(lastTab);
|
||||
tabStrip.setMinimumWidth(tabStrip.getMeasuredWidth());
|
||||
ViewCompat.setPaddingRelative(this, start, getPaddingTop(), end, getPaddingBottom());
|
||||
setClipToPadding(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
// Ensure first scroll
|
||||
if (changed && viewPager != null) {
|
||||
scrollToTab(viewPager.getCurrentItem(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the Indicator scrolling feedback.
|
||||
*
|
||||
* @param interpolator {@link com.ogaclejapan.smarttablayout.SmartTabIndicationInterpolator}
|
||||
*/
|
||||
public void setIndicationInterpolator(SmartTabIndicationInterpolator interpolator) {
|
||||
tabStrip.setIndicationInterpolator(interpolator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom {@link TabColorizer} to be used.
|
||||
*
|
||||
* If you only require simple customisation then you can use
|
||||
* {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve
|
||||
* similar effects.
|
||||
*/
|
||||
public void setCustomTabColorizer(TabColorizer tabColorizer) {
|
||||
tabStrip.setCustomTabColorizer(tabColorizer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color used for styling the tab text. This will need to be called prior to calling
|
||||
* {@link #setViewPager(ViewPager)} otherwise it will not get set
|
||||
*
|
||||
* @param color to use for tab text
|
||||
*/
|
||||
public void setDefaultTabTextColor(int color) {
|
||||
tabViewTextColors = ColorStateList.valueOf(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the colors used for styling the tab text. This will need to be called prior to calling
|
||||
* {@link #setViewPager(ViewPager)} otherwise it will not get set
|
||||
*
|
||||
* @param colors ColorStateList to use for tab text
|
||||
*/
|
||||
public void setDefaultTabTextColor(ColorStateList colors) {
|
||||
tabViewTextColors = colors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the same weight for tab
|
||||
*/
|
||||
public void setDistributeEvenly(boolean distributeEvenly) {
|
||||
this.distributeEvenly = distributeEvenly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the colors to be used for indicating the selected tab. These colors are treated as a
|
||||
* circular array. Providing one color will mean that all tabs are indicated with the same color.
|
||||
*/
|
||||
public void setSelectedIndicatorColors(int... colors) {
|
||||
tabStrip.setSelectedIndicatorColors(colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the colors to be used for tab dividers. These colors are treated as a circular array.
|
||||
* Providing one color will mean that all tabs are indicated with the same color.
|
||||
*/
|
||||
public void setDividerColors(int... colors) {
|
||||
tabStrip.setDividerColors(colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ViewPager.OnPageChangeListener}. When using {@link SmartTabLayout} you are
|
||||
* required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so
|
||||
* that the layout can update it's scroll position correctly.
|
||||
*
|
||||
* @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener)
|
||||
*/
|
||||
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
|
||||
viewPagerPageChangeListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set {@link OnScrollChangeListener} for obtaining values of scrolling.
|
||||
*
|
||||
* @param listener the {@link OnScrollChangeListener} to set
|
||||
*/
|
||||
public void setOnScrollChangeListener(OnScrollChangeListener listener) {
|
||||
onScrollChangeListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set {@link OnTabClickListener} for obtaining click event.
|
||||
*
|
||||
* @param listener the {@link OnTabClickListener} to set
|
||||
*/
|
||||
public void setOnTabClickListener(OnTabClickListener listener) {
|
||||
onTabClickListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom layout to be inflated for the tab views.
|
||||
*
|
||||
* @param layoutResId Layout id to be inflated
|
||||
* @param textViewId id of the {@link TextView} in the inflated view
|
||||
*/
|
||||
public void setCustomTabView(int layoutResId, int textViewId) {
|
||||
tabProvider = new SimpleTabProvider(getContext(), layoutResId, textViewId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom layout to be inflated for the tab views.
|
||||
*
|
||||
* @param provider {@link TabProvider}
|
||||
*/
|
||||
public void setCustomTabView(TabProvider provider) {
|
||||
tabProvider = provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the associated view pager. Note that the assumption here is that the pager content
|
||||
* (number of tabs and tab titles) does not change after this call has been made.
|
||||
*/
|
||||
public void setViewPager(ViewPager viewPager) {
|
||||
tabStrip.removeAllViews();
|
||||
|
||||
this.viewPager = viewPager;
|
||||
if (viewPager != null && viewPager.getAdapter() != null) {
|
||||
viewPager.addOnPageChangeListener(new InternalViewPagerListener());
|
||||
populateTabStrip();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the view at the specified position in the tabs.
|
||||
*
|
||||
* @param position the position at which to get the view from
|
||||
* @return the view at the specified position or null if the position does not exist within the
|
||||
* tabs
|
||||
*/
|
||||
public View getTabAt(int position) {
|
||||
return tabStrip.getChildAt(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default view to be used for tabs. This is called if a custom tab view is not set via
|
||||
* {@link #setCustomTabView(int, int)}.
|
||||
*/
|
||||
protected TextView createDefaultTabView(CharSequence title) {
|
||||
TextView textView = new TextView(getContext());
|
||||
textView.setGravity(Gravity.CENTER);
|
||||
textView.setText(title);
|
||||
if (textAppearance != NO_TEXT_STYLE) {
|
||||
textView.setTextAppearance(getContext(), textAppearance);
|
||||
} else {
|
||||
textView.setTextColor(tabViewTextColors);
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabViewTextSize);
|
||||
textView.setTypeface(Typeface.DEFAULT_BOLD);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
// If we're running on ICS or newer, enable all-caps to match the Action Bar tab style
|
||||
textView.setAllCaps(tabViewTextAllCaps);
|
||||
}
|
||||
|
||||
if (tabViewTextMinWidth > 0) {
|
||||
textView.setMinWidth(tabViewTextMinWidth);
|
||||
}
|
||||
}
|
||||
if (tabViewBackgroundResId != NO_ID) {
|
||||
textView.setBackgroundResource(tabViewBackgroundResId);
|
||||
} else {
|
||||
// If we're running on Honeycomb or newer, then we can use the Theme's
|
||||
// selectableItemBackground to ensure that the View has a pressed state
|
||||
TypedValue outValue = new TypedValue();
|
||||
getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
|
||||
outValue, true);
|
||||
textView.setBackgroundResource(outValue.resourceId);
|
||||
}
|
||||
textView.setPadding(
|
||||
tabViewTextHorizontalPadding, 0,
|
||||
tabViewTextHorizontalPadding, 0);
|
||||
textView.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
|
||||
|
||||
return textView;
|
||||
}
|
||||
|
||||
private void populateTabStrip() {
|
||||
final PagerAdapter adapter = viewPager.getAdapter();
|
||||
|
||||
for (int i = 0; i < adapter.getCount(); i++) {
|
||||
|
||||
final View tabView = (tabProvider == null)
|
||||
? createDefaultTabView(adapter.getPageTitle(i))
|
||||
: tabProvider.createTabView(tabStrip, i, adapter);
|
||||
|
||||
if (tabView == null) {
|
||||
throw new IllegalStateException("tabView is null.");
|
||||
}
|
||||
|
||||
if (distributeEvenly) {
|
||||
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams();
|
||||
lp.width = 0;
|
||||
lp.weight = 1;
|
||||
}
|
||||
|
||||
if (internalTabClickListener != null) {
|
||||
tabView.setOnClickListener(internalTabClickListener);
|
||||
}
|
||||
|
||||
tabStrip.addView(tabView);
|
||||
|
||||
if (i == viewPager.getCurrentItem()) {
|
||||
tabView.setSelected(true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void scrollToTab(int tabIndex, float positionOffset) {
|
||||
final int tabStripChildCount = tabStrip.getChildCount();
|
||||
if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean isLayoutRtl = Utils.isLayoutRtl(this);
|
||||
View selectedTab = tabStrip.getChildAt(tabIndex);
|
||||
int widthPlusMargin = Utils.getWidth(selectedTab) + Utils.getMarginHorizontally(selectedTab);
|
||||
int extraOffset = (int) (positionOffset * widthPlusMargin);
|
||||
|
||||
if (tabStrip.isIndicatorAlwaysInCenter()) {
|
||||
|
||||
if (0f < positionOffset && positionOffset < 1f) {
|
||||
View nextTab = tabStrip.getChildAt(tabIndex + 1);
|
||||
int selectHalfWidth = Utils.getWidth(selectedTab) / 2 + Utils.getMarginEnd(selectedTab);
|
||||
int nextHalfWidth = Utils.getWidth(nextTab) / 2 + Utils.getMarginStart(nextTab);
|
||||
extraOffset = Math.round(positionOffset * (selectHalfWidth + nextHalfWidth));
|
||||
}
|
||||
|
||||
View firstTab = tabStrip.getChildAt(0);
|
||||
int x;
|
||||
if (isLayoutRtl) {
|
||||
int first = Utils.getWidth(firstTab) + Utils.getMarginEnd(firstTab);
|
||||
int selected = Utils.getWidth(selectedTab) + Utils.getMarginEnd(selectedTab);
|
||||
x = Utils.getEnd(selectedTab) - Utils.getMarginEnd(selectedTab) - extraOffset;
|
||||
x -= (first - selected) / 2;
|
||||
} else {
|
||||
int first = Utils.getWidth(firstTab) + Utils.getMarginStart(firstTab);
|
||||
int selected = Utils.getWidth(selectedTab) + Utils.getMarginStart(selectedTab);
|
||||
x = Utils.getStart(selectedTab) - Utils.getMarginStart(selectedTab) + extraOffset;
|
||||
x -= (first - selected) / 2;
|
||||
}
|
||||
|
||||
scrollTo(x, 0);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
int x;
|
||||
if (titleOffset == TITLE_OFFSET_AUTO_CENTER) {
|
||||
|
||||
if (0f < positionOffset && positionOffset < 1f) {
|
||||
View nextTab = tabStrip.getChildAt(tabIndex + 1);
|
||||
int selectHalfWidth = Utils.getWidth(selectedTab) / 2 + Utils.getMarginEnd(selectedTab);
|
||||
int nextHalfWidth = Utils.getWidth(nextTab) / 2 + Utils.getMarginStart(nextTab);
|
||||
extraOffset = Math.round(positionOffset * (selectHalfWidth + nextHalfWidth));
|
||||
}
|
||||
|
||||
if (isLayoutRtl) {
|
||||
x = -Utils.getWidthWithMargin(selectedTab) / 2 + getWidth() / 2;
|
||||
x -= Utils.getPaddingStart(this);
|
||||
} else {
|
||||
x = Utils.getWidthWithMargin(selectedTab) / 2 - getWidth() / 2;
|
||||
x += Utils.getPaddingStart(this);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (isLayoutRtl) {
|
||||
x = (tabIndex > 0 || positionOffset > 0) ? titleOffset : 0;
|
||||
} else {
|
||||
x = (tabIndex > 0 || positionOffset > 0) ? -titleOffset : 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int start = Utils.getStart(selectedTab);
|
||||
int startMargin = Utils.getMarginStart(selectedTab);
|
||||
if (isLayoutRtl) {
|
||||
x += start + startMargin - extraOffset - getWidth() + Utils.getPaddingHorizontally(this);
|
||||
} else {
|
||||
x += start - startMargin + extraOffset;
|
||||
}
|
||||
|
||||
scrollTo(x, 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the scroll position of a view changes.
|
||||
*/
|
||||
public interface OnScrollChangeListener {
|
||||
|
||||
/**
|
||||
* Called when the scroll position of a view changes.
|
||||
*
|
||||
* @param scrollX Current horizontal scroll origin.
|
||||
* @param oldScrollX Previous horizontal scroll origin.
|
||||
*/
|
||||
void onScrollChanged(int scrollX, int oldScrollX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when a tab is clicked.
|
||||
*/
|
||||
public interface OnTabClickListener {
|
||||
|
||||
/**
|
||||
* Called when a tab is clicked.
|
||||
*
|
||||
* @param position tab's position
|
||||
*/
|
||||
void onTabClicked(int position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the custom tabs in the tab layout. Set with
|
||||
* {@link #setCustomTabView(com.ogaclejapan.smarttablayout.SmartTabLayout.TabProvider)}
|
||||
*/
|
||||
public interface TabProvider {
|
||||
|
||||
/**
|
||||
* @return Return the View of {@code position} for the Tabs
|
||||
*/
|
||||
View createTabView(ViewGroup container, int position, PagerAdapter adapter);
|
||||
|
||||
}
|
||||
|
||||
private static class SimpleTabProvider implements TabProvider {
|
||||
|
||||
private final LayoutInflater inflater;
|
||||
private final int tabViewLayoutId;
|
||||
private final int tabViewTextViewId;
|
||||
|
||||
private SimpleTabProvider(Context context, int layoutResId, int textViewId) {
|
||||
inflater = LayoutInflater.from(context);
|
||||
tabViewLayoutId = layoutResId;
|
||||
tabViewTextViewId = textViewId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createTabView(ViewGroup container, int position, PagerAdapter adapter) {
|
||||
View tabView = null;
|
||||
TextView tabTitleView = null;
|
||||
|
||||
if (tabViewLayoutId != NO_ID) {
|
||||
tabView = inflater.inflate(tabViewLayoutId, container, false);
|
||||
}
|
||||
|
||||
if (tabViewTextViewId != NO_ID && tabView != null) {
|
||||
tabTitleView = (TextView) tabView.findViewById(tabViewTextViewId);
|
||||
}
|
||||
|
||||
if (tabTitleView == null && TextView.class.isInstance(tabView)) {
|
||||
tabTitleView = (TextView) tabView;
|
||||
}
|
||||
|
||||
if (tabTitleView != null) {
|
||||
tabTitleView.setText(adapter.getPageTitle(position));
|
||||
}
|
||||
|
||||
return tabView;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {
|
||||
|
||||
private int scrollState;
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
int tabStripChildCount = tabStrip.getChildCount();
|
||||
if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tabStrip.onViewPagerPageChanged(position, positionOffset);
|
||||
|
||||
scrollToTab(position, positionOffset);
|
||||
|
||||
if (viewPagerPageChangeListener != null) {
|
||||
viewPagerPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
scrollState = state;
|
||||
|
||||
if (viewPagerPageChangeListener != null) {
|
||||
viewPagerPageChangeListener.onPageScrollStateChanged(state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
if (scrollState == ViewPager.SCROLL_STATE_IDLE) {
|
||||
tabStrip.onViewPagerPageChanged(position, 0f);
|
||||
scrollToTab(position, 0);
|
||||
}
|
||||
|
||||
for (int i = 0, size = tabStrip.getChildCount(); i < size; i++) {
|
||||
tabStrip.getChildAt(i).setSelected(position == i);
|
||||
}
|
||||
|
||||
if (viewPagerPageChangeListener != null) {
|
||||
viewPagerPageChangeListener.onPageSelected(position);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class InternalTabClickListener implements OnClickListener {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
for (int i = 0; i < tabStrip.getChildCount(); i++) {
|
||||
if (v == tabStrip.getChildAt(i)) {
|
||||
if (onTabClickListener != null) {
|
||||
onTabClickListener.onTabClicked(i);
|
||||
}
|
||||
viewPager.setCurrentItem(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,705 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.chwl.library.R;
|
||||
|
||||
/**
|
||||
* To be used with ViewPager2 to provide a tab indicator component which give constant feedback as
|
||||
* to
|
||||
* the user's scroll progress.
|
||||
* <p>
|
||||
* To use the component, simply add it to your view hierarchy. Then in your
|
||||
* {@link android.app.Activity} or {@link androidx.fragment.app.Fragment} call
|
||||
* {@link #setViewPager(ViewPager2, RecyclerView.Adapter, TabTitleProvider)} providing it the ViewPager this
|
||||
* layout
|
||||
* is being used for.
|
||||
* <p>
|
||||
* The colors can be customized in two ways. The first and simplest is to provide an array of
|
||||
* colors
|
||||
* via {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)}. The
|
||||
* alternative is via the {@link TabColorizer} interface which provides you complete control over
|
||||
* which color is used for any individual position.
|
||||
* <p>
|
||||
* The views used as tabs can be customized by calling {@link #setCustomTabView(int, int)},
|
||||
* providing the layout ID of your custom layout.
|
||||
* <p>
|
||||
* Forked from Google Samples > SlidingTabsBasic >
|
||||
* <a href="https://developer.android.com/samples/SlidingTabsBasic/src/com.example.android.common/view/SlidingTabLayout.html">SlidingTabLayout</a>
|
||||
*/
|
||||
public class SmartTabLayout2 extends HorizontalScrollView {
|
||||
|
||||
private static final boolean DEFAULT_DISTRIBUTE_EVENLY = false;
|
||||
private static final int TITLE_OFFSET_DIPS = 24;
|
||||
private static final int TITLE_OFFSET_AUTO_CENTER = -1;
|
||||
private static final int TAB_VIEW_PADDING_DIPS = 16;
|
||||
private static final boolean TAB_VIEW_TEXT_ALL_CAPS = true;
|
||||
private static final int TAB_VIEW_TEXT_SIZE_SP = 12;
|
||||
private static final int TAB_VIEW_TEXT_COLOR = 0xFC000000;
|
||||
private static final int TAB_VIEW_TEXT_MIN_WIDTH = 0;
|
||||
private static final boolean TAB_CLICKABLE = true;
|
||||
private static final int NO_TEXT_STYLE = -1;
|
||||
|
||||
protected final SmartTabStrip tabStrip;
|
||||
private int titleOffset;
|
||||
private int tabViewBackgroundResId;
|
||||
private boolean tabViewTextAllCaps;
|
||||
private ColorStateList tabViewTextColors;
|
||||
private float tabViewTextSize;
|
||||
private int tabViewTextHorizontalPadding;
|
||||
private int tabViewTextMinWidth;
|
||||
private ViewPager2 viewPager;
|
||||
private ViewPager2.OnPageChangeCallback viewPagerPageChangeCallback;
|
||||
@Nullable
|
||||
private TabTitleProvider tabTitleProvider;
|
||||
private OnScrollChangeListener onScrollChangeListener;
|
||||
private TabProvider tabProvider;
|
||||
private InternalTabClickListener internalTabClickListener;
|
||||
private InternalTabLongClickListener internalTabLongClickListener;
|
||||
private OnTabClickListener onTabClickListener;
|
||||
private OnTabLongClickListener onTabLongClickListener;
|
||||
private boolean distributeEvenly;
|
||||
private int textAppearance;
|
||||
|
||||
private int childCountCache = 0;
|
||||
|
||||
public SmartTabLayout2(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SmartTabLayout2(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SmartTabLayout2(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
// Disable the Scroll Bar
|
||||
setHorizontalScrollBarEnabled(false);
|
||||
|
||||
final DisplayMetrics dm = getResources().getDisplayMetrics();
|
||||
final float density = dm.density;
|
||||
|
||||
int tabBackgroundResId = NO_ID;
|
||||
boolean textAllCaps = TAB_VIEW_TEXT_ALL_CAPS;
|
||||
ColorStateList textColors;
|
||||
float textSize = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP, dm);
|
||||
int textHorizontalPadding = (int) (TAB_VIEW_PADDING_DIPS * density);
|
||||
int textMinWidth = (int) (TAB_VIEW_TEXT_MIN_WIDTH * density);
|
||||
boolean distributeEvenly = DEFAULT_DISTRIBUTE_EVENLY;
|
||||
int customTabLayoutId = NO_ID;
|
||||
int customTabTextViewId = NO_ID;
|
||||
boolean clickable = TAB_CLICKABLE;
|
||||
int titleOffset = (int) (TITLE_OFFSET_DIPS * density);
|
||||
int textStyle = NO_TEXT_STYLE;
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(
|
||||
attrs, R.styleable.stl_SmartTabLayout, defStyle, 0);
|
||||
tabBackgroundResId = a.getResourceId(
|
||||
R.styleable.stl_SmartTabLayout_stl_defaultTabBackground, tabBackgroundResId);
|
||||
textAllCaps = a.getBoolean(
|
||||
R.styleable.stl_SmartTabLayout_stl_defaultTabTextAllCaps, textAllCaps);
|
||||
textColors = a.getColorStateList(
|
||||
R.styleable.stl_SmartTabLayout_stl_defaultTabTextColor);
|
||||
textSize = a.getDimension(
|
||||
R.styleable.stl_SmartTabLayout_stl_defaultTabTextSize, textSize);
|
||||
textHorizontalPadding = a.getDimensionPixelSize(
|
||||
R.styleable.stl_SmartTabLayout_stl_defaultTabTextHorizontalPadding, textHorizontalPadding);
|
||||
textMinWidth = a.getDimensionPixelSize(
|
||||
R.styleable.stl_SmartTabLayout_stl_defaultTabTextMinWidth, textMinWidth);
|
||||
customTabLayoutId = a.getResourceId(
|
||||
R.styleable.stl_SmartTabLayout_stl_customTabTextLayoutId, customTabLayoutId);
|
||||
customTabTextViewId = a.getResourceId(
|
||||
R.styleable.stl_SmartTabLayout_stl_customTabTextViewId, customTabTextViewId);
|
||||
distributeEvenly = a.getBoolean(
|
||||
R.styleable.stl_SmartTabLayout_stl_distributeEvenly, distributeEvenly);
|
||||
clickable = a.getBoolean(
|
||||
R.styleable.stl_SmartTabLayout_stl_clickable, clickable);
|
||||
titleOffset = a.getLayoutDimension(
|
||||
R.styleable.stl_SmartTabLayout_stl_titleOffset, titleOffset);
|
||||
textStyle = a.getResourceId(R.styleable.stl_SmartTabLayout_stl_tabTextStyle, textStyle);
|
||||
a.recycle();
|
||||
|
||||
this.titleOffset = titleOffset;
|
||||
this.tabViewBackgroundResId = tabBackgroundResId;
|
||||
this.tabViewTextAllCaps = textAllCaps;
|
||||
this.tabViewTextColors = (textColors != null)
|
||||
? textColors
|
||||
: ColorStateList.valueOf(TAB_VIEW_TEXT_COLOR);
|
||||
this.tabViewTextSize = textSize;
|
||||
this.tabViewTextHorizontalPadding = textHorizontalPadding;
|
||||
this.tabViewTextMinWidth = textMinWidth;
|
||||
this.internalTabClickListener = clickable ? new InternalTabClickListener() : null;
|
||||
this.internalTabLongClickListener = clickable ? new InternalTabLongClickListener() : null;
|
||||
this.distributeEvenly = distributeEvenly;
|
||||
this.textAppearance = textStyle;
|
||||
|
||||
if (customTabLayoutId != NO_ID) {
|
||||
setCustomTabView(customTabLayoutId, customTabTextViewId);
|
||||
}
|
||||
|
||||
this.tabStrip = new SmartTabStrip(context, attrs);
|
||||
|
||||
if (distributeEvenly && tabStrip.isIndicatorAlwaysInCenter()) {
|
||||
throw new UnsupportedOperationException(
|
||||
"'distributeEvenly' and 'indicatorAlwaysInCenter' both use does not support");
|
||||
}
|
||||
|
||||
// Make sure that the Tab Strips fills this View
|
||||
setFillViewport(!tabStrip.isIndicatorAlwaysInCenter());
|
||||
|
||||
addView(tabStrip, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
|
||||
super.onScrollChanged(l, t, oldl, oldt);
|
||||
if (onScrollChangeListener != null) {
|
||||
onScrollChangeListener.onScrollChanged(l, oldl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
adjustForIndicatorAlwaysInCenter(w, h);
|
||||
}
|
||||
|
||||
private void adjustForIndicatorAlwaysInCenter(int w, int h) {
|
||||
if (tabStrip.isIndicatorAlwaysInCenter() && tabStrip.getChildCount() > 0) {
|
||||
View firstTab = tabStrip.getChildAt(0);
|
||||
View lastTab = tabStrip.getChildAt(tabStrip.getChildCount() - 1);
|
||||
int start = (w - Utils.getMeasuredWidth(firstTab)) / 2 - Utils.getMarginStart(firstTab);
|
||||
int end = (w - Utils.getMeasuredWidth(lastTab)) / 2 - Utils.getMarginEnd(lastTab);
|
||||
tabStrip.setMinimumWidth(tabStrip.getMeasuredWidth());
|
||||
ViewCompat.setPaddingRelative(this, start, getPaddingTop(), end, getPaddingBottom());
|
||||
setClipToPadding(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
// Ensure first scroll
|
||||
if (changed && viewPager != null) {
|
||||
scrollToTab(viewPager.getCurrentItem(), 0);
|
||||
}
|
||||
if (childCountCache != tabStrip.getChildCount()) {
|
||||
adjustForIndicatorAlwaysInCenter(getMeasuredWidth(), getMeasuredHeight());
|
||||
}
|
||||
childCountCache = tabStrip.getChildCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the Indicator scrolling feedback.
|
||||
*
|
||||
* @param interpolator {@link SmartTabIndicationInterpolator}
|
||||
*/
|
||||
public void setIndicationInterpolator(SmartTabIndicationInterpolator interpolator) {
|
||||
tabStrip.setIndicationInterpolator(interpolator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom {@link TabColorizer} to be used.
|
||||
*
|
||||
* If you only require simple customisation then you can use
|
||||
* {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve
|
||||
* similar effects.
|
||||
*/
|
||||
public void setCustomTabColorizer(TabColorizer tabColorizer) {
|
||||
tabStrip.setCustomTabColorizer(tabColorizer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color used for styling the tab text. This will need to be called prior to calling
|
||||
* {@link #setViewPager(ViewPager2, RecyclerView.Adapter, TabTitleProvider)} otherwise it will not get set
|
||||
*
|
||||
* @param color to use for tab text
|
||||
*/
|
||||
public void setDefaultTabTextColor(int color) {
|
||||
tabViewTextColors = ColorStateList.valueOf(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the colors used for styling the tab text. This will need to be called prior to calling
|
||||
* {@link #setViewPager(ViewPager2, RecyclerView.Adapter, TabTitleProvider)} otherwise it will not get set
|
||||
*
|
||||
* @param colors ColorStateList to use for tab text
|
||||
*/
|
||||
public void setDefaultTabTextColor(ColorStateList colors) {
|
||||
tabViewTextColors = colors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the same weight for tab
|
||||
*/
|
||||
public void setDistributeEvenly(boolean distributeEvenly) {
|
||||
this.distributeEvenly = distributeEvenly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the colors to be used for indicating the selected tab. These colors are treated as a
|
||||
* circular array. Providing one color will mean that all tabs are indicated with the same color.
|
||||
*/
|
||||
public void setSelectedIndicatorColors(int... colors) {
|
||||
tabStrip.setSelectedIndicatorColors(colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the colors to be used for tab dividers. These colors are treated as a circular array.
|
||||
* Providing one color will mean that all tabs are indicated with the same color.
|
||||
*/
|
||||
public void setDividerColors(int... colors) {
|
||||
tabStrip.setDividerColors(colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ViewPager2.OnPageChangeCallback}. When using {@link SmartTabLayout2} you are
|
||||
* required to set any {@link ViewPager2.OnPageChangeCallback} through this method. This is so
|
||||
* that the layout can update it's scroll position correctly.
|
||||
*
|
||||
* @see ViewPager2#registerOnPageChangeCallback(ViewPager2.OnPageChangeCallback)
|
||||
*/
|
||||
public void setOnPageChangeCallback(ViewPager2.OnPageChangeCallback listener) {
|
||||
viewPagerPageChangeCallback = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set {@link OnScrollChangeListener} for obtaining values of scrolling.
|
||||
*
|
||||
* @param listener the {@link OnScrollChangeListener} to set
|
||||
*/
|
||||
public void setOnScrollChangeListener(OnScrollChangeListener listener) {
|
||||
onScrollChangeListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set {@link OnTabClickListener} for obtaining click event.
|
||||
*
|
||||
* @param listener the {@link OnTabClickListener} to set
|
||||
*/
|
||||
public void setOnTabClickListener(OnTabClickListener listener) {
|
||||
onTabClickListener = listener;
|
||||
}
|
||||
|
||||
public void setOnTabLongClickListener(OnTabLongClickListener listener) {
|
||||
onTabLongClickListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom layout to be inflated for the tab views.
|
||||
*
|
||||
* @param layoutResId Layout id to be inflated
|
||||
* @param textViewId id of the {@link TextView} in the inflated view
|
||||
*/
|
||||
public void setCustomTabView(int layoutResId, int textViewId) {
|
||||
tabProvider = new SimpleTabProvider(getContext(), layoutResId, textViewId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom layout to be inflated for the tab views.
|
||||
*
|
||||
* @param provider {@link TabProvider}
|
||||
*/
|
||||
public void setCustomTabView(TabProvider provider) {
|
||||
tabProvider = provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the associated view pager. Note that the assumption here is that the pager content
|
||||
* (number of tabs and tab titles) does not change after this call has been made.
|
||||
*/
|
||||
public void setViewPager(@NonNull ViewPager2 viewPager, @NonNull RecyclerView.Adapter adapter,
|
||||
@Nullable TabTitleProvider titleProvider) {
|
||||
tabStrip.removeAllViews();
|
||||
|
||||
this.viewPager = viewPager;
|
||||
if (this.viewPager.getAdapter() != adapter){
|
||||
this.viewPager.setAdapter(adapter);
|
||||
}
|
||||
this.tabTitleProvider = titleProvider;
|
||||
if (viewPager != null && viewPager.getAdapter() != null) {
|
||||
viewPager.registerOnPageChangeCallback(new InternalViewPagerListener());
|
||||
populateTabStrip();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the view at the specified position in the tabs.
|
||||
*
|
||||
* @param position the position at which to get the view from
|
||||
* @return the view at the specified position or null if the position does not exist within the
|
||||
* tabs
|
||||
*/
|
||||
public View getTabAt(int position) {
|
||||
return tabStrip.getChildAt(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default view to be used for tabs. This is called if a custom tab view is not set via
|
||||
* {@link #setCustomTabView(int, int)}.
|
||||
*/
|
||||
protected TextView createDefaultTabView(CharSequence title) {
|
||||
TextView textView = new TextView(getContext());
|
||||
textView.setGravity(Gravity.CENTER);
|
||||
textView.setText(title);
|
||||
if (textAppearance != NO_TEXT_STYLE) {
|
||||
textView.setTextAppearance(getContext(), textAppearance);
|
||||
} else {
|
||||
textView.setTextColor(tabViewTextColors);
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabViewTextSize);
|
||||
textView.setTypeface(Typeface.DEFAULT_BOLD);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
// If we're running on ICS or newer, enable all-caps to match the Action Bar tab style
|
||||
textView.setAllCaps(tabViewTextAllCaps);
|
||||
}
|
||||
|
||||
if (tabViewTextMinWidth > 0) {
|
||||
textView.setMinWidth(tabViewTextMinWidth);
|
||||
}
|
||||
}
|
||||
if (tabViewBackgroundResId != NO_ID) {
|
||||
textView.setBackgroundResource(tabViewBackgroundResId);
|
||||
} else {
|
||||
// If we're running on Honeycomb or newer, then we can use the Theme's
|
||||
// selectableItemBackground to ensure that the View has a pressed state
|
||||
TypedValue outValue = new TypedValue();
|
||||
getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
|
||||
outValue, true);
|
||||
textView.setBackgroundResource(outValue.resourceId);
|
||||
}
|
||||
textView.setPadding(
|
||||
tabViewTextHorizontalPadding, 0,
|
||||
tabViewTextHorizontalPadding, 0);
|
||||
textView.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
|
||||
|
||||
return textView;
|
||||
}
|
||||
|
||||
private void populateTabStrip() {
|
||||
final RecyclerView.Adapter adapter = viewPager.getAdapter();
|
||||
|
||||
for (int i = 0; i < adapter.getItemCount(); i++) {
|
||||
|
||||
CharSequence pageTitle = null;
|
||||
if (tabTitleProvider != null) {
|
||||
pageTitle = tabTitleProvider.getPageTitle(i);
|
||||
}
|
||||
|
||||
final View tabView = (tabProvider == null)
|
||||
? createDefaultTabView(pageTitle)
|
||||
: tabProvider.createTabView(tabStrip, i, pageTitle);
|
||||
|
||||
if (tabView == null) {
|
||||
throw new IllegalStateException("tabView is null.");
|
||||
}
|
||||
|
||||
if (distributeEvenly) {
|
||||
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams();
|
||||
lp.width = 0;
|
||||
lp.weight = 1;
|
||||
}
|
||||
|
||||
if (internalTabClickListener != null) {
|
||||
tabView.setOnClickListener(internalTabClickListener);
|
||||
}
|
||||
if (internalTabLongClickListener != null) {
|
||||
tabView.setOnLongClickListener(internalTabLongClickListener);
|
||||
}
|
||||
|
||||
tabStrip.addView(tabView);
|
||||
|
||||
if (i == viewPager.getCurrentItem()) {
|
||||
tabView.setSelected(true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void scrollToTab(int tabIndex, float positionOffset) {
|
||||
final int tabStripChildCount = tabStrip.getChildCount();
|
||||
if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean isLayoutRtl = Utils.isLayoutRtl(this);
|
||||
View selectedTab = tabStrip.getChildAt(tabIndex);
|
||||
int widthPlusMargin = Utils.getWidth(selectedTab) + Utils.getMarginHorizontally(selectedTab);
|
||||
int extraOffset = (int) (positionOffset * widthPlusMargin);
|
||||
|
||||
if (tabStrip.isIndicatorAlwaysInCenter()) {
|
||||
|
||||
if (0f < positionOffset && positionOffset < 1f) {
|
||||
View nextTab = tabStrip.getChildAt(tabIndex + 1);
|
||||
int selectHalfWidth = Utils.getWidth(selectedTab) / 2 + Utils.getMarginEnd(selectedTab);
|
||||
int nextHalfWidth = Utils.getWidth(nextTab) / 2 + Utils.getMarginStart(nextTab);
|
||||
extraOffset = Math.round(positionOffset * (selectHalfWidth + nextHalfWidth));
|
||||
}
|
||||
|
||||
View firstTab = tabStrip.getChildAt(0);
|
||||
int x;
|
||||
if (isLayoutRtl) {
|
||||
int first = Utils.getWidth(firstTab) + Utils.getMarginEnd(firstTab);
|
||||
int selected = Utils.getWidth(selectedTab) + Utils.getMarginEnd(selectedTab);
|
||||
x = Utils.getEnd(selectedTab) - Utils.getMarginEnd(selectedTab) - extraOffset;
|
||||
x -= (first - selected) / 2;
|
||||
} else {
|
||||
int first = Utils.getWidth(firstTab) + Utils.getMarginStart(firstTab);
|
||||
int selected = Utils.getWidth(selectedTab) + Utils.getMarginStart(selectedTab);
|
||||
x = Utils.getStart(selectedTab) - Utils.getMarginStart(selectedTab) + extraOffset;
|
||||
x -= (first - selected) / 2;
|
||||
}
|
||||
|
||||
scrollTo(x, 0);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
int x;
|
||||
if (titleOffset == TITLE_OFFSET_AUTO_CENTER) {
|
||||
|
||||
if (0f < positionOffset && positionOffset < 1f) {
|
||||
View nextTab = tabStrip.getChildAt(tabIndex + 1);
|
||||
int selectHalfWidth = Utils.getWidth(selectedTab) / 2 + Utils.getMarginEnd(selectedTab);
|
||||
int nextHalfWidth = Utils.getWidth(nextTab) / 2 + Utils.getMarginStart(nextTab);
|
||||
extraOffset = Math.round(positionOffset * (selectHalfWidth + nextHalfWidth));
|
||||
}
|
||||
|
||||
if (isLayoutRtl) {
|
||||
x = -Utils.getWidthWithMargin(selectedTab) / 2 + getWidth() / 2;
|
||||
x -= Utils.getPaddingStart(this);
|
||||
} else {
|
||||
x = Utils.getWidthWithMargin(selectedTab) / 2 - getWidth() / 2;
|
||||
x += Utils.getPaddingStart(this);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (isLayoutRtl) {
|
||||
x = (tabIndex > 0 || positionOffset > 0) ? titleOffset : 0;
|
||||
} else {
|
||||
x = (tabIndex > 0 || positionOffset > 0) ? -titleOffset : 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int start = Utils.getStart(selectedTab);
|
||||
int startMargin = Utils.getMarginStart(selectedTab);
|
||||
if (isLayoutRtl) {
|
||||
x += start + startMargin - extraOffset - getWidth() + Utils.getPaddingHorizontally(this);
|
||||
} else {
|
||||
x += start - startMargin + extraOffset;
|
||||
}
|
||||
|
||||
scrollTo(x, 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the scroll position of a view changes.
|
||||
*/
|
||||
public interface OnScrollChangeListener {
|
||||
|
||||
/**
|
||||
* Called when the scroll position of a view changes.
|
||||
*
|
||||
* @param scrollX Current horizontal scroll origin.
|
||||
* @param oldScrollX Previous horizontal scroll origin.
|
||||
*/
|
||||
void onScrollChanged(int scrollX, int oldScrollX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when a tab is clicked.
|
||||
*/
|
||||
public interface OnTabClickListener {
|
||||
|
||||
/**
|
||||
* Called when a tab is clicked.
|
||||
*
|
||||
* @param position tab's position
|
||||
*/
|
||||
void onTabClicked(int position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when a tab is long clicked.
|
||||
*/
|
||||
public interface OnTabLongClickListener {
|
||||
|
||||
/**
|
||||
* Called when a tab is clicked.
|
||||
*
|
||||
* @param position tab's position
|
||||
*/
|
||||
void onTabLongClicked(int position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the custom tabs in the tab layout. Set with
|
||||
* {@link #setCustomTabView(TabProvider)}
|
||||
*/
|
||||
public interface TabProvider {
|
||||
|
||||
/**
|
||||
* @return Return the View of {@code position} for the Tabs
|
||||
*/
|
||||
View createTabView(ViewGroup container, int position, @Nullable CharSequence pageTitle);
|
||||
|
||||
}
|
||||
|
||||
private static class SimpleTabProvider implements TabProvider {
|
||||
|
||||
private final LayoutInflater inflater;
|
||||
private final int tabViewLayoutId;
|
||||
private final int tabViewTextViewId;
|
||||
|
||||
private SimpleTabProvider(Context context, int layoutResId, int textViewId) {
|
||||
inflater = LayoutInflater.from(context);
|
||||
tabViewLayoutId = layoutResId;
|
||||
tabViewTextViewId = textViewId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createTabView(ViewGroup container, int position, CharSequence pageTitle) {
|
||||
View tabView = null;
|
||||
TextView tabTitleView = null;
|
||||
|
||||
if (tabViewLayoutId != NO_ID) {
|
||||
tabView = inflater.inflate(tabViewLayoutId, container, false);
|
||||
}
|
||||
|
||||
if (tabViewTextViewId != NO_ID && tabView != null) {
|
||||
tabTitleView = (TextView) tabView.findViewById(tabViewTextViewId);
|
||||
}
|
||||
|
||||
if (tabTitleView == null && TextView.class.isInstance(tabView)) {
|
||||
tabTitleView = (TextView) tabView;
|
||||
}
|
||||
|
||||
if (tabTitleView != null) {
|
||||
tabTitleView.setText(pageTitle);
|
||||
}
|
||||
|
||||
return tabView;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class InternalViewPagerListener extends ViewPager2.OnPageChangeCallback {
|
||||
|
||||
private int scrollState;
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
int tabStripChildCount = tabStrip.getChildCount();
|
||||
if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tabStrip.onViewPagerPageChanged(position, positionOffset);
|
||||
|
||||
scrollToTab(position, positionOffset);
|
||||
|
||||
if (viewPagerPageChangeCallback != null) {
|
||||
viewPagerPageChangeCallback.onPageScrolled(position, positionOffset, positionOffsetPixels);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
scrollState = state;
|
||||
|
||||
if (viewPagerPageChangeCallback != null) {
|
||||
viewPagerPageChangeCallback.onPageScrollStateChanged(state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
if (scrollState == ViewPager2.SCROLL_STATE_IDLE) {
|
||||
tabStrip.onViewPagerPageChanged(position, 0f);
|
||||
scrollToTab(position, 0);
|
||||
}
|
||||
|
||||
for (int i = 0, size = tabStrip.getChildCount(); i < size; i++) {
|
||||
tabStrip.getChildAt(i).setSelected(position == i);
|
||||
}
|
||||
|
||||
if (viewPagerPageChangeCallback != null) {
|
||||
viewPagerPageChangeCallback.onPageSelected(position);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class InternalTabClickListener implements OnClickListener {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
for (int i = 0; i < tabStrip.getChildCount(); i++) {
|
||||
if (v == tabStrip.getChildAt(i)) {
|
||||
if (onTabClickListener != null) {
|
||||
onTabClickListener.onTabClicked(i);
|
||||
}
|
||||
viewPager.setCurrentItem(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalTabLongClickListener implements OnLongClickListener {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
for (int i = 0; i < tabStrip.getChildCount(); i++) {
|
||||
if (v == tabStrip.getChildAt(i)) {
|
||||
if (onTabLongClickListener != null) {
|
||||
onTabLongClickListener.onTabLongClicked(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,446 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.chwl.library.R;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Forked from Google Samples > SlidingTabsBasic >
|
||||
* <a href="https://developer.android.com/samples/SlidingTabsBasic/src/com.example.android.common/view/SlidingTabLayout.html">SlidingTabStrip</a>
|
||||
*/
|
||||
class SmartTabStrip extends LinearLayout {
|
||||
|
||||
private static final int GRAVITY_BOTTOM = 0;
|
||||
private static final int GRAVITY_TOP = 1;
|
||||
private static final int GRAVITY_CENTER = 2;
|
||||
|
||||
private static final int AUTO_WIDTH = -1;
|
||||
|
||||
private static final int DEFAULT_TOP_BORDER_THICKNESS_DIPS = 0;
|
||||
private static final byte DEFAULT_TOP_BORDER_COLOR_ALPHA = 0x26;
|
||||
private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 2;
|
||||
private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26;
|
||||
private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 8;
|
||||
private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5;
|
||||
private static final float DEFAULT_INDICATOR_CORNER_RADIUS = 0f;
|
||||
private static final int DEFAULT_DIVIDER_THICKNESS_DIPS = 1;
|
||||
private static final byte DEFAULT_DIVIDER_COLOR_ALPHA = 0x20;
|
||||
private static final float DEFAULT_DIVIDER_HEIGHT = 0.5f;
|
||||
private static final boolean DEFAULT_INDICATOR_IN_CENTER = false;
|
||||
private static final boolean DEFAULT_INDICATOR_IN_FRONT = false;
|
||||
private static final boolean DEFAULT_INDICATOR_WITHOUT_PADDING = false;
|
||||
private static final int DEFAULT_INDICATOR_GRAVITY = GRAVITY_BOTTOM;
|
||||
private static final boolean DEFAULT_DRAW_DECORATION_AFTER_TAB = false;
|
||||
|
||||
private final int topBorderThickness;
|
||||
private final int topBorderColor;
|
||||
private final int bottomBorderThickness;
|
||||
private final int bottomBorderColor;
|
||||
private final Paint borderPaint;
|
||||
private final RectF indicatorRectF = new RectF();
|
||||
private final boolean indicatorWithoutPadding;
|
||||
private final boolean indicatorAlwaysInCenter;
|
||||
private final boolean indicatorInFront;
|
||||
private final int indicatorThickness;
|
||||
private final int indicatorWidth;
|
||||
private final int indicatorGravity;
|
||||
private final float indicatorCornerRadius;
|
||||
private final Paint indicatorPaint;
|
||||
private final int dividerThickness;
|
||||
private final Paint dividerPaint;
|
||||
private final float dividerHeight;
|
||||
private final SimpleTabColorizer defaultTabColorizer;
|
||||
private final boolean drawDecorationAfterTab;
|
||||
|
||||
private int lastPosition;
|
||||
private int selectedPosition;
|
||||
private float selectionOffset;
|
||||
private SmartTabIndicationInterpolator indicationInterpolator;
|
||||
private TabColorizer customTabColorizer;
|
||||
|
||||
SmartTabStrip(Context context, AttributeSet attrs) {
|
||||
super(context);
|
||||
setWillNotDraw(false);
|
||||
|
||||
final float density = getResources().getDisplayMetrics().density;
|
||||
|
||||
TypedValue outValue = new TypedValue();
|
||||
context.getTheme().resolveAttribute(android.R.attr.colorForeground, outValue, true);
|
||||
final int themeForegroundColor = outValue.data;
|
||||
|
||||
boolean indicatorWithoutPadding = DEFAULT_INDICATOR_WITHOUT_PADDING;
|
||||
boolean indicatorInFront = DEFAULT_INDICATOR_IN_FRONT;
|
||||
boolean indicatorAlwaysInCenter = DEFAULT_INDICATOR_IN_CENTER;
|
||||
int indicationInterpolatorId = SmartTabIndicationInterpolator.ID_SMART;
|
||||
int indicatorGravity = DEFAULT_INDICATOR_GRAVITY;
|
||||
int indicatorColor = DEFAULT_SELECTED_INDICATOR_COLOR;
|
||||
int indicatorColorsId = NO_ID;
|
||||
int indicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density);
|
||||
int indicatorWidth = AUTO_WIDTH;
|
||||
float indicatorCornerRadius = DEFAULT_INDICATOR_CORNER_RADIUS * density;
|
||||
int overlineColor = setColorAlpha(themeForegroundColor, DEFAULT_TOP_BORDER_COLOR_ALPHA);
|
||||
int overlineThickness = (int) (DEFAULT_TOP_BORDER_THICKNESS_DIPS * density);
|
||||
int underlineColor = setColorAlpha(themeForegroundColor, DEFAULT_BOTTOM_BORDER_COLOR_ALPHA);
|
||||
int underlineThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density);
|
||||
int dividerColor = setColorAlpha(themeForegroundColor, DEFAULT_DIVIDER_COLOR_ALPHA);
|
||||
int dividerColorsId = NO_ID;
|
||||
int dividerThickness = (int) (DEFAULT_DIVIDER_THICKNESS_DIPS * density);
|
||||
boolean drawDecorationAfterTab = DEFAULT_DRAW_DECORATION_AFTER_TAB;
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.stl_SmartTabLayout);
|
||||
indicatorAlwaysInCenter = a.getBoolean(
|
||||
R.styleable.stl_SmartTabLayout_stl_indicatorAlwaysInCenter, indicatorAlwaysInCenter);
|
||||
indicatorWithoutPadding = a.getBoolean(
|
||||
R.styleable.stl_SmartTabLayout_stl_indicatorWithoutPadding, indicatorWithoutPadding);
|
||||
indicatorInFront = a.getBoolean(
|
||||
R.styleable.stl_SmartTabLayout_stl_indicatorInFront, indicatorInFront);
|
||||
indicationInterpolatorId = a.getInt(
|
||||
R.styleable.stl_SmartTabLayout_stl_indicatorInterpolation, indicationInterpolatorId);
|
||||
indicatorGravity = a.getInt(
|
||||
R.styleable.stl_SmartTabLayout_stl_indicatorGravity, indicatorGravity);
|
||||
indicatorColor = a.getColor(
|
||||
R.styleable.stl_SmartTabLayout_stl_indicatorColor, indicatorColor);
|
||||
indicatorColorsId = a.getResourceId(
|
||||
R.styleable.stl_SmartTabLayout_stl_indicatorColors, indicatorColorsId);
|
||||
indicatorThickness = a.getDimensionPixelSize(
|
||||
R.styleable.stl_SmartTabLayout_stl_indicatorThickness, indicatorThickness);
|
||||
indicatorWidth = a.getLayoutDimension(
|
||||
R.styleable.stl_SmartTabLayout_stl_indicatorWidth, indicatorWidth);
|
||||
indicatorCornerRadius = a.getDimension(
|
||||
R.styleable.stl_SmartTabLayout_stl_indicatorCornerRadius, indicatorCornerRadius);
|
||||
overlineColor = a.getColor(
|
||||
R.styleable.stl_SmartTabLayout_stl_overlineColor, overlineColor);
|
||||
overlineThickness = a.getDimensionPixelSize(
|
||||
R.styleable.stl_SmartTabLayout_stl_overlineThickness, overlineThickness);
|
||||
underlineColor = a.getColor(
|
||||
R.styleable.stl_SmartTabLayout_stl_underlineColor, underlineColor);
|
||||
underlineThickness = a.getDimensionPixelSize(
|
||||
R.styleable.stl_SmartTabLayout_stl_underlineThickness, underlineThickness);
|
||||
dividerColor = a.getColor(
|
||||
R.styleable.stl_SmartTabLayout_stl_dividerColor, dividerColor);
|
||||
dividerColorsId = a.getResourceId(
|
||||
R.styleable.stl_SmartTabLayout_stl_dividerColors, dividerColorsId);
|
||||
dividerThickness = a.getDimensionPixelSize(
|
||||
R.styleable.stl_SmartTabLayout_stl_dividerThickness, dividerThickness);
|
||||
drawDecorationAfterTab = a.getBoolean(
|
||||
R.styleable.stl_SmartTabLayout_stl_drawDecorationAfterTab, drawDecorationAfterTab);
|
||||
a.recycle();
|
||||
|
||||
final int[] indicatorColors = (indicatorColorsId == NO_ID)
|
||||
? new int[] { indicatorColor }
|
||||
: getResources().getIntArray(indicatorColorsId);
|
||||
|
||||
final int[] dividerColors = (dividerColorsId == NO_ID)
|
||||
? new int[] { dividerColor }
|
||||
: getResources().getIntArray(dividerColorsId);
|
||||
|
||||
this.defaultTabColorizer = new SimpleTabColorizer();
|
||||
this.defaultTabColorizer.setIndicatorColors(indicatorColors);
|
||||
this.defaultTabColorizer.setDividerColors(dividerColors);
|
||||
|
||||
this.topBorderThickness = overlineThickness;
|
||||
this.topBorderColor = overlineColor;
|
||||
this.bottomBorderThickness = underlineThickness;
|
||||
this.bottomBorderColor = underlineColor;
|
||||
this.borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
this.indicatorAlwaysInCenter = indicatorAlwaysInCenter;
|
||||
this.indicatorWithoutPadding = indicatorWithoutPadding;
|
||||
this.indicatorInFront = indicatorInFront;
|
||||
this.indicatorThickness = indicatorThickness;
|
||||
this.indicatorWidth = indicatorWidth;
|
||||
this.indicatorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
this.indicatorCornerRadius = indicatorCornerRadius;
|
||||
this.indicatorGravity = indicatorGravity;
|
||||
|
||||
this.dividerHeight = DEFAULT_DIVIDER_HEIGHT;
|
||||
this.dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
this.dividerPaint.setStrokeWidth(dividerThickness);
|
||||
this.dividerThickness = dividerThickness;
|
||||
|
||||
this.drawDecorationAfterTab = drawDecorationAfterTab;
|
||||
|
||||
this.indicationInterpolator = SmartTabIndicationInterpolator.of(indicationInterpolatorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the alpha value of the {@code color} to be the given {@code alpha} value.
|
||||
*/
|
||||
private static int setColorAlpha(int color, byte alpha) {
|
||||
return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color));
|
||||
}
|
||||
|
||||
/**
|
||||
* Blend {@code color1} and {@code color2} using the given ratio.
|
||||
*
|
||||
* @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend,
|
||||
* 0.0 will return {@code color2}.
|
||||
*/
|
||||
private static int blendColors(int color1, int color2, float ratio) {
|
||||
final float inverseRation = 1f - ratio;
|
||||
float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
|
||||
float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
|
||||
float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
|
||||
return Color.rgb((int) r, (int) g, (int) b);
|
||||
}
|
||||
|
||||
void setIndicationInterpolator(SmartTabIndicationInterpolator interpolator) {
|
||||
indicationInterpolator = interpolator;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void setCustomTabColorizer(TabColorizer customTabColorizer) {
|
||||
this.customTabColorizer = customTabColorizer;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void setSelectedIndicatorColors(int... colors) {
|
||||
// Make sure that the custom colorizer is removed
|
||||
customTabColorizer = null;
|
||||
defaultTabColorizer.setIndicatorColors(colors);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void setDividerColors(int... colors) {
|
||||
// Make sure that the custom colorizer is removed
|
||||
customTabColorizer = null;
|
||||
defaultTabColorizer.setDividerColors(colors);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void onViewPagerPageChanged(int position, float positionOffset) {
|
||||
selectedPosition = position;
|
||||
selectionOffset = positionOffset;
|
||||
if (positionOffset == 0f && lastPosition != selectedPosition) {
|
||||
lastPosition = selectedPosition;
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
boolean isIndicatorAlwaysInCenter() {
|
||||
return indicatorAlwaysInCenter;
|
||||
}
|
||||
|
||||
TabColorizer getTabColorizer() {
|
||||
return (customTabColorizer != null) ? customTabColorizer : defaultTabColorizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (!drawDecorationAfterTab) {
|
||||
drawDecoration(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
if (drawDecorationAfterTab) {
|
||||
drawDecoration(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawDecoration(Canvas canvas) {
|
||||
final int height = getHeight();
|
||||
final int width = getWidth();
|
||||
final int tabCount = getChildCount();
|
||||
final TabColorizer tabColorizer = getTabColorizer();
|
||||
final boolean isLayoutRtl = Utils.isLayoutRtl(this);
|
||||
|
||||
if (indicatorInFront) {
|
||||
drawOverline(canvas, 0, width);
|
||||
drawUnderline(canvas, 0, width, height);
|
||||
}
|
||||
|
||||
// Thick colored underline below the current selection
|
||||
if (tabCount > 0) {
|
||||
View selectedTab = getChildAt(selectedPosition);
|
||||
int selectedStart = Utils.getStart(selectedTab, indicatorWithoutPadding);
|
||||
int selectedEnd = Utils.getEnd(selectedTab, indicatorWithoutPadding);
|
||||
int left;
|
||||
int right;
|
||||
if (isLayoutRtl) {
|
||||
left = selectedEnd;
|
||||
right = selectedStart;
|
||||
} else {
|
||||
left = selectedStart;
|
||||
right = selectedEnd;
|
||||
}
|
||||
|
||||
int color = tabColorizer.getIndicatorColor(selectedPosition);
|
||||
float thickness = indicatorThickness;
|
||||
|
||||
if (selectionOffset > 0f && selectedPosition < (getChildCount() - 1)) {
|
||||
int nextColor = tabColorizer.getIndicatorColor(selectedPosition + 1);
|
||||
if (color != nextColor) {
|
||||
color = blendColors(nextColor, color, selectionOffset);
|
||||
}
|
||||
|
||||
// Draw the selection partway between the tabs
|
||||
float startOffset = indicationInterpolator.getLeftEdge(selectionOffset);
|
||||
float endOffset = indicationInterpolator.getRightEdge(selectionOffset);
|
||||
float thicknessOffset = indicationInterpolator.getThickness(selectionOffset);
|
||||
|
||||
View nextTab = getChildAt(selectedPosition + 1);
|
||||
int nextStart = Utils.getStart(nextTab, indicatorWithoutPadding);
|
||||
int nextEnd = Utils.getEnd(nextTab, indicatorWithoutPadding);
|
||||
if (isLayoutRtl) {
|
||||
left = (int) (endOffset * nextEnd + (1.0f - endOffset) * left);
|
||||
right = (int) (startOffset * nextStart + (1.0f - startOffset) * right);
|
||||
} else {
|
||||
left = (int) (startOffset * nextStart + (1.0f - startOffset) * left);
|
||||
right = (int) (endOffset * nextEnd + (1.0f - endOffset) * right);
|
||||
}
|
||||
thickness = thickness * thicknessOffset;
|
||||
}
|
||||
|
||||
drawIndicator(canvas, left, right, height, thickness, color);
|
||||
|
||||
}
|
||||
|
||||
if (!indicatorInFront) {
|
||||
drawOverline(canvas, 0, width);
|
||||
drawUnderline(canvas, 0, getWidth(), height);
|
||||
}
|
||||
|
||||
// Vertical separators between the titles
|
||||
drawSeparator(canvas, height, tabCount);
|
||||
|
||||
}
|
||||
|
||||
private void drawSeparator(Canvas canvas, int height, int tabCount) {
|
||||
if (dividerThickness <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int dividerHeightPx = (int) (Math.min(Math.max(0f, dividerHeight), 1f) * height);
|
||||
final TabColorizer tabColorizer = getTabColorizer();
|
||||
|
||||
// Vertical separators between the titles
|
||||
final int separatorTop = (height - dividerHeightPx) / 2;
|
||||
final int separatorBottom = separatorTop + dividerHeightPx;
|
||||
|
||||
final boolean isLayoutRtl = Utils.isLayoutRtl(this);
|
||||
for (int i = 0; i < tabCount - 1; i++) {
|
||||
View child = getChildAt(i);
|
||||
int end = Utils.getEnd(child);
|
||||
int endMargin = Utils.getMarginEnd(child);
|
||||
int separatorX = isLayoutRtl ? end - endMargin : end + endMargin;
|
||||
dividerPaint.setColor(tabColorizer.getDividerColor(i));
|
||||
canvas.drawLine(separatorX, separatorTop, separatorX, separatorBottom, dividerPaint);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawIndicator(Canvas canvas, int left, int right, int height, float thickness,
|
||||
int color) {
|
||||
if (indicatorThickness <= 0 || indicatorWidth == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
float center;
|
||||
float top;
|
||||
float bottom;
|
||||
|
||||
switch (indicatorGravity) {
|
||||
case GRAVITY_TOP:
|
||||
center = indicatorThickness / 2f;
|
||||
top = center - (thickness / 2f);
|
||||
bottom = center + (thickness / 2f);
|
||||
break;
|
||||
case GRAVITY_CENTER:
|
||||
center = height / 2f;
|
||||
top = center - (thickness / 2f);
|
||||
bottom = center + (thickness / 2f);
|
||||
break;
|
||||
case GRAVITY_BOTTOM:
|
||||
default:
|
||||
center = height - (indicatorThickness / 2f);
|
||||
top = center - (thickness / 2f);
|
||||
bottom = center + (thickness / 2f);
|
||||
}
|
||||
|
||||
indicatorPaint.setColor(color);
|
||||
if (indicatorWidth == AUTO_WIDTH) {
|
||||
indicatorRectF.set(left, top, right, bottom);
|
||||
} else {
|
||||
float padding = (Math.abs(left - right) - indicatorWidth) / 2f;
|
||||
indicatorRectF.set(left + padding, top, right - padding, bottom);
|
||||
}
|
||||
|
||||
if (indicatorCornerRadius > 0f) {
|
||||
canvas.drawRoundRect(
|
||||
indicatorRectF, indicatorCornerRadius,
|
||||
indicatorCornerRadius, indicatorPaint);
|
||||
} else {
|
||||
canvas.drawRect(indicatorRectF, indicatorPaint);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawOverline(Canvas canvas, int left, int right) {
|
||||
if (topBorderThickness <= 0) {
|
||||
return;
|
||||
}
|
||||
// Thin overline along the entire top edge
|
||||
borderPaint.setColor(topBorderColor);
|
||||
canvas.drawRect(left, 0, right, topBorderThickness, borderPaint);
|
||||
}
|
||||
|
||||
private void drawUnderline(Canvas canvas, int left, int right, int height) {
|
||||
if (bottomBorderThickness <= 0) {
|
||||
return;
|
||||
}
|
||||
// Thin underline along the entire bottom edge
|
||||
borderPaint.setColor(bottomBorderColor);
|
||||
canvas.drawRect(left, height - bottomBorderThickness, right, height, borderPaint);
|
||||
}
|
||||
|
||||
private static class SimpleTabColorizer implements TabColorizer {
|
||||
|
||||
private int[] indicatorColors;
|
||||
private int[] dividerColors;
|
||||
|
||||
@Override
|
||||
public final int getIndicatorColor(int position) {
|
||||
return indicatorColors[position % indicatorColors.length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getDividerColor(int position) {
|
||||
return dividerColors[position % dividerColors.length];
|
||||
}
|
||||
|
||||
void setIndicatorColors(int... colors) {
|
||||
indicatorColors = colors;
|
||||
}
|
||||
|
||||
void setDividerColors(int... colors) {
|
||||
dividerColors = colors;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package com.chwl.library.widget.tab;
|
||||
|
||||
/**
|
||||
* Allows complete control over the colors drawn in the tab layout. Set with
|
||||
* {@link SmartTabLayout#setCustomTabColorizer(TabColorizer)}.
|
||||
*/
|
||||
public interface TabColorizer {
|
||||
|
||||
/**
|
||||
* @return return the color of the indicator used when {@code position} is selected.
|
||||
*/
|
||||
int getIndicatorColor(int position);
|
||||
|
||||
/**
|
||||
* @return return the color of the divider drawn to the right of {@code position}.
|
||||
*/
|
||||
int getDividerColor(int position);
|
||||
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
package com.chwl.library.widget.tab;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public interface TabTitleProvider {
|
||||
@Nullable
|
||||
CharSequence getPageTitle(int position);
|
||||
}
|
120
library/src/main/java/com/chwl/library/widget/tab/Utils.java
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.core.view.MarginLayoutParamsCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
final class Utils {
|
||||
|
||||
private Utils() { }
|
||||
|
||||
static int getMeasuredWidth(View v) {
|
||||
return (v == null) ? 0 : v.getMeasuredWidth();
|
||||
}
|
||||
|
||||
static int getWidth(View v) {
|
||||
return (v == null) ? 0 : v.getWidth();
|
||||
}
|
||||
|
||||
static int getWidthWithMargin(View v) {
|
||||
return getWidth(v) + getMarginHorizontally(v);
|
||||
}
|
||||
|
||||
static int getStart(View v) {
|
||||
return getStart(v, false);
|
||||
}
|
||||
|
||||
static int getStart(View v, boolean withoutPadding) {
|
||||
if (v == null) {
|
||||
return 0;
|
||||
}
|
||||
if (isLayoutRtl(v)) {
|
||||
return (withoutPadding) ? v.getRight() - getPaddingStart(v) : v.getRight();
|
||||
} else {
|
||||
return (withoutPadding) ? v.getLeft() + getPaddingStart(v) : v.getLeft();
|
||||
}
|
||||
}
|
||||
|
||||
static int getEnd(View v) {
|
||||
return getEnd(v, false);
|
||||
}
|
||||
|
||||
static int getEnd(View v, boolean withoutPadding) {
|
||||
if (v == null) {
|
||||
return 0;
|
||||
}
|
||||
if (isLayoutRtl(v)) {
|
||||
return (withoutPadding) ? v.getLeft() + getPaddingEnd(v) : v.getLeft();
|
||||
} else {
|
||||
return (withoutPadding) ? v.getRight() - getPaddingEnd(v) : v.getRight();
|
||||
}
|
||||
}
|
||||
|
||||
static int getPaddingStart(View v) {
|
||||
if (v == null) {
|
||||
return 0;
|
||||
}
|
||||
return ViewCompat.getPaddingStart(v);
|
||||
}
|
||||
|
||||
static int getPaddingEnd(View v) {
|
||||
if (v == null) {
|
||||
return 0;
|
||||
}
|
||||
return ViewCompat.getPaddingEnd(v);
|
||||
}
|
||||
|
||||
static int getPaddingHorizontally(View v) {
|
||||
if (v == null) {
|
||||
return 0;
|
||||
}
|
||||
return v.getPaddingLeft() + v.getPaddingRight();
|
||||
}
|
||||
|
||||
static int getMarginStart(View v) {
|
||||
if (v == null) {
|
||||
return 0;
|
||||
}
|
||||
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
|
||||
return MarginLayoutParamsCompat.getMarginStart(lp);
|
||||
}
|
||||
|
||||
static int getMarginEnd(View v) {
|
||||
if (v == null) {
|
||||
return 0;
|
||||
}
|
||||
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
|
||||
return MarginLayoutParamsCompat.getMarginEnd(lp);
|
||||
}
|
||||
|
||||
static int getMarginHorizontally(View v) {
|
||||
if (v == null) {
|
||||
return 0;
|
||||
}
|
||||
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
|
||||
return MarginLayoutParamsCompat.getMarginStart(lp) + MarginLayoutParamsCompat.getMarginEnd(lp);
|
||||
}
|
||||
|
||||
static boolean isLayoutRtl(View v) {
|
||||
return ViewCompat.getLayoutDirection(v) == ViewCompat.LAYOUT_DIRECTION_RTL;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package com.chwl.library.widget.tab.util
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
|
||||
class FragmentPageAdapter(fragmentManager: FragmentActivity, var fgList: List<Fragment>?) :
|
||||
FragmentStateAdapter(fragmentManager) {
|
||||
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return fgList?.size?:0
|
||||
}
|
||||
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
return fgList?.get(position) ?: Fragment()
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab.util;
|
||||
|
||||
public abstract class PagerItem {
|
||||
|
||||
protected static final float DEFAULT_WIDTH = 1.f;
|
||||
|
||||
private final CharSequence title;
|
||||
private final float width;
|
||||
|
||||
protected PagerItem(CharSequence title, float width) {
|
||||
this.title = title;
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public CharSequence getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public float getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class PagerItems<T extends PagerItem> extends ArrayList<T> {
|
||||
|
||||
private final Context context;
|
||||
|
||||
protected PagerItems(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab.util;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
|
||||
public class ViewPagerItem extends PagerItem {
|
||||
|
||||
private final int resource;
|
||||
|
||||
protected ViewPagerItem(CharSequence title, float width, @LayoutRes int resource) {
|
||||
super(title, width);
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public static ViewPagerItem of(CharSequence title, @LayoutRes int resource) {
|
||||
return of(title, DEFAULT_WIDTH, resource);
|
||||
}
|
||||
|
||||
public static ViewPagerItem of(CharSequence title, float width, @LayoutRes int resource) {
|
||||
return new ViewPagerItem(title, width, resource);
|
||||
}
|
||||
|
||||
public View initiate(LayoutInflater inflater, ViewGroup container) {
|
||||
return inflater.inflate(resource, container, false);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab.util;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.collection.SparseArrayCompat;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class ViewPagerItemAdapter extends PagerAdapter {
|
||||
|
||||
private final ViewPagerItems pages;
|
||||
private final SparseArrayCompat<WeakReference<View>> holder;
|
||||
private final LayoutInflater inflater;
|
||||
|
||||
public ViewPagerItemAdapter(ViewPagerItems pages) {
|
||||
this.pages = pages;
|
||||
this.holder = new SparseArrayCompat<>(pages.size());
|
||||
this.inflater = LayoutInflater.from(pages.getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return pages.size();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Object instantiateItem(@NonNull ViewGroup container, int position) {
|
||||
View view = getPagerItem(position).initiate(inflater, container);
|
||||
container.addView(view);
|
||||
holder.put(position, new WeakReference<View>(view));
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
||||
holder.remove(position);
|
||||
container.removeView((View) object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
|
||||
return object == view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return getPagerItem(position).getTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPageWidth(int position) {
|
||||
return getPagerItem(position).getWidth();
|
||||
}
|
||||
|
||||
public View getPage(int position) {
|
||||
final WeakReference<View> weakRefItem = holder.get(position);
|
||||
return (weakRefItem != null) ? weakRefItem.get() : null;
|
||||
}
|
||||
|
||||
protected ViewPagerItem getPagerItem(int position) {
|
||||
return pages.get(position);
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
public class ViewPagerItems extends PagerItems<ViewPagerItem> {
|
||||
|
||||
public ViewPagerItems(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public static Creator with(Context context) {
|
||||
return new Creator(context);
|
||||
}
|
||||
|
||||
public static class Creator {
|
||||
|
||||
private final ViewPagerItems items;
|
||||
|
||||
public Creator(Context context) {
|
||||
items = new ViewPagerItems(context);
|
||||
}
|
||||
|
||||
public Creator add(@StringRes int title, @LayoutRes int resource) {
|
||||
return add(ViewPagerItem.of(items.getContext().getString(title), resource));
|
||||
}
|
||||
|
||||
public Creator add(@StringRes int title, float width, @LayoutRes int resource) {
|
||||
return add(ViewPagerItem.of(items.getContext().getString(title), width, resource));
|
||||
}
|
||||
|
||||
public Creator add(CharSequence title, @LayoutRes int resource) {
|
||||
return add(ViewPagerItem.of(title, resource));
|
||||
}
|
||||
|
||||
public Creator add(ViewPagerItem item) {
|
||||
items.add(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ViewPagerItems create() {
|
||||
return items;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,520 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab.util.v4;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Size;
|
||||
import android.util.SizeF;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Bundler {
|
||||
|
||||
private final Bundle bundle;
|
||||
|
||||
/**
|
||||
* Constructs a new, empty Bundle.
|
||||
*/
|
||||
public Bundler() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
private Bundler(Bundle b) {
|
||||
bundle = (b == null) ? new Bundle() : new Bundle(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Bundle containing a copy of the mappings from the given
|
||||
* Bundle.
|
||||
*
|
||||
* @param b a Bundle to be copied.
|
||||
*/
|
||||
public static Bundler of(Bundle b) {
|
||||
return new Bundler(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all mappings from the given Bundle into this Bundle.
|
||||
*
|
||||
* @param bundle a Bundle
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putAll(Bundle bundle) {
|
||||
this.bundle.putAll(bundle);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a byte value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a byte
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putByte(String key, byte value) {
|
||||
bundle.putByte(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a char value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a char, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putChar(String key, char value) {
|
||||
bundle.putChar(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a short value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a short
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putShort(String key, short value) {
|
||||
bundle.putShort(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a float value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a float
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putFloat(String key, float value) {
|
||||
bundle.putFloat(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a CharSequence value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a CharSequence, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putCharSequence(String key, CharSequence value) {
|
||||
bundle.putCharSequence(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a Parcelable value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a Parcelable object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putParcelable(String key, Parcelable value) {
|
||||
bundle.putParcelable(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a Size value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a Size object, or null
|
||||
* @return this
|
||||
*/
|
||||
@TargetApi(21)
|
||||
public Bundler putSize(String key, Size value) {
|
||||
bundle.putSize(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a SizeF value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a SizeF object, or null
|
||||
* @return this
|
||||
*/
|
||||
@TargetApi(21)
|
||||
public Bundler putSizeF(String key, SizeF value) {
|
||||
bundle.putSizeF(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an array of Parcelable values into the mapping of this Bundle,
|
||||
* replacing any existing value for the given key. Either key or value may
|
||||
* be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value an array of Parcelable objects, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putParcelableArray(String key, Parcelable[] value) {
|
||||
bundle.putParcelableArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a List of Parcelable values into the mapping of this Bundle,
|
||||
* replacing any existing value for the given key. Either key or value may
|
||||
* be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value an ArrayList of Parcelable objects, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putParcelableArrayList(String key,
|
||||
ArrayList<? extends Parcelable> value) {
|
||||
bundle.putParcelableArrayList(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a SparceArray of Parcelable values into the mapping of this
|
||||
* Bundle, replacing any existing value for the given key. Either key
|
||||
* or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a SparseArray of Parcelable objects, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putSparseParcelableArray(String key,
|
||||
SparseArray<? extends Parcelable> value) {
|
||||
bundle.putSparseParcelableArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an ArrayList<Integer> value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value an ArrayList<Integer> object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putIntegerArrayList(String key, ArrayList<Integer> value) {
|
||||
bundle.putIntegerArrayList(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an ArrayList<String> value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value an ArrayList<String> object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putStringArrayList(String key, ArrayList<String> value) {
|
||||
bundle.putStringArrayList(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an ArrayList<CharSequence> value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value an ArrayList<CharSequence> object, or null
|
||||
* @return this
|
||||
*/
|
||||
@TargetApi(8)
|
||||
public Bundler putCharSequenceArrayList(String key, ArrayList<CharSequence> value) {
|
||||
bundle.putCharSequenceArrayList(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a Serializable value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a Serializable object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putSerializable(String key, Serializable value) {
|
||||
bundle.putSerializable(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a byte array value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a byte array object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putByteArray(String key, byte[] value) {
|
||||
bundle.putByteArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a short array value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a short array object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putShortArray(String key, short[] value) {
|
||||
bundle.putShortArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a char array value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a char array object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putCharArray(String key, char[] value) {
|
||||
bundle.putCharArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a float array value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a float array object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putFloatArray(String key, float[] value) {
|
||||
bundle.putFloatArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a CharSequence array value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a CharSequence array object, or null
|
||||
* @return this
|
||||
*/
|
||||
@TargetApi(8)
|
||||
public Bundler putCharSequenceArray(String key, CharSequence[] value) {
|
||||
bundle.putCharSequenceArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a Bundle value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a Bundle object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putBundle(String key, Bundle value) {
|
||||
bundle.putBundle(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an {@link IBinder} value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* <p class="note">You should be very careful when using this function. In many
|
||||
* places where Bundles are used (such as inside of Intent objects), the Bundle
|
||||
* can live longer inside of another process than the process that had originally
|
||||
* created it. In that case, the IBinder you supply here will become invalid
|
||||
* when your process goes away, and no longer usable, even if a new process is
|
||||
* created for you later on.</p>
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value an IBinder object, or null
|
||||
* @return this
|
||||
*/
|
||||
@TargetApi(18)
|
||||
public Bundler putBinder(String key, IBinder value) {
|
||||
bundle.putBinder(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a Boolean value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a Boolean, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putBoolean(String key, boolean value) {
|
||||
bundle.putBoolean(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an int value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value an int, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putInt(String key, int value) {
|
||||
bundle.putInt(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a long value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a long
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putLong(String key, long value) {
|
||||
bundle.putLong(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a double value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a double
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putDouble(String key, double value) {
|
||||
bundle.putDouble(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a String value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a String, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putString(String key, String value) {
|
||||
bundle.putString(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a boolean array value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a boolean array object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putBooleanArray(String key, boolean[] value) {
|
||||
bundle.putBooleanArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an int array value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value an int array object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putIntArray(String key, int[] value) {
|
||||
bundle.putIntArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a long array value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a long array object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putLongArray(String key, long[] value) {
|
||||
bundle.putLongArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a double array value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a double array object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putDoubleArray(String key, double[] value) {
|
||||
bundle.putDoubleArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a String array value into the mapping of this Bundle, replacing
|
||||
* any existing value for the given key. Either key or value may be null.
|
||||
*
|
||||
* @param key a String, or null
|
||||
* @param value a String array object, or null
|
||||
* @return this
|
||||
*/
|
||||
public Bundler putStringArray(String key, String[] value) {
|
||||
bundle.putStringArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bundle.
|
||||
*
|
||||
* @return a bundle
|
||||
*/
|
||||
public Bundle get() {
|
||||
return bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the argument of Fragment.
|
||||
*
|
||||
* @param fragment a fragment
|
||||
* @return a fragment
|
||||
*/
|
||||
public <T extends Fragment> T into(T fragment) {
|
||||
fragment.setArguments(get());
|
||||
return fragment;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab.util.v4;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.chwl.library.widget.tab.util.PagerItem;
|
||||
|
||||
|
||||
public class FragmentPagerItem extends PagerItem {
|
||||
|
||||
private static final String TAG = "FragmentPagerItem";
|
||||
private static final String KEY_POSITION = TAG + ":Position";
|
||||
|
||||
private final String className;
|
||||
private final Bundle args;
|
||||
|
||||
protected FragmentPagerItem(CharSequence title, float width, String className, Bundle args) {
|
||||
super(title, width);
|
||||
this.className = className;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public static FragmentPagerItem of(CharSequence title, Class<? extends Fragment> clazz) {
|
||||
return of(title, DEFAULT_WIDTH, clazz);
|
||||
}
|
||||
|
||||
public static FragmentPagerItem of(CharSequence title, Class<? extends Fragment> clazz,
|
||||
Bundle args) {
|
||||
return of(title, DEFAULT_WIDTH, clazz, args);
|
||||
}
|
||||
|
||||
public static FragmentPagerItem of(CharSequence title, float width,
|
||||
Class<? extends Fragment> clazz) {
|
||||
return of(title, width, clazz, new Bundle());
|
||||
}
|
||||
|
||||
public static FragmentPagerItem of(CharSequence title, float width,
|
||||
Class<? extends Fragment> clazz, Bundle args) {
|
||||
return new FragmentPagerItem(title, width, clazz.getName(), args);
|
||||
}
|
||||
|
||||
public static boolean hasPosition(Bundle args) {
|
||||
return args != null && args.containsKey(KEY_POSITION);
|
||||
}
|
||||
|
||||
public static int getPosition(Bundle args) {
|
||||
return (hasPosition(args)) ? args.getInt(KEY_POSITION) : 0;
|
||||
}
|
||||
|
||||
static void setPosition(Bundle args, int position) {
|
||||
args.putInt(KEY_POSITION, position);
|
||||
}
|
||||
|
||||
public Fragment instantiate(Context context, int position) {
|
||||
setPosition(args, position);
|
||||
return Fragment.instantiate(context, className, args);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab.util.v4;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.collection.SparseArrayCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class FragmentPagerItemAdapter extends FragmentPagerAdapter {
|
||||
|
||||
private final FragmentPagerItems pages;
|
||||
private final SparseArrayCompat<WeakReference<Fragment>> holder;
|
||||
|
||||
public FragmentPagerItemAdapter(FragmentManager fm, FragmentPagerItems pages) {
|
||||
super(fm);
|
||||
this.pages = pages;
|
||||
this.holder = new SparseArrayCompat<>(pages.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return pages.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return getPagerItem(position).instantiate(pages.getContext(), position);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Object instantiateItem(@NonNull ViewGroup container, int position) {
|
||||
Object item = super.instantiateItem(container, position);
|
||||
if (item instanceof Fragment) {
|
||||
holder.put(position, new WeakReference<Fragment>((Fragment) item));
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
||||
holder.remove(position);
|
||||
super.destroyItem(container, position, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return getPagerItem(position).getTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPageWidth(int position) {
|
||||
return super.getPageWidth(position);
|
||||
}
|
||||
|
||||
public Fragment getPage(int position) {
|
||||
final WeakReference<Fragment> weakRefItem = holder.get(position);
|
||||
return (weakRefItem != null) ? weakRefItem.get() : null;
|
||||
}
|
||||
|
||||
protected FragmentPagerItem getPagerItem(int position) {
|
||||
return pages.get(position);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab.util.v4;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.chwl.library.widget.tab.util.PagerItems;
|
||||
|
||||
|
||||
public class FragmentPagerItems extends PagerItems<FragmentPagerItem> {
|
||||
|
||||
public FragmentPagerItems(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public static Creator with(Context context) {
|
||||
return new Creator(context);
|
||||
}
|
||||
|
||||
public static class Creator {
|
||||
|
||||
private final FragmentPagerItems items;
|
||||
|
||||
public Creator(Context context) {
|
||||
items = new FragmentPagerItems(context);
|
||||
}
|
||||
|
||||
public Creator add(@StringRes int title, Class<? extends Fragment> clazz) {
|
||||
return add(FragmentPagerItem.of(items.getContext().getString(title), clazz));
|
||||
}
|
||||
|
||||
public Creator add(@StringRes int title, Class<? extends Fragment> clazz, Bundle args) {
|
||||
return add(FragmentPagerItem.of(items.getContext().getString(title), clazz, args));
|
||||
}
|
||||
|
||||
public Creator add(@StringRes int title, float width, Class<? extends Fragment> clazz) {
|
||||
return add(FragmentPagerItem.of(items.getContext().getString(title), width, clazz));
|
||||
}
|
||||
|
||||
public Creator add(@StringRes int title, float width, Class<? extends Fragment> clazz,
|
||||
Bundle args) {
|
||||
return add(FragmentPagerItem.of(items.getContext().getString(title), width, clazz, args));
|
||||
}
|
||||
|
||||
public Creator add(CharSequence title, Class<? extends Fragment> clazz) {
|
||||
return add(FragmentPagerItem.of(title, clazz));
|
||||
}
|
||||
|
||||
public Creator add(CharSequence title, Class<? extends Fragment> clazz, Bundle args) {
|
||||
return add(FragmentPagerItem.of(title, clazz, args));
|
||||
}
|
||||
|
||||
public Creator add(FragmentPagerItem item) {
|
||||
items.add(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FragmentPagerItems create() {
|
||||
return items;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright (C) 2015 ogaclejapan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chwl.library.widget.tab.util.v4;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.collection.SparseArrayCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class FragmentStatePagerItemAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
private final FragmentPagerItems pages;
|
||||
private final SparseArrayCompat<WeakReference<Fragment>> holder;
|
||||
|
||||
public FragmentStatePagerItemAdapter(FragmentManager fm, FragmentPagerItems pages) {
|
||||
super(fm);
|
||||
this.pages = pages;
|
||||
this.holder = new SparseArrayCompat<>(pages.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return pages.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return getPagerItem(position).instantiate(pages.getContext(), position);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Object instantiateItem(@NonNull ViewGroup container, int position) {
|
||||
Object item = super.instantiateItem(container, position);
|
||||
if (item instanceof Fragment) {
|
||||
holder.put(position, new WeakReference<Fragment>((Fragment) item));
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
||||
holder.remove(position);
|
||||
super.destroyItem(container, position, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return getPagerItem(position).getTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPageWidth(int position) {
|
||||
return getPagerItem(position).getWidth();
|
||||
}
|
||||
|
||||
public Fragment getPage(int position) {
|
||||
final WeakReference<Fragment> weakRefItem = holder.get(position);
|
||||
return (weakRefItem != null) ? weakRefItem.get() : null;
|
||||
}
|
||||
|
||||
protected FragmentPagerItem getPagerItem(int position) {
|
||||
return pages.get(position);
|
||||
}
|
||||
|
||||
}
|
@@ -120,7 +120,7 @@ public class DrawableTextView extends AppCompatTextView {
|
||||
strikeColor = a.getColor(R.styleable.DrawableTextView_dt_strikeColor, -1);
|
||||
strikeWidth = a.getDimensionPixelSize(R.styleable.DrawableTextView_dt_strikeWidth, 0);
|
||||
//填充颜色
|
||||
soildColor = a.getColor(R.styleable.DrawableTextView_dt_soildColor, 0xffffffff);
|
||||
soildColor = a.getColor(R.styleable.DrawableTextView_dt_soildColor, 0x00000000);
|
||||
//渐变相关
|
||||
angle = a.getInt(R.styleable.DrawableTextView_dt_angle, 0);
|
||||
startColor = a.getColor(R.styleable.DrawableTextView_dt_startColor, -1);
|
||||
|
@@ -191,4 +191,64 @@
|
||||
<attr name="dt_lineColor" format="color" />
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
<declare-styleable name="stl_SmartTabLayout">
|
||||
<!-- 设置为true时与权重互斥, 不能都设置为true-->
|
||||
<attr name="stl_indicatorAlwaysInCenter" format="boolean"/>
|
||||
<attr name="stl_indicatorWithoutPadding" format="boolean"/>
|
||||
<attr name="stl_indicatorInFront" format="boolean"/>
|
||||
<attr name="stl_indicatorInterpolation" format="enum">
|
||||
<enum name="smart" value="0"/>
|
||||
<enum name="linear" value="1"/>
|
||||
</attr>
|
||||
<attr name="stl_indicatorGravity" format="enum">
|
||||
<enum name="bottom" value="0"/>
|
||||
<enum name="top" value="1"/>
|
||||
<enum name="center" value="2"/>
|
||||
</attr>
|
||||
<attr name="stl_indicatorColor" format="color"/>
|
||||
<attr name="stl_indicatorColors" format="reference"/>
|
||||
<!-- 指示器高-->
|
||||
<attr name="stl_indicatorThickness" format="dimension"/>
|
||||
<!-- 指示器宽-->
|
||||
<attr name="stl_indicatorWidth" format="dimension">
|
||||
<enum name="auto" value="-1"/>
|
||||
</attr>
|
||||
<attr name="stl_indicatorCornerRadius" format="dimension"/>
|
||||
|
||||
<attr name="stl_overlineColor" format="color"/>
|
||||
<attr name="stl_overlineThickness" format="dimension"/>
|
||||
|
||||
<attr name="stl_underlineColor" format="color"/>
|
||||
<attr name="stl_underlineThickness" format="dimension"/>
|
||||
|
||||
<attr name="stl_dividerColor" format="color"/>
|
||||
<attr name="stl_dividerColors" format="reference"/>
|
||||
<attr name="stl_dividerThickness" format="dimension"/>
|
||||
|
||||
<attr name="stl_defaultTabBackground" format="reference"/>
|
||||
|
||||
<attr name="stl_defaultTabTextAllCaps" format="boolean"/>
|
||||
<attr name="stl_defaultTabTextColor" format="color|reference"/>
|
||||
<attr name="stl_defaultTabTextSize" format="dimension"/>
|
||||
<attr name="stl_defaultTabTextHorizontalPadding" format="dimension"/>
|
||||
<attr name="stl_defaultTabTextMinWidth" format="dimension"/>
|
||||
|
||||
<!-- 自定义布局-->
|
||||
<attr name="stl_customTabTextLayoutId" format="reference"/>
|
||||
<attr name="stl_customTabTextViewId" format="reference"/>
|
||||
<!-- 权重-->
|
||||
<attr name="stl_distributeEvenly" format="boolean"/>
|
||||
|
||||
<attr name="stl_clickable" format="boolean"/>
|
||||
|
||||
<attr name="stl_titleOffset" format="dimension">
|
||||
<enum name="auto_center" value="-1"/>
|
||||
</attr>
|
||||
|
||||
<attr name="stl_drawDecorationAfterTab" format="boolean"/>
|
||||
|
||||
<attr name="stl_tabTextStyle" format="reference" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
@@ -0,0 +1,434 @@
|
||||
//package com.kelly.dawi.util
|
||||
//
|
||||
//import android.graphics.Bitmap
|
||||
//import android.graphics.Paint
|
||||
//import android.os.Looper
|
||||
//import android.text.TextPaint
|
||||
//import android.view.View
|
||||
//import android.widget.ImageView
|
||||
//import androidx.annotation.DrawableRes
|
||||
//import androidx.lifecycle.findViewTreeLifecycleOwner
|
||||
//import androidx.lifecycle.lifecycleScope
|
||||
//import com.bumptech.glide.Glide
|
||||
//import com.bumptech.glide.load.DataSource
|
||||
//import com.bumptech.glide.load.engine.GlideException
|
||||
//import com.bumptech.glide.request.FutureTarget
|
||||
//import com.bumptech.glide.request.RequestFutureTarget
|
||||
//import com.bumptech.glide.request.RequestListener
|
||||
//import com.bumptech.glide.request.RequestOptions
|
||||
//import com.bumptech.glide.request.target.Target
|
||||
//import com.kelly.dawi.dp
|
||||
//import com.kelly.dawi.getOrNull
|
||||
//import com.kelly.dawi.simpleImpl.SimpleSvgaCallback
|
||||
//import com.kelly.dawi.suspendGetOrNull
|
||||
//import com.opensource.svgaplayer.SVGAImageView
|
||||
//import com.opensource.svgaplayer.glideplugin.asSVGADrawable
|
||||
//import com.tencent.qgame.animplayer.AnimView
|
||||
//import com.tencent.qgame.animplayer.inter.IFetchResource
|
||||
//import com.tencent.qgame.animplayer.mix.Resource
|
||||
//import com.tencent.qgame.animplayer.util.ScaleType
|
||||
//import com.kelly.dawi.simpleImpl.SimpleVapCallback
|
||||
//import kotlinx.coroutines.*
|
||||
//import java.io.File
|
||||
//import java.lang.RuntimeException
|
||||
//import java.util.concurrent.CancellationException
|
||||
//
|
||||
///**
|
||||
// * @Author Vance
|
||||
// * @Date 2022/6/17 0017 13:44
|
||||
// */
|
||||
//
|
||||
//object AnimEffectUtil {
|
||||
//
|
||||
// @JvmStatic
|
||||
// fun newBuilder(): ExtBuilder {
|
||||
// return ExtBuilder()
|
||||
// }
|
||||
//
|
||||
// @JvmStatic
|
||||
// fun load(url: String?): ExtBuilder {
|
||||
// return ExtBuilder().load(url)
|
||||
// }
|
||||
//
|
||||
// class ExtBuilder : IFetchResource, View.OnAttachStateChangeListener {
|
||||
// private val defTextPaint = TextPaint().apply { textAlign = Paint.Align.CENTER }
|
||||
//
|
||||
// private var job: Job? = null
|
||||
// private var extMap = mutableMapOf<String, Ext>()
|
||||
// private var glideRequests = mutableListOf<FutureTarget<*>?>()
|
||||
//
|
||||
// private var tempExtMap = mutableMapOf<String, Ext>()
|
||||
// private var listener: Listener? = null
|
||||
// private var repeatCount: Int? = null
|
||||
// private var clearsAfterDetached: Boolean? = null
|
||||
// private var scaleType: ImageView.ScaleType? = null
|
||||
//
|
||||
// private var url: String? = null
|
||||
//
|
||||
// private var skipMemoryCache = true
|
||||
//
|
||||
// private var scope:CoroutineScope? = null
|
||||
//
|
||||
// fun load(url: String?): ExtBuilder {
|
||||
// this.url = url
|
||||
// return this
|
||||
// }
|
||||
//
|
||||
// fun setCoroutineScope(scope:CoroutineScope): ExtBuilder {
|
||||
// this.scope = scope
|
||||
// return this
|
||||
// }
|
||||
//
|
||||
// fun skipMemoryCache(skipMemoryCache: Boolean): ExtBuilder {
|
||||
// this.skipMemoryCache = skipMemoryCache
|
||||
// return this
|
||||
// }
|
||||
//
|
||||
// fun scaleType(scaleType: ImageView.ScaleType): ExtBuilder {
|
||||
// this.scaleType = scaleType
|
||||
// return this
|
||||
// }
|
||||
//
|
||||
// fun clearsAfterDetached(clearsAfterDetached: Boolean): ExtBuilder {
|
||||
// this.clearsAfterDetached = clearsAfterDetached
|
||||
// return this
|
||||
// }
|
||||
//
|
||||
// fun listener(listener: Listener?): ExtBuilder {
|
||||
// this.listener = listener
|
||||
// return this
|
||||
// }
|
||||
//
|
||||
// fun repeatCount(repeatCount: Int): ExtBuilder {
|
||||
// this.repeatCount = repeatCount
|
||||
// return this
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * textPain是SVGA用的
|
||||
// */
|
||||
// @JvmOverloads
|
||||
// fun putText(key: String, text: String?, textPaint: TextPaint = defTextPaint): ExtBuilder {
|
||||
// tempExtMap[key] = Ext(text, textPaint)
|
||||
// return this
|
||||
// }
|
||||
//
|
||||
// @JvmOverloads
|
||||
// fun putImg(
|
||||
// key: String,
|
||||
// imgUrl: Any?,
|
||||
// widthDp: Float = 0f,
|
||||
// heightDp: Float = 0f,
|
||||
// isCircle: Boolean = true,
|
||||
// @DrawableRes default: Int = 0
|
||||
// ): ExtBuilder {
|
||||
// tempExtMap[key] = Ext(
|
||||
// imgGetter = {
|
||||
// val option = RequestOptions()
|
||||
// if (isCircle) {
|
||||
// option.circleCrop()
|
||||
// }
|
||||
// if (widthDp > 0 && heightDp > 0) {
|
||||
// option.override(widthDp.dp, heightDp.dp)
|
||||
// }
|
||||
//
|
||||
// val futureTarget = RequestFutureTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
|
||||
// glideRequests.add(futureTarget)
|
||||
// var bitmap: Bitmap? = null
|
||||
// try {
|
||||
// bitmap = Glide.with(MyUtils.application)
|
||||
// .asBitmap()
|
||||
// .load(imgUrl)
|
||||
// .apply(option)
|
||||
// .addListener(futureTarget)
|
||||
// .into(futureTarget)
|
||||
// .get()
|
||||
// }catch (e: InterruptedException){
|
||||
// glideRequests.remove(futureTarget)
|
||||
// return@Ext null //取消掉的直接返回不去加载默认图了
|
||||
// }catch (e: CancellationException){
|
||||
// glideRequests.remove(futureTarget)
|
||||
// return@Ext null //取消掉的直接返回不去加载默认图了
|
||||
// }catch (e: Exception){
|
||||
// glideRequests.remove(futureTarget)
|
||||
// }
|
||||
//
|
||||
// if (bitmap == null && default != 0) {
|
||||
// val defFutureTarget = RequestFutureTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
|
||||
// glideRequests.add(defFutureTarget)
|
||||
// bitmap = Glide.with(MyUtils.application)
|
||||
// .asBitmap()
|
||||
// .load(default)
|
||||
// .apply(option)
|
||||
// .addListener(defFutureTarget)
|
||||
// .into(defFutureTarget)
|
||||
// .getOrNull()
|
||||
// }
|
||||
// bitmap
|
||||
// })
|
||||
// return this
|
||||
// }
|
||||
//
|
||||
// fun into(svgaImageView: SVGAImageView){
|
||||
// setup(svgaImageView)
|
||||
// val animUrl = url
|
||||
// if(animUrl.isNullOrBlank()){
|
||||
// listener?.onAnimError(RuntimeException("url is empty"))
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// var svgaUrl = animUrl
|
||||
// if(!animUrl.startsWith("http")){//没有http前缀就当成asset文件加载
|
||||
// svgaUrl = "file:///android_asset/$animUrl"
|
||||
// }
|
||||
//
|
||||
// if(scope == null){
|
||||
// scope = svgaImageView.findViewTreeLifecycleOwner()?.lifecycleScope
|
||||
// }
|
||||
//
|
||||
// job = scope?.launch(Dispatchers.IO) {
|
||||
// val svgaJob = async {
|
||||
// Glide.with(svgaImageView.context)
|
||||
// .asSVGADrawable()
|
||||
// .load(svgaUrl.trim())
|
||||
// .skipMemoryCache(skipMemoryCache)
|
||||
// .submit()
|
||||
// .suspendGetOrNull()
|
||||
// }
|
||||
//
|
||||
// val bitmapJobMap = mutableMapOf<String, Deferred<Bitmap?>>()
|
||||
// val textMap = mutableMapOf<String, Ext>()
|
||||
// val paramsMap = mutableMapOf<String, Ext>()
|
||||
// try {
|
||||
// paramsMap.putAll(extMap)
|
||||
// paramsMap.forEach {
|
||||
// ensureActive()
|
||||
// if (it.value.isImg()) {
|
||||
// val job = async { it.value.getBitMap() }
|
||||
// bitmapJobMap[it.key] = job
|
||||
// } else {
|
||||
// textMap[it.key] = it.value
|
||||
// }
|
||||
// }
|
||||
// } catch (_: Exception) { }
|
||||
//
|
||||
// val drawable = svgaJob.await()
|
||||
// if (drawable == null) {
|
||||
// bitmapJobMap.forEach {
|
||||
// it.value.cancelAndJoin()
|
||||
// }
|
||||
// val imgRequests = glideRequests
|
||||
// imgRequests.forEach {
|
||||
// it?.cancel(true)
|
||||
// }
|
||||
// withContext(Dispatchers.Main) {
|
||||
// onAnimError("svga loading error ")
|
||||
// }
|
||||
// } else {
|
||||
// bitmapJobMap.forEach { entry ->
|
||||
// ensureActive()
|
||||
// entry.value.await()?.let {
|
||||
// drawable.dynamicItem.setDynamicImage(it, entry.key)
|
||||
// }
|
||||
// }
|
||||
// textMap.forEach { entry ->
|
||||
// entry.value.text?.let {
|
||||
// drawable.dynamicItem.setDynamicText(it, entry.value.textPaint, entry.key)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// withContext(Dispatchers.Main) {
|
||||
// onAnimStart()
|
||||
// svgaImageView.setImageDrawable(drawable)
|
||||
// svgaImageView.startAnimation()
|
||||
// extMap = mutableMapOf()
|
||||
// glideRequests = mutableListOf()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fun into(animView: AnimView){
|
||||
// setup(animView)
|
||||
// val mp4Url = url
|
||||
// if(mp4Url.isNullOrBlank()){
|
||||
// listener?.onAnimError(RuntimeException("url is empty"))
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// animView.setFetchResource(this)
|
||||
//
|
||||
// if(!mp4Url.startsWith("http")){//没有http前缀就当成asset文件加载
|
||||
// onAnimStart()
|
||||
// animView.startPlay(animView.context.assets, mp4Url)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// if(scope == null){
|
||||
// scope = animView.findViewTreeLifecycleOwner()?.lifecycleScope
|
||||
// }
|
||||
// job = scope?.launch(Dispatchers.IO) {
|
||||
// Glide.with(animView.context)
|
||||
// .asFile()
|
||||
// .skipMemoryCache(skipMemoryCache)
|
||||
// .load(mp4Url)
|
||||
// .addListener(object : RequestListener<File> {
|
||||
// override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<File>, isFirstResource: Boolean): Boolean {
|
||||
// e?.logRootCauses("vap_loading_error")
|
||||
// animView.post {
|
||||
// onAnimError("vap loading error msg:${e?.message ?: "empty"}")
|
||||
// }
|
||||
// return true
|
||||
// }
|
||||
//
|
||||
// override fun onResourceReady(resource: File, model: Any, target: Target<File>?, dataSource: DataSource, isFirstResource: Boolean): Boolean {
|
||||
// return false
|
||||
// }
|
||||
// })
|
||||
// .submit()
|
||||
// .suspendGetOrNull()
|
||||
// ?.let {
|
||||
// withContext(Dispatchers.Main){
|
||||
// onAnimStart()
|
||||
// animView.startPlay(it)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private fun setup(view: View){
|
||||
// if(Looper.myLooper() != Looper.getMainLooper()){
|
||||
// throw Exception("must run on MAIN Thread current Thread ${Thread.currentThread().name}")
|
||||
// }
|
||||
// cancelJob()
|
||||
// extMap = mutableMapOf()
|
||||
// extMap.putAll(tempExtMap)
|
||||
// view.addOnAttachStateChangeListener(this)
|
||||
//
|
||||
// if(view is SVGAImageView){
|
||||
// if(!skipMemoryCache){
|
||||
// view.clearsAfterDetached = false
|
||||
// } else {
|
||||
// clearsAfterDetached?.let { view.clearsAfterDetached = it }
|
||||
// }
|
||||
// repeatCount?.let { view.loops = if(it <= 0) Int.MAX_VALUE else it }
|
||||
// scaleType?.let { view.scaleType = it }
|
||||
// view.callback = object: SimpleSvgaCallback(){
|
||||
// override fun onStep(frame: Int, percentage: Double) {
|
||||
// if (percentage == 1.0) {
|
||||
// view.post { onAnimComplete() }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }else if (view is AnimView){
|
||||
// repeatCount?.let { view.setLoop(if(it <= 0) Int.MAX_VALUE else it) }
|
||||
// scaleType?.let {
|
||||
// when (it) {
|
||||
// ImageView.ScaleType.FIT_XY -> {
|
||||
// view.setScaleType(ScaleType.FIT_XY)
|
||||
// }
|
||||
// ImageView.ScaleType.CENTER_CROP -> {
|
||||
// view.setScaleType(ScaleType.CENTER_CROP)
|
||||
// }
|
||||
// else -> {
|
||||
// view.setScaleType(ScaleType.FIT_CENTER)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// view.setAnimListener(object : SimpleVapCallback(){
|
||||
// override fun onFailed(errorType: Int, errorMsg: String?) {
|
||||
// view.post { onAnimError("vap errorType:${errorMsg} errorMsg:${errorMsg ?: "empty"}") }
|
||||
// }
|
||||
//
|
||||
// override fun onVideoComplete() {
|
||||
// view.post { onAnimComplete() }
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fun clear(){
|
||||
// tempExtMap = mutableMapOf()
|
||||
// extMap = mutableMapOf()
|
||||
// cancelJob()
|
||||
// }
|
||||
//
|
||||
// private fun cancelJob(){
|
||||
// try {
|
||||
// job?.cancel()
|
||||
// val imgRequests = glideRequests
|
||||
// glideRequests = mutableListOf()
|
||||
// imgRequests.forEach {
|
||||
// it?.cancel(true)
|
||||
// }
|
||||
// } catch (_: Exception) { }
|
||||
// }
|
||||
//
|
||||
// private fun onAnimStart() {
|
||||
// listener?.onAnimStart()
|
||||
// }
|
||||
//
|
||||
// private fun onAnimComplete() {
|
||||
// extMap = mutableMapOf()
|
||||
// glideRequests = mutableListOf()
|
||||
// listener?.onAnimComplete()
|
||||
// }
|
||||
//
|
||||
// private fun onAnimError(msg: String) {
|
||||
// extMap = mutableMapOf()
|
||||
// cancelJob()
|
||||
// listener?.onAnimError(Exception(msg))
|
||||
// }
|
||||
//
|
||||
// override fun fetchImage(resource: Resource, result: (Bitmap?) -> Unit) {
|
||||
// val ext = extMap[resource.tag]
|
||||
// result(ext?.getBitMap())
|
||||
// }
|
||||
//
|
||||
// override fun fetchText(resource: Resource, result: (String?) -> Unit) {
|
||||
// val ext = extMap[resource.tag]
|
||||
// result(ext?.text)
|
||||
// }
|
||||
//
|
||||
// override fun releaseResource(resources: List<Resource>) {
|
||||
// }
|
||||
//
|
||||
// private inner class Ext(
|
||||
// val text: String? = null,
|
||||
// val textPaint: TextPaint = defTextPaint,
|
||||
// val imgGetter: (() -> Bitmap?)? = null) {
|
||||
// fun getBitMap(): Bitmap? {
|
||||
// return try {
|
||||
// val bitmap = imgGetter?.invoke()
|
||||
// bitmap
|
||||
// } catch (t: Throwable) {
|
||||
// null
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fun isImg(): Boolean {
|
||||
// return text.isNullOrBlank()
|
||||
// }
|
||||
//
|
||||
// fun isText(): Boolean {
|
||||
// return !text.isNullOrBlank()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun onViewAttachedToWindow(v: View) {
|
||||
// }
|
||||
//
|
||||
// override fun onViewDetachedFromWindow(v: View) {
|
||||
// v.removeOnAttachStateChangeListener(this)
|
||||
// cancelJob()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// interface Listener {
|
||||
// fun onAnimStart() {}
|
||||
// fun onAnimComplete()
|
||||
// fun onAnimError(e: Exception?) {
|
||||
// onAnimComplete()
|
||||
// }
|
||||
// }
|
||||
//}
|
@@ -1376,6 +1376,28 @@ class GlideUtils {
|
||||
glideConfig?.downloadOnly()?.load(url)?.listener(listener)?.preload()
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用Glide下载图片,返回File
|
||||
*/
|
||||
fun downloadFromUrl2(
|
||||
context: Context?,
|
||||
url: String?,
|
||||
listener: RequestListener<File?>?
|
||||
) {
|
||||
if (context == null) {
|
||||
LibLogger.error(TAG, "load context is null")
|
||||
return
|
||||
}
|
||||
|
||||
val glideConfig = getGlideConfig(context)
|
||||
glideConfig
|
||||
?.asFile()
|
||||
?.skipMemoryCache(true)
|
||||
?.load(url)
|
||||
?.addListener(listener)
|
||||
?.submit()
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载图片,并添加RequestListener ,无占位图 ,listener需使用addListener方法添加
|
||||
*/
|
||||
@@ -1422,6 +1444,17 @@ class GlideUtils {
|
||||
.into(imageView)
|
||||
}
|
||||
}
|
||||
//加载图片,无默认图片
|
||||
fun loadAsBitmap(url: String?, imageView: ImageView?) {
|
||||
if (imageView == null || TextUtils.isEmpty(url)) {
|
||||
LibLogger.error(TAG, "load url is invalid or imageViw is null")
|
||||
return
|
||||
}
|
||||
getGlideConfig(imageView.context)?.apply {
|
||||
this.asDrawable().load(url)
|
||||
.into(imageView)
|
||||
}
|
||||
}
|
||||
|
||||
//加载图片,无默认图片
|
||||
fun loadWithError(url: String?, errorDrawable: Int, imageView: ImageView?) {
|
||||
|
@@ -8,6 +8,8 @@ import androidx.core.view.isVisible
|
||||
import com.chwl.library.utils.ResUtil
|
||||
import com.chwl.library.utils.SizeUtils
|
||||
import com.example.lib_utils.UiUtils.isRtl
|
||||
import com.example.lib_utils.ktx.getString
|
||||
import com.hjq.toast.ToastUtils
|
||||
|
||||
|
||||
fun View.setMargin(start:Int?=null,top:Int?=null,end:Int?=null,bottom:Int?=null,isDP:Boolean = true) {
|
||||
@@ -70,6 +72,32 @@ fun String?.isVerify() : Boolean {
|
||||
return this?.isBlank() == false
|
||||
}
|
||||
|
||||
fun String?.isSvgaUrl() : Boolean {
|
||||
if (this.isVerify()) {
|
||||
return this?.endsWith(".svga") == true || this?.endsWith(".SVGA") == true
|
||||
}
|
||||
return false
|
||||
}
|
||||
fun String?.isMp4() : Boolean {
|
||||
if (this.isVerify()) {
|
||||
return this?.endsWith(".mp4") == true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun String?.doToast() {
|
||||
if (this.isVerify()) {
|
||||
ToastUtils.show(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.doToast() {
|
||||
val string = this.getString()
|
||||
if (string.isVerify()) {
|
||||
ToastUtils.show(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun List<Any>?.isVerify() : Boolean{
|
||||
return this?.isEmpty() == false
|
||||
}
|
||||
|
@@ -74,11 +74,74 @@ class SpannableTextBuilder(private val textView: TextView) {
|
||||
textSize,
|
||||
textStyle,
|
||||
underline,
|
||||
null,
|
||||
clickListener
|
||||
)
|
||||
return this
|
||||
}
|
||||
|
||||
fun setTextStyle(
|
||||
text: String,
|
||||
@ColorInt textColor: Int? = null,
|
||||
@ColorInt backgroundColor: Int? = null,
|
||||
textSize: Int? = null,
|
||||
textStyle: Int? = null,
|
||||
underline: Boolean? = null,
|
||||
clickListener: ((String) -> Unit)? = null
|
||||
): SpannableTextBuilder {
|
||||
if (text.isEmpty()) {
|
||||
return this
|
||||
}
|
||||
val start = spannableBuilder.indexOf(text)
|
||||
if (start == -1) {
|
||||
return this
|
||||
}
|
||||
val end = start + text.length
|
||||
return setTextStyle(
|
||||
text,
|
||||
start,
|
||||
end,
|
||||
textColor,
|
||||
backgroundColor,
|
||||
textSize,
|
||||
textStyle,
|
||||
underline,
|
||||
null,
|
||||
clickListener
|
||||
)
|
||||
}
|
||||
fun setTextStyle(
|
||||
text: String,
|
||||
@ColorInt textColor: Int? = null,
|
||||
@ColorInt backgroundColor: Int? = null,
|
||||
textSize: Int? = null,
|
||||
textStyle: Int? = null,
|
||||
underline: Boolean? = null,
|
||||
delLine: Boolean? = null,
|
||||
clickListener: ((String) -> Unit)? = null
|
||||
): SpannableTextBuilder {
|
||||
if (text.isEmpty()) {
|
||||
return this
|
||||
}
|
||||
val start = spannableBuilder.indexOf(text)
|
||||
if (start == -1) {
|
||||
return this
|
||||
}
|
||||
val end = start + text.length
|
||||
return setTextStyle(
|
||||
text,
|
||||
start,
|
||||
end,
|
||||
textColor,
|
||||
backgroundColor,
|
||||
textSize,
|
||||
textStyle,
|
||||
underline,
|
||||
delLine,
|
||||
clickListener
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加图片
|
||||
* @param drawable 图片
|
||||
@@ -187,6 +250,7 @@ class SpannableTextBuilder(private val textView: TextView) {
|
||||
textSize: Int? = null,
|
||||
textStyle: Int? = null,
|
||||
underline: Boolean? = null,
|
||||
delLine: Boolean? = null,
|
||||
clickListener: ((String) -> Unit)? = null
|
||||
): SpannableTextBuilder {
|
||||
if (start < 0 || end > spannableBuilder.length) {
|
||||
@@ -236,6 +300,10 @@ class SpannableTextBuilder(private val textView: TextView) {
|
||||
if (underline == true) {
|
||||
spannableBuilder.setSpan(UnderlineSpan(), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
// 删除线
|
||||
if (delLine == true) {
|
||||
spannableBuilder.setSpan(StrikethroughSpan(), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
|
||||
// 点击事件
|
||||
if (clickListener != null) {
|
||||
@@ -251,35 +319,7 @@ class SpannableTextBuilder(private val textView: TextView) {
|
||||
return this
|
||||
}
|
||||
|
||||
fun setTextStyle(
|
||||
text: String,
|
||||
@ColorInt textColor: Int? = null,
|
||||
@ColorInt backgroundColor: Int? = null,
|
||||
textSize: Int? = null,
|
||||
textStyle: Int? = null,
|
||||
underline: Boolean? = null,
|
||||
clickListener: ((String) -> Unit)? = null
|
||||
): SpannableTextBuilder {
|
||||
if (text.isEmpty()) {
|
||||
return this
|
||||
}
|
||||
val start = spannableBuilder.indexOf(text)
|
||||
if (start == -1) {
|
||||
return this
|
||||
}
|
||||
val end = start + text.length
|
||||
return setTextStyle(
|
||||
text,
|
||||
start,
|
||||
end,
|
||||
textColor,
|
||||
backgroundColor,
|
||||
textSize,
|
||||
textStyle,
|
||||
underline,
|
||||
clickListener
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
fun build(): SpannableStringBuilder {
|
||||
return spannableBuilder
|
||||
|
279
mode.json
@@ -1,98 +1,181 @@
|
||||
[
|
||||
{
|
||||
"id": 359,
|
||||
"uid": 3224,
|
||||
"nameplateId": 101,
|
||||
"isCustomWord": false,
|
||||
"word": " ",
|
||||
"remark": " ",
|
||||
"expireTime": 1731998395000,
|
||||
"createTime": 1731047995000,
|
||||
"updateTime": 1731318342000,
|
||||
"nameplateName": "schoolgirl-Advanced",
|
||||
"nameplateImage": "https://image.pekolive.com/gonghuizhangmingpaikaobei.png",
|
||||
"expireDays": 0,
|
||||
"iconPic": "https://image.pekolive.com/gonghuizhangmingpaikaobei.png",
|
||||
"fixedWord": " ",
|
||||
"nameplateType": "1"
|
||||
},
|
||||
{
|
||||
"id": 371,
|
||||
"uid": 3224,
|
||||
"nameplateId": 96,
|
||||
"isCustomWord": false,
|
||||
"remark": " ",
|
||||
"expireTime": 1731143136000,
|
||||
"createTime": 1731056736000,
|
||||
"updateTime": 1731056736000,
|
||||
"nameplateName": "king",
|
||||
"nameplateImage": "https://image.pekolive.com/zu689(11).png",
|
||||
"expireDays": 0,
|
||||
"iconPic": "https://image.pekolive.com/zu689(11).png",
|
||||
"nameplateType": "1"
|
||||
},
|
||||
{
|
||||
"id": 369,
|
||||
"uid": 3224,
|
||||
"nameplateId": 100,
|
||||
"isCustomWord": false,
|
||||
"remark": " ",
|
||||
"expireTime": 1731143131000,
|
||||
"createTime": 1731056731000,
|
||||
"updateTime": 1731056731000,
|
||||
"nameplateName": "schoolgirl-Advanced",
|
||||
"nameplateImage": "https://image.pekolive.com/huayunu:shen.png",
|
||||
"expireDays": 0,
|
||||
"iconPic": "https://image.pekolive.com/guanfangzhuli-bajisitan.png",
|
||||
"nameplateType": "1"
|
||||
},
|
||||
{
|
||||
"id": 367,
|
||||
"uid": 3224,
|
||||
"nameplateId": 93,
|
||||
"isCustomWord": false,
|
||||
"remark": " ",
|
||||
"expireTime": 1731143124000,
|
||||
"createTime": 1731056724000,
|
||||
"updateTime": 1731056724000,
|
||||
"nameplateName": "queen",
|
||||
"nameplateImage": "https://image.pekolive.com/zu688(3).png",
|
||||
"expireDays": 0,
|
||||
"iconPic": "https://image.pekolive.com/zu688(3).png",
|
||||
"nameplateType": "1"
|
||||
},
|
||||
{
|
||||
"id": 365,
|
||||
"uid": 3224,
|
||||
"nameplateId": 92,
|
||||
"isCustomWord": true,
|
||||
"word": " العناوين",
|
||||
"remark": " العناوين",
|
||||
"expireTime": 1731143086000,
|
||||
"createTime": 1731056686000,
|
||||
"updateTime": 1731056686000,
|
||||
"nameplateName": "給糖不搗蛋",
|
||||
"nameplateImage": "https://image.pekolive.com/8350643695e74ec9bb78b9944fc9e842.png",
|
||||
"expireDays": 0,
|
||||
"iconPic": "https://image.pekolive.com/zu689(5).png",
|
||||
"fixedWord": "العناوين",
|
||||
"nameplateType": "1"
|
||||
},
|
||||
{
|
||||
"id": 124,
|
||||
"uid": 3224,
|
||||
"nameplateId": 101,
|
||||
"isCustomWord": false,
|
||||
"word": " ",
|
||||
"remark": " ",
|
||||
"expireTime": 1729340700000,
|
||||
"createTime": 1728476700000,
|
||||
"updateTime": 1731318342000,
|
||||
"nameplateName": "schoolgirl-Advanced",
|
||||
"nameplateImage": "https://image.pekolive.com/gonghuizhangmingpaikaobei.png",
|
||||
"expireDays": 0,
|
||||
"iconPic": "https://image.pekolive.com/gonghuizhangmingpaikaobei.png",
|
||||
"fixedWord": " ",
|
||||
"nameplateType": "1"
|
||||
}
|
||||
]
|
||||
{
|
||||
"success": true,
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": [
|
||||
{
|
||||
"dressId": 195,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "https://image.pekolive.com/Vip5headdress.png",
|
||||
"effectType": 2,
|
||||
"effect": "https://image.pekolive.com/Vip5headdress.svga",
|
||||
"name": "VIP5頭飾",
|
||||
"used": true,
|
||||
"expireDays": 22,
|
||||
"hasExpired": false,
|
||||
"expireTime": 1733976000000
|
||||
},
|
||||
{
|
||||
"dressId": 196,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "https://image.pekolive.com/Vip6headdress.png",
|
||||
"effectType": 2,
|
||||
"effect": "https://image.pekolive.com/Vip6headdress.svga",
|
||||
"name": "VIP6頭飾",
|
||||
"used": false,
|
||||
"expireDays": 25,
|
||||
"hasExpired": false,
|
||||
"expireTime": 1734235200000
|
||||
},
|
||||
{
|
||||
"dressId": 193,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "https://image.pekolive.com/Vip3headdress.png",
|
||||
"effectType": 2,
|
||||
"effect": "https://image.pekolive.com/Vip3headdress.svga",
|
||||
"name": "VIP3頭飾",
|
||||
"used": false,
|
||||
"expireDays": 23,
|
||||
"hasExpired": false,
|
||||
"expireTime": 1734062400000
|
||||
},
|
||||
{
|
||||
"dressId": 26,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "https://image.hfighting.com/1df2071a-610d-41be-b763-8437ef9f3524",
|
||||
"effectType": 2,
|
||||
"effect": "https://image.hfighting.com/6d9ff134-80c1-44d5-97b0-981817e03bd4",
|
||||
"name": "幸運星人",
|
||||
"used": false,
|
||||
"expireDays": 22,
|
||||
"hasExpired": false,
|
||||
"expireTime": 1733919509000
|
||||
},
|
||||
{
|
||||
"dressId": 31,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "https://image.hfighting.com/2ec2f8cd-e660-4af2-bd49-b9eed8de10a2",
|
||||
"effectType": 2,
|
||||
"effect": "https://image.hfighting.com/34369437-e9a3-4bb8-80a2-f310bf8e90fc",
|
||||
"name": "財氣沖天",
|
||||
"used": false,
|
||||
"expireDays": 13,
|
||||
"hasExpired": false,
|
||||
"expireTime": 1733173500000
|
||||
},
|
||||
{
|
||||
"dressId": 27,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "https://image.hfighting.com/06fe0618-cd55-4e5e-84bf-1071f821d608",
|
||||
"effectType": 2,
|
||||
"effect": "https://image.hfighting.com/22f0fbb1-fdb1-46f9-b037-03f0693effeb",
|
||||
"name": "潮舞星迎",
|
||||
"used": false,
|
||||
"expireDays": 13,
|
||||
"hasExpired": false,
|
||||
"expireTime": 1733131248000
|
||||
},
|
||||
{
|
||||
"dressId": 123,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "http://beta.img.pekolive.com/FklHnzcmijfk_0QGRePXuzG3LSdN?imageslim",
|
||||
"effectType": 2,
|
||||
"effect": "http://beta.img.pekolive.com/FmDgjyKd_p0SvpKmC5v0rwhszdH9?imageslim",
|
||||
"name": "花语小兔",
|
||||
"used": false,
|
||||
"expireDays": 9,
|
||||
"hasExpired": false,
|
||||
"expireTime": 1732780728000
|
||||
},
|
||||
{
|
||||
"dressId": 110,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "http://beta.img.pekolive.com/FrTtFcnSI88bITGonp5PJjdbGLLR?imageslim",
|
||||
"effectType": 2,
|
||||
"effect": "http://beta.img.pekolive.com/FrTtFcnSI88bITGonp5PJjdbGLLR?imageslim",
|
||||
"name": "豪氣季軍",
|
||||
"used": false,
|
||||
"expireDays": 8,
|
||||
"hasExpired": false,
|
||||
"expireTime": 1732760886000
|
||||
},
|
||||
{
|
||||
"dressId": 30,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "https://image.hfighting.com/0fcea959-e82a-410e-a3f5-52f751a6c327",
|
||||
"effectType": 2,
|
||||
"effect": "https://image.hfighting.com/efacf269-c628-4940-984f-b817aabf2127",
|
||||
"name": "拉丁之神",
|
||||
"used": false,
|
||||
"expireDays": 6,
|
||||
"hasExpired": false,
|
||||
"expireTime": 1732526621000
|
||||
},
|
||||
{
|
||||
"dressId": 28,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "https://image.hfighting.com/4dd02f23-e30f-4df7-9326-53a1f4ae8ebf",
|
||||
"effectType": 2,
|
||||
"effect": "https://image.hfighting.com/c17f08d6-1854-4d03-a760-e02ad5fdf081",
|
||||
"name": "月魔法帽",
|
||||
"used": false,
|
||||
"expireDays": 6,
|
||||
"hasExpired": false,
|
||||
"expireTime": 1732526452000
|
||||
},
|
||||
{
|
||||
"dressId": 42,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "http://beta.img.pekolive.com/Fq_EzPCxN99nV84CgO3c3z242pEh?imageslim",
|
||||
"effectType": 2,
|
||||
"effect": "http://beta.img.pekolive.com/Fq_EzPCxN99nV84CgO3c3z242pEh?imageslim",
|
||||
"name": "海浪",
|
||||
"used": false,
|
||||
"expireDays": 2,
|
||||
"hasExpired": false,
|
||||
"expireTime": 1732175930000
|
||||
},
|
||||
{
|
||||
"dressId": 29,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "https://image.hfighting.com/a51c4b19-6862-41fa-83cb-2475db2320da",
|
||||
"effectType": 2,
|
||||
"effect": "https://image.hfighting.com/5df51843-1c4c-40c1-b1dd-5420ce093de2",
|
||||
"name": "神囚魔法",
|
||||
"used": false,
|
||||
"expireDays": 1,
|
||||
"hasExpired": false,
|
||||
"expireTime": 1732097432000
|
||||
},
|
||||
{
|
||||
"dressId": 102,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "http://beta.img.pekolive.com/FrQQrQ0yEhTCLxyKHygT76kZLHoy?imageslim",
|
||||
"effectType": 2,
|
||||
"effect": "http://beta.img.pekolive.com/FqJrMr8YmRr6WBR0FOMaYL05HPxy?imageslim",
|
||||
"name": "星河白羽",
|
||||
"used": false,
|
||||
"expireDays": 0,
|
||||
"hasExpired": true,
|
||||
"expireTime": 1731664948000
|
||||
},
|
||||
{
|
||||
"dressId": 44,
|
||||
"dressType": 0,
|
||||
"obtainWay": 1,
|
||||
"pic": "https://image.hfighting.com/bb55be24-3418-4f03-bf46-1bb491b95ba2",
|
||||
"effectType": 2,
|
||||
"effect": "https:/
|
||||
|
@@ -31,11 +31,12 @@ import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
import com.netease.nim.uikit.R;
|
||||
|
||||
public class CircleImageView extends ImageView {
|
||||
public class CircleImageView extends AppCompatImageView {
|
||||
|
||||
private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
|
||||
|
||||
|