SurfaceView动画+小手动画
状态流转
@@ -1,6 +0,0 @@
|
||||
package com.mogo.och.taxi.passenger.callback;
|
||||
|
||||
public interface ITaxiPassengerCheckPhoneCallback {
|
||||
//验证手机号并流转状态
|
||||
void onCheckPhoneAndUpdateOrderStatus(String phoneTail);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.mogo.och.taxi.passenger.callback;
|
||||
|
||||
public interface ITaxiPassengerScoreCallback {
|
||||
void onScoreCallback(int fraction,String orderNo);
|
||||
}
|
||||
@@ -702,11 +702,10 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback
|
||||
});
|
||||
}
|
||||
|
||||
public void arrivedAndScore(int score, ITaxiPassengerCommonValueCallback<Boolean> commonCallback) {
|
||||
if (mCurrentOCHOrder == null) return;
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "--route--- checkPhoneAndUpdateStatus");
|
||||
TaxiPassengerServiceManager.getInstance().arrivedAndScore(mContext,mCurrentOCHOrder.orderNo,
|
||||
score, new TaxiPassengerServiceCallback<TaxiPassengerBaseRespBean>() {
|
||||
public void arrivedAndScore(int score,String orderNo ,ITaxiPassengerCommonValueCallback<Boolean> commonCallback) {
|
||||
if (orderNo == null) return;
|
||||
TaxiPassengerServiceManager.getInstance().arrivedAndScore(mContext,orderNo,score,
|
||||
new TaxiPassengerServiceCallback<TaxiPassengerBaseRespBean>() {
|
||||
@Override
|
||||
public void onSuccess(TaxiPassengerBaseRespBean data) {
|
||||
ToastUtils.showLong("评分成功");
|
||||
|
||||
@@ -123,7 +123,7 @@ public class BaseTaxiPassengerPresenter extends Presenter<TaxiPassengerBaseFragm
|
||||
|
||||
@Override
|
||||
public void onCurrentOrderStatusChanged(TaxiPassengerOrderQueryRespBean.Result order) {
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P + TAG, GsonUtil.jsonFromObject(order));
|
||||
// CallerLogger.INSTANCE.d(M_TAXI_P + TAG, GsonUtil.jsonFromObject(order));
|
||||
if (mCurrentPassengerOrder == null){
|
||||
mCurrentPassengerOrder = order; //当前无订单
|
||||
updateOrderView(order);
|
||||
@@ -145,43 +145,45 @@ public class BaseTaxiPassengerPresenter extends Presenter<TaxiPassengerBaseFragm
|
||||
|
||||
private void updateOrderView(TaxiPassengerOrderQueryRespBean.Result order) {
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P+TAG,"updateOrderView = "+order.orderStatus);
|
||||
// 70 取消订单
|
||||
if (TaxiPassengerOrderStatusEnum.Cancel.getCode() == order.orderStatus){
|
||||
runOnUIThread(() -> {
|
||||
mView.showOrHideServingOrderFragment(false);
|
||||
mView.showOrHidePressengerCheckPager(false, "",
|
||||
"", "", "", "");
|
||||
mView.showOrHideArrivedEndLayout(false,"");
|
||||
mView.showOrHideArrivedEndLayout(false,"","");
|
||||
});
|
||||
TaxiPassengerModel.getInstance().recoverNaviInfo();
|
||||
TaxiPassengerGeocodeSearchModel.getInstance(getContext()).destroyGeocodeSearch();
|
||||
return;
|
||||
}
|
||||
// 20 司机到达上车点
|
||||
if (TaxiPassengerOrderStatusEnum.ArriveAtStart.getCode() == order.orderStatus) {
|
||||
runOnUIThread(() -> {
|
||||
mView.showOrHideArrivedEndLayout(false, "");
|
||||
mView.showOrHidePressengerCheckPager(true, order.startSiteAddr,
|
||||
mView.preOrderThankPageTenlogic(order.startSiteAddr,
|
||||
order.endSiteAddr, order.passengerNum, order.carNumber, order.passengerPhone);
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 30 用户到达上车点 并通过了手机号后四位验证
|
||||
// 40 服务中
|
||||
if (TaxiPassengerOrderStatusEnum.UserArriveAtStart.getCode() == order.orderStatus
|
||||
|| TaxiPassengerOrderStatusEnum.OnTheWayToEnd.getCode() == order.orderStatus){
|
||||
runOnUIThread(() -> mView.showOrHideServingOrderFragment(true));
|
||||
return;
|
||||
}
|
||||
// 50 到达终点 乘客可以评价
|
||||
if (TaxiPassengerOrderStatusEnum.ArriveAtEnd.getCode() == order.orderStatus){
|
||||
TaxiPassengerModel.getInstance().recoverNaviInfo();
|
||||
TaxiPassengerGeocodeSearchModel.getInstance(getContext()).destroyGeocodeSearch();
|
||||
runOnUIThread(() -> {
|
||||
mView.showOrHideServingOrderFragment(false);
|
||||
mView.showOrHideArrivedEndLayout(true, order.endSiteAddr);
|
||||
mView.showOrHideArrivedEndLayout(true, order.endSiteAddr,order.orderNo);
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 60 服务完成 页面
|
||||
if (TaxiPassengerOrderStatusEnum.JourneyCompleted.getCode() == order.orderStatus){
|
||||
runOnUIThread(() -> {
|
||||
mView.showOrHideServingOrderFragment(false);
|
||||
});
|
||||
TaxiPassengerGeocodeSearchModel.getInstance(getContext()).destroyGeocodeSearch();
|
||||
mCurrentPassengerOrder = null;
|
||||
return;
|
||||
@@ -201,14 +203,8 @@ public class BaseTaxiPassengerPresenter extends Presenter<TaxiPassengerBaseFragm
|
||||
*
|
||||
* @param score 分数
|
||||
*/
|
||||
public void arrivedAndScore(int score){
|
||||
TaxiPassengerModel.getInstance().arrivedAndScore(score, new ITaxiPassengerCommonValueCallback<Boolean>() {
|
||||
|
||||
@Override
|
||||
public void onCommonCallback(Boolean aBoolean) {
|
||||
mView.showArrivedEndLayout2Thank(aBoolean);
|
||||
}
|
||||
});
|
||||
public void arrivedAndScore(int score,String orderNo){
|
||||
TaxiPassengerModel.getInstance().arrivedAndScore(score,orderNo, aBoolean -> mView.showArrivedEndLayout2Thank(aBoolean));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.mogo.och.taxi.passenger.ui
|
||||
|
||||
import android.animation.*
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.AnimationDrawable
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@@ -13,9 +14,17 @@ import android.widget.TextView
|
||||
import com.amap.api.navi.view.PoiInputSearchWidget
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
|
||||
import com.mogo.eagle.core.utilcode.util.OverlayViewUtils
|
||||
import com.mogo.och.common.module.wigets.OCHBorderShadowLayout
|
||||
import com.mogo.och.taxi.passenger.R
|
||||
import com.mogo.och.taxi.passenger.callback.ITaxiPassengerCommonValueCallback
|
||||
import com.mogo.och.taxi.passenger.callback.ITaxiPassengerCommonCallback
|
||||
import com.mogo.och.taxi.passenger.callback.ITaxiPassengerScoreCallback
|
||||
import com.mogo.och.taxi.passenger.utils.view.FrameSurfaceView
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -41,12 +50,113 @@ class TaxiPassengerArrivedView :RelativeLayout, View.OnClickListener {
|
||||
private lateinit var ivStarThird: ImageView
|
||||
private lateinit var ivStarFourth: ImageView
|
||||
private lateinit var ivStarFifth: ImageView
|
||||
private lateinit var ivAnimalList: ImageView
|
||||
private lateinit var svFrame: FrameSurfaceView
|
||||
private var subscribe: Disposable?=null
|
||||
private var orderNo = ""
|
||||
|
||||
var taxiPassengerCommonValueCallback: ITaxiPassengerCommonValueCallback<Int>?=null
|
||||
var trAnimation: Animation = AnimationUtils.loadAnimation(
|
||||
var right_res_id = arrayListOf<Int>(
|
||||
R.drawable.tail_ani_0000,
|
||||
R.drawable.tail_ani_0001,
|
||||
R.drawable.tail_ani_0002,
|
||||
R.drawable.tail_ani_0003,
|
||||
R.drawable.tail_ani_0004,
|
||||
R.drawable.tail_ani_0005,
|
||||
R.drawable.tail_ani_0006,
|
||||
R.drawable.tail_ani_0007,
|
||||
R.drawable.tail_ani_0008,
|
||||
R.drawable.tail_ani_0009,
|
||||
R.drawable.tail_ani_0010,
|
||||
R.drawable.tail_ani_0011,
|
||||
R.drawable.tail_ani_0012,
|
||||
R.drawable.tail_ani_0013,
|
||||
R.drawable.tail_ani_0014,
|
||||
R.drawable.tail_ani_0015,
|
||||
R.drawable.tail_ani_0016,
|
||||
R.drawable.tail_ani_0017,
|
||||
R.drawable.tail_ani_0018,
|
||||
R.drawable.tail_ani_0019,
|
||||
R.drawable.tail_ani_0020,
|
||||
R.drawable.tail_ani_0021,
|
||||
R.drawable.tail_ani_0022,
|
||||
R.drawable.tail_ani_0023,
|
||||
R.drawable.tail_ani_0024,
|
||||
R.drawable.tail_ani_0025,
|
||||
R.drawable.tail_ani_0026,
|
||||
R.drawable.tail_ani_0027,
|
||||
R.drawable.tail_ani_0028,
|
||||
R.drawable.tail_ani_0029,
|
||||
R.drawable.tail_ani_0030,
|
||||
R.drawable.tail_ani_0031,
|
||||
R.drawable.tail_ani_0032,
|
||||
R.drawable.tail_ani_0033,
|
||||
R.drawable.tail_ani_0034,
|
||||
R.drawable.tail_ani_0035,
|
||||
R.drawable.tail_ani_0036,
|
||||
R.drawable.tail_ani_0037,
|
||||
R.drawable.tail_ani_0038,
|
||||
R.drawable.tail_ani_0039,
|
||||
R.drawable.tail_ani_0040,
|
||||
R.drawable.tail_ani_0041,
|
||||
R.drawable.tail_ani_0042,
|
||||
R.drawable.tail_ani_0043,
|
||||
R.drawable.tail_ani_0044,
|
||||
R.drawable.tail_ani_0045,
|
||||
R.drawable.tail_ani_0046,
|
||||
R.drawable.tail_ani_0047,
|
||||
R.drawable.tail_ani_0048,
|
||||
R.drawable.tail_ani_0049,
|
||||
R.drawable.tail_ani_0050,
|
||||
R.drawable.tail_ani_0051,
|
||||
R.drawable.tail_ani_0052,
|
||||
R.drawable.tail_ani_0053,
|
||||
R.drawable.tail_ani_0054,
|
||||
R.drawable.tail_ani_0055,
|
||||
R.drawable.tail_ani_0056,
|
||||
R.drawable.tail_ani_0057,
|
||||
R.drawable.tail_ani_0058,
|
||||
R.drawable.tail_ani_0059,
|
||||
R.drawable.tail_ani_0060,
|
||||
R.drawable.tail_ani_0061,
|
||||
R.drawable.tail_ani_0062,
|
||||
R.drawable.tail_ani_0063,
|
||||
R.drawable.tail_ani_0064,
|
||||
R.drawable.tail_ani_0065,
|
||||
R.drawable.tail_ani_0066,
|
||||
R.drawable.tail_ani_0067,
|
||||
R.drawable.tail_ani_0068,
|
||||
R.drawable.tail_ani_0069,
|
||||
R.drawable.tail_ani_0070,
|
||||
R.drawable.tail_ani_0071,
|
||||
R.drawable.tail_ani_0072,
|
||||
R.drawable.tail_ani_0073,
|
||||
R.drawable.tail_ani_0074,
|
||||
R.drawable.tail_ani_0075,
|
||||
R.drawable.tail_ani_0076,
|
||||
R.drawable.tail_ani_0077,
|
||||
R.drawable.tail_ani_0078,
|
||||
R.drawable.tail_ani_0079,
|
||||
R.drawable.tail_ani_0080,
|
||||
R.drawable.tail_ani_0081,
|
||||
R.drawable.tail_ani_0082,
|
||||
R.drawable.tail_ani_0083,
|
||||
R.drawable.tail_ani_0084,
|
||||
R.drawable.tail_ani_0085,
|
||||
R.drawable.tail_ani_0086,
|
||||
R.drawable.tail_ani_0087,
|
||||
R.drawable.tail_ani_0088,
|
||||
R.drawable.tail_ani_0089,
|
||||
R.drawable.tail_ani_0090
|
||||
)
|
||||
|
||||
|
||||
var iTaxiPassengerScoreCallback: ITaxiPassengerScoreCallback?=null
|
||||
@Volatile
|
||||
var taxiPassengerCommonCallback: ITaxiPassengerCommonCallback?=null
|
||||
var left2Right: Animation = AnimationUtils.loadAnimation(
|
||||
context, R.anim.left_to_right
|
||||
)
|
||||
var troutAnimation: Animation = AnimationUtils.loadAnimation(
|
||||
var right2Left: Animation = AnimationUtils.loadAnimation(
|
||||
context, R.anim.right_to_left
|
||||
)
|
||||
var alphaAnimation: Animation = AnimationUtils.loadAnimation(
|
||||
@@ -55,6 +165,9 @@ class TaxiPassengerArrivedView :RelativeLayout, View.OnClickListener {
|
||||
|
||||
private var allStartOrdered = mutableListOf<ImageView>()
|
||||
|
||||
var show: Boolean = false
|
||||
var showThanks:Boolean = false
|
||||
|
||||
private fun initView(context: Context) {
|
||||
d(SceneConstant.M_TAXI_P + TAG, "initView")
|
||||
LayoutInflater.from(context).inflate(R.layout.taxi_p_arrived_end_panel, this, true)
|
||||
@@ -62,15 +175,20 @@ class TaxiPassengerArrivedView :RelativeLayout, View.OnClickListener {
|
||||
tvFeel = findViewById(R.id.tv_feel)
|
||||
ochShadowLayout = findViewById(R.id.och_shadow_layout)
|
||||
ochThankShadowLayout = findViewById(R.id.och_thank_shadow_layout)
|
||||
ivAnimalList = findViewById(R.id.iv_animal_list)
|
||||
svFrame = findViewById(R.id.sv_frame)
|
||||
|
||||
allStartOrdered = mutableListOf<ImageView>()
|
||||
allStartOrdered = mutableListOf()
|
||||
initScore()
|
||||
|
||||
findViewById<View>(R.id.tv_please_score).setOnClickListener(this)
|
||||
|
||||
svFrame.setBitmapIds(right_res_id)
|
||||
svFrame.setDuration(2000)
|
||||
|
||||
// debug 弹出
|
||||
mArrivedEndStation.setOnLongClickListener {
|
||||
showThanksPageWithAnimation(true)
|
||||
scoreSuccess()
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -94,10 +212,25 @@ class TaxiPassengerArrivedView :RelativeLayout, View.OnClickListener {
|
||||
allStartOrdered.add(ivStarFifth)
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
show = true
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
show = false
|
||||
subscribe?.let {
|
||||
if (!it.isDisposed) {
|
||||
it.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(v: View?) {
|
||||
when (v?.id) {
|
||||
R.id.tv_please_score -> {
|
||||
taxiPassengerCommonValueCallback?.onCommonCallback(2)
|
||||
iTaxiPassengerScoreCallback?.onScoreCallback(2,orderNo)
|
||||
}
|
||||
R.id.iv_star_first -> {commitAndStartAnimation(1,"不满意")}
|
||||
R.id.iv_star_second -> {commitAndStartAnimation(2,"不满意")}
|
||||
@@ -127,6 +260,9 @@ class TaxiPassengerArrivedView :RelativeLayout, View.OnClickListener {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 星星动画
|
||||
*/
|
||||
private fun animation(fraction: Int) {
|
||||
|
||||
val showView = allStartOrdered[currentAnimarion]
|
||||
@@ -171,42 +307,88 @@ class TaxiPassengerArrivedView :RelativeLayout, View.OnClickListener {
|
||||
set.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
super.onAnimationEnd(animation)
|
||||
taxiPassengerCommonValueCallback?.onCommonCallback(fraction)
|
||||
iTaxiPassengerScoreCallback?.onScoreCallback(fraction,orderNo)
|
||||
}
|
||||
})
|
||||
}
|
||||
set.start()
|
||||
}
|
||||
|
||||
|
||||
fun setDataAndStartAnimation(endSiteAddr: String?) {
|
||||
/**
|
||||
* 设置目的地重置星星状态
|
||||
*/
|
||||
fun setDataAndStartAnimation(endSiteAddr: String?,orderId:String) {
|
||||
mArrivedEndStation.text = endSiteAddr
|
||||
ochShadowLayout.startAnimation(trAnimation)
|
||||
ochThankShadowLayout.visibility = View.GONE
|
||||
ivAnimalList.visibility = View.GONE
|
||||
|
||||
//play frame animation by FrameSurfaceView which is much more memory-efficient than AnimationDrawable
|
||||
svFrame.setRepeatTimes(0)
|
||||
svFrame.setFrameFinishCallback {
|
||||
ochShadowLayout.visibility = View.VISIBLE
|
||||
svFrame.setBackgroundResource(R.drawable.tail_ani_0090)
|
||||
ochShadowLayout.startAnimation(left2Right)
|
||||
}
|
||||
svFrame.start()
|
||||
|
||||
showThanks = false
|
||||
this.orderNo = orderId
|
||||
resetStar()
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论成功 向左移动并消失 消失后感谢页面透明度0-1 然后开始小手的动画
|
||||
*/
|
||||
fun scoreSuccess(){
|
||||
right2Left.setAnimationListener(object :PoiInputSearchWidget.AnimationListenerAdapter(){
|
||||
override fun onAnimationEnd(p0: Animation?) {
|
||||
ochShadowLayout.visibility = View.GONE
|
||||
ochThankShadowLayout.startAnimation(alphaAnimation)
|
||||
alphaAnimation.setAnimationListener(object : PoiInputSearchWidget.AnimationListenerAdapter(){
|
||||
override fun onAnimationStart(p0: Animation?) {
|
||||
ochThankShadowLayout.visibility = View.VISIBLE
|
||||
showThanks = true
|
||||
}
|
||||
override fun onAnimationEnd(p0: Animation?) {
|
||||
ivAnimalList.visibility = View.VISIBLE
|
||||
val animationDrawable = ivAnimalList.drawable as AnimationDrawable
|
||||
animationDrawable.start()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
ochShadowLayout.startAnimation(right2Left)
|
||||
|
||||
// 10s 后逻辑
|
||||
subscribe = Observable.timer(10000, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
// 正在展示感谢页面
|
||||
if (taxiPassengerCommonCallback == null) {
|
||||
// 没有用户确定页面
|
||||
OverlayViewUtils.dismissOverlayView(this@TaxiPassengerArrivedView)
|
||||
} else {
|
||||
// 有排队展示的用户确定页面
|
||||
taxiPassengerCommonCallback?.onCommonCallback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论失败 重置状态
|
||||
*/
|
||||
fun scoreFail(){
|
||||
tvFeel.text = ""
|
||||
resetStar()
|
||||
}
|
||||
|
||||
private fun resetStar() {
|
||||
allStartOrdered.forEach {
|
||||
it.setImageResource(R.drawable.taxi_p_passenger_star)
|
||||
it.isEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
fun showThanksPageWithAnimation(isSuccess:Boolean) {
|
||||
if(!isSuccess){
|
||||
tvFeel.text = ""
|
||||
allStartOrdered.forEach {
|
||||
it.setImageResource(R.drawable.taxi_p_passenger_star)
|
||||
it.isEnabled = true
|
||||
}
|
||||
return
|
||||
}
|
||||
troutAnimation.setAnimationListener(object :PoiInputSearchWidget.AnimationListenerAdapter(){
|
||||
override fun onAnimationEnd(p0: Animation?) {
|
||||
ochShadowLayout.visibility = View.GONE
|
||||
ochThankShadowLayout.startAnimation(alphaAnimation)
|
||||
ochThankShadowLayout.visibility = View.VISIBLE
|
||||
}
|
||||
})
|
||||
ochShadowLayout.startAnimation(troutAnimation)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "TaxiPassengerArrivedView"
|
||||
}
|
||||
|
||||
@@ -78,9 +78,6 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
mV2XNotificationView = new TaxiPassengerV2XNotificationView(getContext());
|
||||
CallerHmiManager.INSTANCE.setProxyNotificationView(mV2XNotificationView);
|
||||
|
||||
initArrivedView();
|
||||
initCheckView();
|
||||
|
||||
mMapswitchBtn = findViewById(R.id.module_och_taxi_swich_map_iv);
|
||||
initListener();
|
||||
|
||||
@@ -110,15 +107,11 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
});
|
||||
|
||||
findViewById(R.id.iv_temp).setOnLongClickListener(new View.OnLongClickListener() {
|
||||
int i = 0;
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if(i%2==0){
|
||||
showOrHideArrivedEndLayout(true,"北京北京北京");
|
||||
}else {
|
||||
showOrHidePressengerCheckPager(true, "开始站点开", "开始站点开始站点开始", "2", "京A888888", "18811539480");
|
||||
}
|
||||
i++;
|
||||
//showOrHideArrivedEndLayout(true, "北京北京北京", "1527481606997577728");
|
||||
//showOrHidePressengerCheckPager(true, "开始站点开", "开始站点开始站点开始", "2", "京A888888", "18811539480");
|
||||
//CallerHmiManager.INSTANCE.showToolsView();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
@@ -126,12 +119,12 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
|
||||
private void initArrivedView(){
|
||||
mArrivedEndView = new WeakReference<>(new TaxiPassengerArrivedView(getContext()));
|
||||
mArrivedEndView.get().setTaxiPassengerCommonValueCallback(integer -> getPresenter().arrivedAndScore(integer));
|
||||
mArrivedEndView.get().setITaxiPassengerScoreCallback((fraction, orderNo) -> getPresenter().arrivedAndScore(fraction,orderNo));
|
||||
}
|
||||
|
||||
private void initCheckView() {
|
||||
mArrivedCheckView = new WeakReference<>(new TaxiPassengerCheckView(getContext()));
|
||||
mArrivedCheckView.get().setOnCheckPhoneAndUpdateStatusListener(phoneTail -> getPresenter().checkAndUpdateStatus(phoneTail));
|
||||
mArrivedCheckView.get().setITaxiPassengerCommonValueCallback(phoneTail -> getPresenter().checkAndUpdateStatus(phoneTail));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,8 +208,6 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
}, 1000L);
|
||||
}
|
||||
|
||||
private boolean isStarting = false;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected BaseTaxiPassengerPresenter createPresenter() {
|
||||
@@ -267,20 +258,63 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
|
||||
/**
|
||||
* 显示或者隐藏到达乘客站点的洁面
|
||||
* @param isShow
|
||||
* ① 取消订单 可有可无
|
||||
* ② 到达上车点 隐藏到达终点的页面(上一个订单没有评价)
|
||||
* ③ 到达目的地 显示到达终点的页面
|
||||
* ④ debug 使用
|
||||
* @param isShow true 展示 false 隐藏
|
||||
* @param arrivedEndStation 目的地
|
||||
* @param orderNo 订单No
|
||||
*/
|
||||
public void showOrHideArrivedEndLayout(boolean isShow, String arrivedEndStation){
|
||||
public void showOrHideArrivedEndLayout(boolean isShow, String arrivedEndStation,String orderNo){
|
||||
if (isShow){
|
||||
if(mArrivedEndView.get()==null){
|
||||
if(mArrivedEndView==null||mArrivedEndView.get()==null){
|
||||
initArrivedView();
|
||||
}
|
||||
OverlayViewUtils.showOverlayView(getActivity(),mArrivedEndView.get(), R.style.och_window_anim_alpha);
|
||||
mArrivedEndView.get().setDataAndStartAnimation(arrivedEndStation);
|
||||
OverlayViewUtils.showOverlayView(getActivity(),mArrivedEndView.get());
|
||||
mArrivedEndView.get().setDataAndStartAnimation(arrivedEndStation,orderNo);
|
||||
}else {
|
||||
OverlayViewUtils.dismissOverlayView(mArrivedEndView.get());
|
||||
}
|
||||
}
|
||||
// 20 司机到达上车点
|
||||
// 展示:① 没有在展示打分用、感谢页面 用户手机号验证页面
|
||||
// ② 正在展示打分页面 关闭打分页面展示用户手机号验证页面 eg:上一个用户正在打分中 出现错乱
|
||||
// 正在展示感谢页面 等待感谢页面展示够10s后 关闭感谢页面展示 用户手机号验证页面
|
||||
public void preOrderThankPageTenlogic(String startSiteAddr,
|
||||
String endSiteAddr,
|
||||
String passengerNum,
|
||||
String carNumber,
|
||||
String phone){
|
||||
if(mArrivedEndView.get()==null||!mArrivedEndView.get().getShow()){
|
||||
showOrHidePressengerCheckPager(true, startSiteAddr,
|
||||
endSiteAddr, passengerNum, carNumber, phone);
|
||||
}else {
|
||||
if (mArrivedEndView.get().getShowThanks()) {
|
||||
// 正在展示感谢页面
|
||||
mArrivedEndView.get().setTaxiPassengerCommonCallback(() -> {
|
||||
showOrHideArrivedEndLayout(false, "","");
|
||||
showOrHidePressengerCheckPager(true, startSiteAddr,
|
||||
endSiteAddr, passengerNum, carNumber, phone);
|
||||
mArrivedEndView.get().setTaxiPassengerCommonCallback(null);
|
||||
});
|
||||
}else {
|
||||
// 正在展示打分页面
|
||||
showOrHideArrivedEndLayout(false, "","");
|
||||
showOrHidePressengerCheckPager(true, startSiteAddr,
|
||||
endSiteAddr, passengerNum, carNumber, phone);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* ① 取消订单 到达上车点后乘客取消订单 隐藏乘客验证页面
|
||||
* ② 司机到达上车点 到达上车点 展示乘客验证页面
|
||||
* ③ 乘客到达上车点 手机号验证成功后 隐藏乘客验证页面
|
||||
* ④ debug 使用
|
||||
*/
|
||||
public void showOrHidePressengerCheckPager(boolean isShow, String startSiteAddr,
|
||||
String endSiteAddr,
|
||||
String passengerNum,
|
||||
@@ -288,7 +322,7 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
String phone) {
|
||||
try {
|
||||
if (isShow) {
|
||||
if(mArrivedCheckView.get()==null){
|
||||
if(mArrivedCheckView==null||mArrivedCheckView.get()==null){
|
||||
initCheckView();
|
||||
}
|
||||
mArrivedCheckView.get().setData(startSiteAddr, endSiteAddr, passengerNum, carNumber,phone);
|
||||
@@ -301,10 +335,18 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户评分后接口回调
|
||||
* @param isSuccess true 打分成功 false 打分失败
|
||||
*/
|
||||
public void showArrivedEndLayout2Thank(boolean isSuccess) {
|
||||
if(mArrivedEndView.get()==null){
|
||||
initArrivedView();
|
||||
}
|
||||
mArrivedEndView.get().showThanksPageWithAnimation(isSuccess);
|
||||
if(isSuccess){
|
||||
mArrivedEndView.get().scoreSuccess();
|
||||
}else {
|
||||
mArrivedEndView.get().scoreFail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,9 @@ import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
|
||||
import com.mogo.eagle.core.utilcode.util.OverlayViewUtils
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils
|
||||
import com.mogo.och.taxi.passenger.R
|
||||
import com.mogo.och.taxi.passenger.callback.ITaxiPassengerCheckPhoneCallback
|
||||
import com.mogo.och.taxi.passenger.callback.ITaxiPassengerCommonValueCallback
|
||||
|
||||
/**
|
||||
* V2X预警事件view:通过FloatWindow呈现,无需加入到自定义layout中
|
||||
@@ -32,7 +31,7 @@ class TaxiPassengerCheckView :RelativeLayout, View.OnClickListener {
|
||||
|
||||
constructor(context: Context?, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
|
||||
|
||||
var onCheckPhoneAndUpdateStatusListener: ITaxiPassengerCheckPhoneCallback?=null
|
||||
var iTaxiPassengerCommonValueCallback: ITaxiPassengerCommonValueCallback<String>?=null
|
||||
|
||||
private lateinit var tvPassengerCount: TextView
|
||||
private lateinit var tvPassengerStart: TextView
|
||||
@@ -115,7 +114,7 @@ class TaxiPassengerCheckView :RelativeLayout, View.OnClickListener {
|
||||
ToastUtils.showLong("请输入正确的手机尾号")
|
||||
return
|
||||
}
|
||||
onCheckPhoneAndUpdateStatusListener?.onCheckPhoneAndUpdateOrderStatus(numberStr)
|
||||
iTaxiPassengerCommonValueCallback?.onCommonCallback(numberStr)
|
||||
}
|
||||
|
||||
private fun selectIndex(i: Int) {
|
||||
@@ -141,7 +140,7 @@ class TaxiPassengerCheckView :RelativeLayout, View.OnClickListener {
|
||||
index--
|
||||
}
|
||||
changeStyle()
|
||||
return
|
||||
//return
|
||||
}
|
||||
numSelect[index] = null
|
||||
numSelectTextView[index]!!.text = ""
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
package com.mogo.och.taxi.passenger.utils.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
|
||||
public abstract class BaseSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
|
||||
public static final int DEFAULT_FRAME_DURATION_MILLISECOND = 50;
|
||||
|
||||
private HandlerThread handlerThread;
|
||||
private SurfaceViewHandler handler;
|
||||
protected int frameDuration = DEFAULT_FRAME_DURATION_MILLISECOND;
|
||||
private Canvas canvas;
|
||||
private boolean isAlive;
|
||||
|
||||
public BaseSurfaceView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public BaseSurfaceView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public BaseSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
protected int getFrameDuration() {
|
||||
return frameDuration;
|
||||
}
|
||||
|
||||
protected void setFrameDuration(int frameDuration) {
|
||||
this.frameDuration = frameDuration;
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
getHolder().addCallback(this);
|
||||
setBackgroundTransparent();
|
||||
}
|
||||
|
||||
private void setBackgroundTransparent() {
|
||||
getHolder().setFormat(PixelFormat.TRANSLUCENT);
|
||||
setZOrderOnTop(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
isAlive = true;
|
||||
startDrawThread();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
stopDrawThread();
|
||||
isAlive = false;
|
||||
}
|
||||
|
||||
private void stopDrawThread() {
|
||||
isAlive = false;
|
||||
handlerThread.quit();
|
||||
handler = null;
|
||||
}
|
||||
|
||||
private void startDrawThread() {
|
||||
handlerThread = new HandlerThread("SurfaceViewThread");
|
||||
handlerThread.start();
|
||||
handler = new SurfaceViewHandler(handlerThread.getLooper());
|
||||
handler.post(new DrawRunnable());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int originWidth = getMeasuredWidth();
|
||||
int originHeight = getMeasuredHeight();
|
||||
int width = widthMode == MeasureSpec.AT_MOST ? getDefaultWidth() : originWidth;
|
||||
int height = heightMode == MeasureSpec.AT_MOST ? getDefaultHeight() : originHeight;
|
||||
setMeasuredDimension(width, height);
|
||||
Log.v("ttaylor", "BaseSurfaceView.onMeasure()" + " default Width=" + getDefaultWidth() + " default height=" + getDefaultHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* the width is used when wrap_content is set to layout_width
|
||||
* the child knows how big it should be
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract int getDefaultWidth();
|
||||
|
||||
/**
|
||||
* the height is used when wrap_content is set to layout_height
|
||||
* the child knows how big it should be
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract int getDefaultHeight();
|
||||
|
||||
|
||||
private class SurfaceViewHandler extends Handler {
|
||||
|
||||
public SurfaceViewHandler(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private class DrawRunnable implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isAlive) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
canvas = getHolder().lockCanvas();
|
||||
onFrameDraw(canvas);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
getHolder().unlockCanvasAndPost(canvas);
|
||||
onFrameDrawFinish();
|
||||
}
|
||||
|
||||
handler.postDelayed(this, frameDuration);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* it is will be invoked after one frame is drawn
|
||||
*/
|
||||
protected abstract void onFrameDrawFinish();
|
||||
|
||||
/**
|
||||
* draw one frame to the surface by canvas
|
||||
*
|
||||
* @param canvas
|
||||
*/
|
||||
protected abstract void onFrameDraw(Canvas canvas);
|
||||
|
||||
protected void runOnUIThread( Runnable executor ) {
|
||||
if ( executor == null ) {
|
||||
return;
|
||||
}
|
||||
if ( Looper.myLooper() != Looper.getMainLooper() ) {
|
||||
UiThreadHandler.post( executor );
|
||||
} else {
|
||||
executor.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.mogo.och.taxi.passenger.utils.view;
|
||||
|
||||
public interface FrameFinishCallback {
|
||||
void onFinishCallback();
|
||||
}
|
||||
@@ -0,0 +1,399 @@
|
||||
package com.mogo.och.taxi.passenger.utils.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* a SurfaceView which draws bitmaps one after another like frame animation
|
||||
*/
|
||||
public class FrameSurfaceView extends BaseSurfaceView {
|
||||
public static final int INVALID_INDEX = Integer.MAX_VALUE;
|
||||
private int bufferSize = 3;
|
||||
public static final String DECODE_THREAD_NAME = "DecodingThread";
|
||||
public static final int INFINITE = -1;
|
||||
//-1 means repeat infinitely
|
||||
private int repeatTimes;
|
||||
private int repeatedCount;
|
||||
|
||||
/**
|
||||
* the resources of frame animation
|
||||
*/
|
||||
private List<Integer> bitmapIds = new ArrayList<>();
|
||||
/**
|
||||
* the index of bitmap resource which is decoding
|
||||
*/
|
||||
private int bitmapIdIndex;
|
||||
/**
|
||||
* the index of frame which is drawing
|
||||
*/
|
||||
private AtomicInteger frameIndex;
|
||||
/**
|
||||
* decoded bitmaps stores in this queue
|
||||
* consumer is drawing thread, producer is decoding thread.
|
||||
*/
|
||||
private LinkedBlockingQueue decodedBitmaps = new LinkedBlockingQueue(bufferSize);
|
||||
/**
|
||||
* bitmaps already drawn by canvas stores in this queue
|
||||
* consumer is decoding thread, producer is drawing thread.
|
||||
*/
|
||||
private LinkedBlockingQueue drawnBitmaps = new LinkedBlockingQueue(bufferSize);
|
||||
/**
|
||||
* the thread for decoding bitmaps
|
||||
*/
|
||||
private HandlerThread decodeThread;
|
||||
/**
|
||||
* the Runnable describes how to decode one bitmap
|
||||
*/
|
||||
private DecodeRunnable decodeRunnable;
|
||||
/**
|
||||
* this handler helps to decode bitmap one after another
|
||||
*/
|
||||
private Handler handler;
|
||||
private BitmapFactory.Options options;
|
||||
private Paint paint = new Paint();
|
||||
private Rect srcRect;
|
||||
private Rect dstRect = new Rect();
|
||||
private int defaultWidth;
|
||||
private int defaultHeight;
|
||||
|
||||
private FrameFinishCallback frameFinishCallback;
|
||||
|
||||
public FrameSurfaceView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public FrameSurfaceView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public FrameSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public void setRepeatTimes(int repeatTimes) {
|
||||
this.repeatTimes = repeatTimes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
options = new BitmapFactory.Options();
|
||||
options.inMutable = true;
|
||||
decodeThread = new HandlerThread(DECODE_THREAD_NAME);
|
||||
frameIndex = new AtomicInteger();
|
||||
frameIndex.set(INVALID_INDEX);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
dstRect.set(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDefaultWidth() {
|
||||
return defaultWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDefaultHeight() {
|
||||
return defaultHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFrameDrawFinish() {
|
||||
}
|
||||
|
||||
/**
|
||||
* set the duration of frame animation
|
||||
*
|
||||
* @param duration time in milliseconds
|
||||
*/
|
||||
public void setDuration(int duration) {
|
||||
int frameDuration = duration / bitmapIds.size();
|
||||
setFrameDuration(frameDuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the materials of frame animation which is an array of bitmap resource id
|
||||
*
|
||||
* @param bitmapIds an array of bitmap resource id
|
||||
*/
|
||||
public void setBitmapIds(List<Integer> bitmapIds) {
|
||||
if (bitmapIds == null || bitmapIds.size() == 0) {
|
||||
return;
|
||||
}
|
||||
this.bitmapIds = bitmapIds;
|
||||
//by default, take the first bitmap's dimension into consideration
|
||||
getBitmapDimension(bitmapIds.get(bitmapIdIndex));
|
||||
preloadFrames();
|
||||
decodeRunnable = new DecodeRunnable(bitmapIdIndex, bitmapIds, options);
|
||||
}
|
||||
|
||||
private void getBitmapDimension(int bitmapId) {
|
||||
final BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeResource(this.getResources(), bitmapId, options);
|
||||
defaultWidth = options.outWidth;
|
||||
defaultHeight = options.outHeight;
|
||||
srcRect = new Rect(0, 0, defaultWidth, defaultHeight);
|
||||
//we have to re-measure to make defaultWidth in use in onMeasure()
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* load the first several frames of animation before it is started
|
||||
*/
|
||||
private void preloadFrames() {
|
||||
decodeAndPutBitmap(bitmapIds.get(bitmapIdIndex++), options, new LinkedBitmap());
|
||||
decodeAndPutBitmap(bitmapIds.get(bitmapIdIndex++), options, new LinkedBitmap());
|
||||
}
|
||||
|
||||
/**
|
||||
* recycle the bitmap used by frame animation.
|
||||
* Usually it should be invoked when the ui of frame animation is no longer visible
|
||||
*/
|
||||
public void destroy() {
|
||||
if (drawnBitmaps != null) {
|
||||
drawnBitmaps.clear();
|
||||
}
|
||||
if (decodeThread != null) {
|
||||
decodeThread.quit();
|
||||
decodeThread = null;
|
||||
}
|
||||
if (handler != null) {
|
||||
handler = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFrameDraw(Canvas canvas) {
|
||||
clearCanvas(canvas);
|
||||
if (!isStart()) {
|
||||
return;
|
||||
}
|
||||
if (!isFinish()) {
|
||||
drawOneFrame(canvas);
|
||||
} else {
|
||||
onFrameAnimationEnd();
|
||||
if (repeatTimes != 0 && repeatTimes == INFINITE) {
|
||||
start();
|
||||
} else if (repeatedCount < repeatTimes) {
|
||||
start();
|
||||
repeatedCount++;
|
||||
} else {
|
||||
repeatedCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* draw a single frame which is a bitmap
|
||||
*
|
||||
* @param canvas
|
||||
*/
|
||||
private void drawOneFrame(Canvas canvas) {
|
||||
LinkedBitmap linkedBitmap = getDecodedBitmap();
|
||||
if (linkedBitmap != null) {
|
||||
canvas.drawBitmap(linkedBitmap.bitmap, srcRect, dstRect, paint);
|
||||
}
|
||||
putDrawnBitmap(linkedBitmap);
|
||||
frameIndex.incrementAndGet();
|
||||
if(isFinish()&&frameFinishCallback!=null){
|
||||
runOnUIThread(() -> frameFinishCallback.onFinishCallback());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* invoked when frame animation is done
|
||||
*/
|
||||
private void onFrameAnimationEnd() {
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* reset the index of frame, preparing for the next frame animation
|
||||
*/
|
||||
private void reset() {
|
||||
frameIndex.set(INVALID_INDEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* whether frame animation is finished
|
||||
*
|
||||
* @return true: animation is finished, false: animation is doing
|
||||
*/
|
||||
private boolean isFinish() {
|
||||
return frameIndex.get() >= bitmapIds.size() - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* whether frame animation is started
|
||||
*
|
||||
* @return true: animation is started, false: animation is not started
|
||||
*/
|
||||
private boolean isStart() {
|
||||
return frameIndex.get() != INVALID_INDEX;
|
||||
}
|
||||
|
||||
/**
|
||||
* start frame animation from the first frame
|
||||
*/
|
||||
public void start() {
|
||||
frameIndex.compareAndSet(INVALID_INDEX, 0);
|
||||
if (decodeThread == null) {
|
||||
decodeThread = new HandlerThread(DECODE_THREAD_NAME);
|
||||
}
|
||||
if (!decodeThread.isAlive()) {
|
||||
decodeThread.start();
|
||||
}
|
||||
if (handler == null) {
|
||||
handler = new Handler(decodeThread.getLooper());
|
||||
}
|
||||
if (decodeRunnable != null) {
|
||||
decodeRunnable.setIndex(0);
|
||||
}
|
||||
handler.post(decodeRunnable);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* clear out the drawing on canvas,preparing for the next frame
|
||||
* * @param canvas
|
||||
*/
|
||||
private void clearCanvas(Canvas canvas) {
|
||||
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
|
||||
canvas.drawPaint(paint);
|
||||
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
|
||||
}
|
||||
|
||||
/**
|
||||
* decode bitmap by BitmapFactory.decodeStream(), it is about twice faster than BitmapFactory.decodeResource()
|
||||
*
|
||||
* @param resId the bitmap resource
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
private Bitmap decodeBitmap(int resId, BitmapFactory.Options options) {
|
||||
options.inScaled = false;
|
||||
InputStream inputStream = getResources().openRawResource(resId);
|
||||
return BitmapFactory.decodeStream(inputStream, null, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* reuse bitmap in drawnBitmaps to decode new bitmap
|
||||
*
|
||||
* @param resId
|
||||
* @param options
|
||||
*/
|
||||
private void decodedBitmapByReuse(int resId, BitmapFactory.Options options) {
|
||||
LinkedBitmap linkedBitmap = getDrawnBitmap();
|
||||
if (linkedBitmap == null) {
|
||||
linkedBitmap = new LinkedBitmap();
|
||||
}
|
||||
options.inBitmap = linkedBitmap.bitmap;
|
||||
decodeAndPutBitmap(resId, options, linkedBitmap);
|
||||
}
|
||||
|
||||
/**
|
||||
* decode bitmap and put it into decodedBitmaps
|
||||
*
|
||||
* @param resId
|
||||
* @param options
|
||||
* @param linkedBitmap
|
||||
*/
|
||||
private void decodeAndPutBitmap(int resId, BitmapFactory.Options options, LinkedBitmap linkedBitmap) {
|
||||
Bitmap bitmap = decodeBitmap(resId, options);
|
||||
linkedBitmap.bitmap = bitmap;
|
||||
try {
|
||||
decodedBitmaps.put(linkedBitmap);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void putDrawnBitmap(LinkedBitmap bitmap) {
|
||||
drawnBitmaps.offer(bitmap);
|
||||
}
|
||||
|
||||
/**
|
||||
* get bitmap which already drawn by canvas
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private LinkedBitmap getDrawnBitmap() {
|
||||
LinkedBitmap bitmap = null;
|
||||
try {
|
||||
bitmap = drawnBitmaps.take();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* get decoded bitmap in the decoded bitmap queue
|
||||
* it might block due to new bitmap is not ready
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private LinkedBitmap getDecodedBitmap() {
|
||||
LinkedBitmap bitmap = null;
|
||||
try {
|
||||
bitmap = decodedBitmaps.take();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public FrameFinishCallback getFrameFinishCallback() {
|
||||
return frameFinishCallback;
|
||||
}
|
||||
|
||||
public void setFrameFinishCallback(FrameFinishCallback frameFinishCallback) {
|
||||
this.frameFinishCallback = frameFinishCallback;
|
||||
}
|
||||
|
||||
private class DecodeRunnable implements Runnable {
|
||||
|
||||
private int index;
|
||||
private List<Integer> bitmapIds;
|
||||
private BitmapFactory.Options options;
|
||||
|
||||
public DecodeRunnable(int index, List<Integer> bitmapIds, BitmapFactory.Options options) {
|
||||
this.index = index;
|
||||
this.bitmapIds = bitmapIds;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
decodedBitmapByReuse(bitmapIds.get(index), options);
|
||||
index++;
|
||||
if (index < bitmapIds.size()) {
|
||||
handler.post(this);
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.mogo.och.taxi.passenger.utils.view;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
/**
|
||||
* a structure used by LinkedBlockingQueue to keep bitmap
|
||||
*/
|
||||
public class LinkedBitmap {
|
||||
public Bitmap bitmap;
|
||||
public LinkedBitmap next;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
package com.mogo.och.taxi.passenger.utils.view;
|
||||
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class LinkedBlockingQueue {
|
||||
/**
|
||||
* Current number of elements
|
||||
*/
|
||||
private final AtomicInteger count = new AtomicInteger();
|
||||
/**
|
||||
* Lock held by take, poll, etc
|
||||
*/
|
||||
private final ReentrantLock takeLock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* Wait queue for waiting takes
|
||||
*/
|
||||
private final Condition notEmpty = takeLock.newCondition();
|
||||
|
||||
/**
|
||||
* Lock held by put, offer, etc
|
||||
*/
|
||||
private final ReentrantLock putLock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* Wait queue for waiting puts
|
||||
*/
|
||||
private final Condition notFull = putLock.newCondition();
|
||||
/**
|
||||
* The capacity bound, or Integer.MAX_VALUE if none
|
||||
*/
|
||||
private final int capacity;
|
||||
/**
|
||||
* the first element in the queue
|
||||
*/
|
||||
private LinkedBitmap head;
|
||||
/**
|
||||
* the last element int the queue
|
||||
*/
|
||||
private LinkedBitmap tail;
|
||||
|
||||
|
||||
public LinkedBlockingQueue(int capacity) {
|
||||
if (capacity <= 0) throw new IllegalArgumentException();
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
public void put(LinkedBitmap bitmap) throws InterruptedException {
|
||||
if (bitmap == null) throw new NullPointerException();
|
||||
// Note: convention in all put/take/etc is to preset local var
|
||||
// holding count negative to indicate failure unless set.
|
||||
int c = -1;
|
||||
final ReentrantLock putLock = this.putLock;
|
||||
final AtomicInteger count = this.count;
|
||||
putLock.lockInterruptibly();
|
||||
try {
|
||||
/*
|
||||
* Note that count is used in wait guard even though it is
|
||||
* not protected by lock. This works because count can
|
||||
* only decrease at this point (all other puts are shut
|
||||
* out by lock), and we (or some other waiting put) are
|
||||
* signalled if it ever changes from capacity. Similarly
|
||||
* for all other uses of count in other wait guards.
|
||||
*/
|
||||
while (count.get() == capacity) {
|
||||
notFull.await();
|
||||
}
|
||||
enqueue(bitmap);
|
||||
c = count.getAndIncrement();
|
||||
if (c + 1 < capacity)
|
||||
notFull.signal();
|
||||
} finally {
|
||||
putLock.unlock();
|
||||
}
|
||||
if (c == 0)
|
||||
signalNotEmpty();
|
||||
}
|
||||
|
||||
public boolean offer(LinkedBitmap bitmap) {
|
||||
if (bitmap == null) throw new NullPointerException();
|
||||
final AtomicInteger count = this.count;
|
||||
if (count.get() == capacity)
|
||||
return false;
|
||||
int c = -1;
|
||||
final ReentrantLock putLock = this.putLock;
|
||||
putLock.lock();
|
||||
try {
|
||||
if (count.get() < capacity) {
|
||||
enqueue(bitmap);
|
||||
c = count.getAndIncrement();
|
||||
if (c + 1 < capacity)
|
||||
notFull.signal();
|
||||
}
|
||||
} finally {
|
||||
putLock.unlock();
|
||||
}
|
||||
if (c == 0)
|
||||
signalNotEmpty();
|
||||
return c >= 0;
|
||||
}
|
||||
|
||||
public LinkedBitmap take() throws InterruptedException {
|
||||
LinkedBitmap x;
|
||||
int c = -1;
|
||||
final AtomicInteger count = this.count;
|
||||
final ReentrantLock takeLock = this.takeLock;
|
||||
takeLock.lockInterruptibly();
|
||||
try {
|
||||
while (count.get() == 0) {
|
||||
notEmpty.await();
|
||||
}
|
||||
x = dequeue();
|
||||
c = count.getAndDecrement();
|
||||
if (c > 1)
|
||||
notEmpty.signal();
|
||||
} finally {
|
||||
takeLock.unlock();
|
||||
}
|
||||
if (c == capacity)
|
||||
signalNotFull();
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* insert element into the end of queue
|
||||
*
|
||||
* @param bitmap
|
||||
*/
|
||||
private void enqueue(LinkedBitmap bitmap) {
|
||||
if (head == null) {
|
||||
head = bitmap;
|
||||
tail = bitmap;
|
||||
bitmap.next = null;
|
||||
} else {
|
||||
tail.next = bitmap;
|
||||
bitmap.next = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get and remove the first element of the queue
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private LinkedBitmap dequeue() {
|
||||
LinkedBitmap p = head;
|
||||
if (p == null) {
|
||||
return null;
|
||||
} else {
|
||||
head = head.next;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals a waiting take. Called only from put/offer (which do not
|
||||
* otherwise ordinarily lock takeLock.)
|
||||
*/
|
||||
private void signalNotEmpty() {
|
||||
final ReentrantLock takeLock = this.takeLock;
|
||||
takeLock.lock();
|
||||
try {
|
||||
notEmpty.signal();
|
||||
} finally {
|
||||
takeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals a waiting put. Called only from take/poll.
|
||||
*/
|
||||
private void signalNotFull() {
|
||||
final ReentrantLock putLock = this.putLock;
|
||||
putLock.lock();
|
||||
try {
|
||||
notFull.signal();
|
||||
} finally {
|
||||
putLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* recycle the bitmaps one by one
|
||||
*/
|
||||
public void clear() {
|
||||
LinkedBitmap p = head;
|
||||
if (p == null) {
|
||||
return;
|
||||
}
|
||||
while (p != null) {
|
||||
if (p.bitmap != null) {
|
||||
p.bitmap.recycle();
|
||||
}
|
||||
p.bitmap = null;
|
||||
p = p.next;
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getCount() {
|
||||
return count.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.mogo.och.taxi.passenger.utils.view;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
public class MethodUtil {
|
||||
/**
|
||||
* calculate the time consumed by runnable invocation, print log in millisecond
|
||||
*
|
||||
* @param runnable
|
||||
*/
|
||||
public static long time(Runnable runnable) {
|
||||
long start = SystemClock.elapsedRealtime();
|
||||
runnable.run();
|
||||
long end = SystemClock.elapsedRealtime();
|
||||
long span = end - start;
|
||||
Log.v("ttaylor", "MethodUtil.time()" + " time span = " + span + " ms");
|
||||
return span;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.mogo.och.taxi.passenger.utils.view;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
public class NumberUtil {
|
||||
|
||||
private static long total;
|
||||
private static int times;
|
||||
|
||||
private static String tag;
|
||||
|
||||
/**
|
||||
* calculate the average of a series long number and print it
|
||||
* @param tag
|
||||
* @param l
|
||||
*/
|
||||
public static void average(String tag, Long l) {
|
||||
if (!TextUtils.isEmpty(tag) && !tag.equals(NumberUtil.tag)) {
|
||||
reset();
|
||||
NumberUtil.tag = tag;
|
||||
}
|
||||
times++;
|
||||
total += l;
|
||||
Log.v("ttaylor", "Average.average() " + NumberUtil.tag + " average = " + (total / times));
|
||||
}
|
||||
|
||||
private static void reset() {
|
||||
total = 0;
|
||||
times = 0;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android" android:startOffset="500" >
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android" android:startOffset="500" >
|
||||
<translate
|
||||
android:duration="1000"
|
||||
android:duration="500"
|
||||
android:fromXDelta="-110%"
|
||||
android:toXDelta="0"/>
|
||||
</set>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android" android:startOffset="500" >
|
||||
<translate
|
||||
android:duration="1000"
|
||||
android:duration="500"
|
||||
android:fromXDelta="0"
|
||||
android:toXDelta="-110%"/>
|
||||
</set>
|
||||
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:oneshot="true">
|
||||
<item android:drawable="@drawable/tail_ani_0000" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0001" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0002" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0003" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0004" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0005" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0006" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0007" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0008" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0009" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0010" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0011" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0012" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0013" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0014" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0015" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0016" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0017" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0018" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0019" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0020" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0021" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0022" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0023" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0024" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0025" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0026" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0027" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0028" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0029" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0030" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0031" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0032" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0033" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0034" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0035" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0036" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0037" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0038" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0039" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0040" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0041" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0042" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0043" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0044" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0045" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0046" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0047" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0048" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0049" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0050" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0051" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0052" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0053" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0054" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0055" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0056" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0057" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0058" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0059" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0060" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0061" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0062" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0063" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0064" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0065" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0066" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0067" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0068" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0069" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0070" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0071" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0072" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0073" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0074" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0075" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0076" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0077" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0078" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0079" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0080" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0081" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0082" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0083" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0084" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0085" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0086" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0087" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0088" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0089" android:duration="33"/>
|
||||
<item android:drawable="@drawable/tail_ani_0090" android:duration="33"/>
|
||||
|
||||
</animation-list>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:oneshot="false">
|
||||
<item android:drawable="@drawable/hand_00000" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00002" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00004" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00006" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00008" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00010" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00012" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00014" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00016" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00018" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00020" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00022" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00024" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00026" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00028" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00030" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00032" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00034" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00036" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00038" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00040" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00042" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00044" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00046" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00048" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00050" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00052" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00054" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00056" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00058" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00060" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00062" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00064" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00066" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00068" android:duration="33"/>
|
||||
<item android:drawable="@drawable/hand_00069" android:duration="33"/>
|
||||
|
||||
</animation-list>
|
||||
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00000.png
Executable file
|
After Width: | Height: | Size: 156 B |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00002.png
Executable file
|
After Width: | Height: | Size: 22 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00004.png
Executable file
|
After Width: | Height: | Size: 24 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00006.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00008.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00010.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00012.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00014.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00016.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00018.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00020.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00022.png
Executable file
|
After Width: | Height: | Size: 27 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00024.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00026.png
Executable file
|
After Width: | Height: | Size: 28 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00028.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00030.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00032.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00034.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00036.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00038.png
Executable file
|
After Width: | Height: | Size: 27 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00040.png
Executable file
|
After Width: | Height: | Size: 24 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00042.png
Executable file
|
After Width: | Height: | Size: 25 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00044.png
Executable file
|
After Width: | Height: | Size: 24 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00046.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00048.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00050.png
Executable file
|
After Width: | Height: | Size: 27 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00052.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00054.png
Executable file
|
After Width: | Height: | Size: 27 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00056.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00058.png
Executable file
|
After Width: | Height: | Size: 25 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00060.png
Executable file
|
After Width: | Height: | Size: 25 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00062.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00064.png
Executable file
|
After Width: | Height: | Size: 27 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00066.png
Executable file
|
After Width: | Height: | Size: 28 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00068.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/hand_00069.png
Executable file
|
After Width: | Height: | Size: 25 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0000.jpg
Executable file
|
After Width: | Height: | Size: 155 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0001.jpg
Executable file
|
After Width: | Height: | Size: 155 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0002.jpg
Executable file
|
After Width: | Height: | Size: 155 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0003.jpg
Executable file
|
After Width: | Height: | Size: 155 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0004.jpg
Executable file
|
After Width: | Height: | Size: 155 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0005.jpg
Executable file
|
After Width: | Height: | Size: 155 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0006.jpg
Executable file
|
After Width: | Height: | Size: 155 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0007.jpg
Executable file
|
After Width: | Height: | Size: 155 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0008.jpg
Executable file
|
After Width: | Height: | Size: 155 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0009.jpg
Executable file
|
After Width: | Height: | Size: 155 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0010.jpg
Executable file
|
After Width: | Height: | Size: 155 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0011.jpg
Executable file
|
After Width: | Height: | Size: 155 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0012.jpg
Executable file
|
After Width: | Height: | Size: 156 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0013.jpg
Executable file
|
After Width: | Height: | Size: 157 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0014.jpg
Executable file
|
After Width: | Height: | Size: 158 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0015.jpg
Executable file
|
After Width: | Height: | Size: 159 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0016.jpg
Executable file
|
After Width: | Height: | Size: 159 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0017.jpg
Executable file
|
After Width: | Height: | Size: 159 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0018.jpg
Executable file
|
After Width: | Height: | Size: 158 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0019.jpg
Executable file
|
After Width: | Height: | Size: 172 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0020.jpg
Executable file
|
After Width: | Height: | Size: 160 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0021.jpg
Executable file
|
After Width: | Height: | Size: 161 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0022.jpg
Executable file
|
After Width: | Height: | Size: 162 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0023.jpg
Executable file
|
After Width: | Height: | Size: 157 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0024.jpg
Executable file
|
After Width: | Height: | Size: 158 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0025.jpg
Executable file
|
After Width: | Height: | Size: 151 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0026.jpg
Executable file
|
After Width: | Height: | Size: 145 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0027.jpg
Executable file
|
After Width: | Height: | Size: 144 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0028.jpg
Executable file
|
After Width: | Height: | Size: 144 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0029.jpg
Executable file
|
After Width: | Height: | Size: 143 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0030.jpg
Executable file
|
After Width: | Height: | Size: 142 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0031.jpg
Executable file
|
After Width: | Height: | Size: 142 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0032.jpg
Executable file
|
After Width: | Height: | Size: 142 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0033.jpg
Executable file
|
After Width: | Height: | Size: 141 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0034.jpg
Executable file
|
After Width: | Height: | Size: 140 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0035.jpg
Executable file
|
After Width: | Height: | Size: 139 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0036.jpg
Executable file
|
After Width: | Height: | Size: 131 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0037.jpg
Executable file
|
After Width: | Height: | Size: 131 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0038.jpg
Executable file
|
After Width: | Height: | Size: 131 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0039.jpg
Executable file
|
After Width: | Height: | Size: 130 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0040.jpg
Executable file
|
After Width: | Height: | Size: 131 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0041.jpg
Executable file
|
After Width: | Height: | Size: 129 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0042.jpg
Executable file
|
After Width: | Height: | Size: 128 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0043.jpg
Executable file
|
After Width: | Height: | Size: 127 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0044.jpg
Executable file
|
After Width: | Height: | Size: 126 KiB |
BIN
OCH/mogo-och-taxi-passenger/src/main/res/drawable/tail_ani_0045.jpg
Executable file
|
After Width: | Height: | Size: 126 KiB |