添加SlidePanelView实现

This commit is contained in:
tongchenfei
2021-01-21 12:54:52 +08:00
parent d187af5d98
commit 301cd0f4ed
5 changed files with 263 additions and 11 deletions

View File

@@ -13,6 +13,7 @@ import com.mogo.module.common.view.OnPreventFastClickListener;
import com.mogo.och.bus.R;
import com.mogo.och.bus.bean.OchBusStation;
import com.mogo.och.bus.presenter.OchBusPresenter;
import com.mogo.service.adas.entity.AdasOCHData;
import com.mogo.utils.logger.Logger;
import java.util.ArrayList;
@@ -26,7 +27,6 @@ import java.util.List;
*/
public class OchBusFragment extends MvpFragment<OchBusFragment, OchBusPresenter> {
private static final String TAG = "OchBusFragment";
private Group groupOchBus;
private final List<OchBusStation> stationList = new ArrayList<>();
private Button btnExecute;
private TextView tvNotice;
@@ -38,13 +38,15 @@ public class OchBusFragment extends MvpFragment<OchBusFragment, OchBusPresenter>
@Override
protected void initViews() {
groupOchBus = findViewById(R.id.groupOchBus);
findViewById(R.id.btnEnterOchBus).setOnClickListener(new OnPreventFastClickListener() {
@Override
public void onClickImpl(View v) {
showOchBus();
}
});
findViewById(R.id.btnArrive).setOnClickListener(view->{
mPresenter.onArriveAt(new AdasOCHData(10, nextStation.getLon(), nextStation.getLat()));
});
btnExecute = findViewById(R.id.btnExecute);
btnExecute.setOnClickListener(new OnPreventFastClickListener() {
@Override
@@ -63,8 +65,8 @@ public class OchBusFragment extends MvpFragment<OchBusFragment, OchBusPresenter>
public void showOchBus() {
MogoApisHandler.getInstance().getApis().getTopViewManager().removeAllViewInVrMode();
groupOchBus.setVisibility(View.VISIBLE);
tvNotice.setVisibility(View.VISIBLE);
}
@Override
@@ -83,6 +85,8 @@ public class OchBusFragment extends MvpFragment<OchBusFragment, OchBusPresenter>
}
}
private OchBusStation nextStation;
public void refreshBusStations(List<OchBusStation> busStationList) {
if (getActivity() == null) {
return;
@@ -98,6 +102,7 @@ public class OchBusFragment extends MvpFragment<OchBusFragment, OchBusPresenter>
OchBusStation station = stationList.get(i);
if (station.getIsCurrentSite() == OchBusPresenter.STATION_STATUS_LEAVING) {
tvNotice.setText("正在从 " + i + "站驶向" + (i + 1) + "");
nextStation = stationList.get(i + 1);
btnExecute.setVisibility(View.GONE);
break;
} else if (station.getIsCurrentSite() == OchBusPresenter.STATION_STATUS_STOPED) {
@@ -118,7 +123,7 @@ public class OchBusFragment extends MvpFragment<OchBusFragment, OchBusPresenter>
}
public void hideOchBus() {
groupOchBus.setVisibility(View.GONE);
tvNotice.setVisibility(View.GONE);
}
private void queryStationListIfNecessary() {

View File

@@ -60,7 +60,7 @@ public class OchBusPresenter extends Presenter<OchBusFragment> implements IMogoA
lon = lastLocation.getLongitude();
}
OchBusRoutesRequest request = new OchBusRoutesRequest(Utils.getSn(),lat, lon);
RequestBody requestBody = RequestBody.create(MediaType.get("application/json"), GsonUtil.jsonFromObject(request));
RequestBody requestBody = RequestBody.create(MediaType.get("application/json;charset=UTF-8"), GsonUtil.jsonFromObject(request));
MogoApisHandler.getInstance().getApis().getNetworkApi()
.create(IOchBusApiService.class, HostConst.OCH_DOMAIN)
.querySiteByCoordinate(requestBody)

View File

@@ -22,6 +22,15 @@
app:layout_constraintRight_toRightOf="@id/vBusRoute"
app:layout_constraintTop_toBottomOf="@id/vBusRoute" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnArrive"
android:text="到达"
android:textSize="30sp"
app:layout_constraintRight_toLeftOf="@id/vBusRoute"
app:layout_constraintTop_toTopOf="@id/vBusRoute" />
<TextView
android:id="@+id/vBusRoute"
android:layout_width="600px"
@@ -33,10 +42,4 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Group
android:id="@+id/groupOchBus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="vBusRoute,btnExecute" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,244 @@
package com.mogo.och.view;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import androidx.annotation.Nullable;
import com.mogo.och.R;
/**
* 滑块滑动面板
*
* @author tongchenfei
*/
public class SlidePanelView extends View {
private static final String TAG = "SlidePanelView";
public SlidePanelView(Context context) {
this(context, null);
}
public SlidePanelView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidePanelView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private final Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint blockPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private static final int BLOCK_START_X = 10;
private static final int BLOCK_START_Y = 10;
private static final int TEXT_MARGIN_LEFT = 20;
private static final int TEXT_MARGIN_RIGHT = 30;
private OnSlidePanelMoveToEndListener moveToEndListener;
private int blockWidth = 0;
private int blockOffset = 0;
private float lastX;
private boolean isToEnd = false;
private static final String STRING_SLIDE_TO_RIGHT = "向右滑动";
private RectF bgRectF;
private Bitmap bmBlock;
private final Matrix gradientMatrix = new Matrix();
private float matrixTranslate;
private final Rect textRect = new Rect();
private LinearGradient textGradient;
private ObjectAnimator matrixAnim;
private String blockText = STRING_SLIDE_TO_RIGHT;
private Paint.FontMetrics blockTextMetrics = new Paint.FontMetrics();
public void setOnSlidePanelMoveToEndListener(OnSlidePanelMoveToEndListener moveToEndListener) {
this.moveToEndListener = moveToEndListener;
}
private void setBlockOffset(int blockOffset) {
this.blockOffset = blockOffset;
invalidate();
}
private void setMatrixTranslate(float matrixTranslate) {
this.matrixTranslate = matrixTranslate;
invalidate();
}
public void setText(String text) {
this.blockText = text;
requestLayout();
invalidate();
}
private void init() {
bgPaint.setColor(Color.RED);
bgPaint.setStyle(Paint.Style.FILL);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(40);
textPaint.setTextAlign(Paint.Align.LEFT);
textGradient = new LinearGradient(-80, 0, 0, 0, new int[]{0xffffffff, 0xff000000, 0xffffffff}, new float[]{0, 0.5f, 1f}, Shader.TileMode.CLAMP);
textGradient.setLocalMatrix(gradientMatrix);
textPaint.setShader(textGradient);
textPaint.getFontMetrics(blockTextMetrics);
bmBlock = BitmapFactory.decodeResource(getResources(), R.drawable.ic_block);
blockWidth = bmBlock.getWidth();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
Log.d(TAG, "onMeasure:\r\n widthMode: " + widthMode + " widthSize: " + widthSize + " \r\n heightMode: " + heightMode + " heightSize: " + heightSize);
Log.d(TAG, "textMetrics: ascent: " + blockTextMetrics.ascent + " descent: " + blockTextMetrics.descent + " top: " + blockTextMetrics.top + " bottom: " + blockTextMetrics.bottom);
if (widthMode == MeasureSpec.AT_MOST) {
// 宽度根据图片大小,字符串长度,各种间隔确定
// 高度根据图片大小和上下间隔确定
textPaint.getTextBounds(blockText, 0, blockText.length(), textRect);
widthSize = BLOCK_START_X * 2 + bmBlock.getWidth() + TEXT_MARGIN_LEFT + TEXT_MARGIN_RIGHT + textRect.width();
heightSize = BLOCK_START_Y * 2 + bmBlock.getHeight();
widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private float textOffset = 0;
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
bgRectF = new RectF(0, 0, w, h);
if (matrixAnim != null) {
matrixAnim.cancel();
}
textOffset = (getHeight() - blockTextMetrics.ascent - blockTextMetrics.descent) / 2;
matrixAnim = ObjectAnimator.ofFloat(this, "matrixTranslate", 0, w + 80).setDuration(1000);
matrixAnim.setRepeatCount(ValueAnimator.INFINITE);
matrixAnim.start();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (matrixAnim != null) {
matrixAnim.start();
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (matrixAnim != null) {
matrixAnim.cancel();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (x > BLOCK_START_X + blockOffset && x < blockWidth + BLOCK_START_X + blockOffset && y > BLOCK_START_Y && y < getHeight() - BLOCK_START_Y) {
isToEnd = false;
lastX = x;
}
break;
case MotionEvent.ACTION_MOVE:
if (lastX != 0) {
blockOffset = (int) (x - lastX);
if (blockOffset < 0) {
blockOffset = 0;
}
if (blockOffset + BLOCK_START_X + blockWidth > getWidth()) {
// 超出右边界
blockOffset = getWidth() - BLOCK_START_X - blockWidth;
if (!isToEnd) {
isToEnd = true;
if (moveToEndListener != null) {
moveToEndListener.moveToEnd();
}
startBlockBackAnim();
}
}
invalidate();
}
break;
case MotionEvent.ACTION_UP:
// 执行滑块回归动画
if (!isToEnd) {
startBlockBackAnim();
}
break;
default:
break;
}
return true;
}
private void startBlockBackAnim() {
ObjectAnimator animator = ObjectAnimator.ofInt(this, "blockOffset", blockOffset, 0);
animator.setInterpolator(new DecelerateInterpolator());
animator.setDuration(1000 * blockOffset / getWidth());
animator.start();
lastX = 0;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 画背景
canvas.drawRoundRect(bgRectF, (float) getHeight() / 2, (float) getHeight() / 2, bgPaint);
// 画文字
gradientMatrix.setTranslate(matrixTranslate, 0);
textGradient.setLocalMatrix(gradientMatrix);
canvas.save();
canvas.drawText(blockText, blockWidth + BLOCK_START_X + TEXT_MARGIN_LEFT, textOffset, textPaint);
canvas.restore();
// 画滑块
canvas.drawBitmap(bmBlock, BLOCK_START_X + blockOffset, BLOCK_START_Y, blockPaint);
}
public interface OnSlidePanelMoveToEndListener {
/**
* 滑块滑到了末尾
*/
void moveToEnd();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB