我创建了一个自定义步骤视图,并在卡片视图中添加了该视图,以便在回收站视图中使用。但是当添加卡片时,回收者视图中不会显示自定义步骤视图。 但是当直接在活动或片段中使用时,自定义视图是可见的。我附上了截图
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import com.ata.gogreenuser.R;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class StepView extends View {
private static final int START_STEP = 1;
private final List<String> mSteps = new ArrayList<>();
private int mCurrentStep = START_STEP;
private int mCircleColor;
private int mTextColor;
private int mSelectedColor;
private int mCancelColor;
private int mFillRadius;
private int mStrokeWidth;
private int mLineWidth;
private int mDrawablePadding;
private float stepNumberTextSize;
private boolean cancelled = false;
private Paint mPaint;
public StepView(Context context) {
super(context,null);
}
public StepView(Context context, AttributeSet attrs) {
super(context,attrs);
this.setBackgroundColor(Color.TRANSPARENT);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.StepView, 0, R.style.StepView);
mCircleColor = ta.getColor(R.styleable.StepView_svCircleColor, 0);
mTextColor = ta.getColor(R.styleable.StepView_svTextColor, 0);
mSelectedColor = ta.getColor(R.styleable.StepView_svSelectedColor, 0);
mCancelColor = ta.getColor(R.styleable.StepView_svCancelColor, 0);
mFillRadius = ta.getDimensionPixelSize(R.styleable.StepView_svFillRadius, 0);
mStrokeWidth = ta.getDimensionPixelSize(R.styleable.StepView_svStrokeWidth, 0);
mLineWidth = ta.getDimensionPixelSize(R.styleable.StepView_svLineWidth, 0);
mDrawablePadding = ta.getDimensionPixelSize(R.styleable.StepView_svDrawablePadding, 0);
final int textSize = ta.getDimensionPixelSize(R.styleable.StepView_svTextSize, 0);
stepNumberTextSize = ta.getDimension(R.styleable.StepView_sv_stepNumberTextSize, 0);
ta.recycle();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaint.setTextSize(textSize);
mPaint.setTextAlign(Paint.Align.CENTER);
cancel(false);
}
public void setSteps(List<String> steps) {
mSteps.clear();
if (steps != null) {
mSteps.addAll(steps);
}
selectedStep(START_STEP);
}
public void selectedStep(int step) {
final int selected = step < START_STEP ?
START_STEP : (step > mSteps.size() ? mSteps.size() : step);
mCurrentStep = selected;
invalidate();
}
public void cancel(boolean state){
this.cancelled = state;
String[] steps;
if(!state){
steps = new String[]{"Step 1", "Step2", "Step3", "Step4"};
}else {
steps = new String[]{"Step1", "Step2", "Step3", "Step4"
, "Cancelled"};
}
setSteps(Arrays.asList(steps));
}
public int getCurrentStep() {
return mCurrentStep;
}
public int getStepCount() {
return mSteps.size();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode == MeasureSpec.AT_MOST) {
final int fontHeight = (int) Math.ceil(mPaint.descent() - mPaint.ascent());
height = getPaddingTop() + getPaddingBottom() + (mFillRadius + mStrokeWidth) * 2
+ mDrawablePadding + fontHeight;
}
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
final int stepSize = mSteps.size();
if (stepSize == 0) {
return;
}
final int width = getWidth();
final float ascent = mPaint.ascent();
final float descent = mPaint.descent();
final int fontHeight = (int) Math.ceil(descent - ascent);
final int halfFontHeightOffset = -(int)(ascent + descent) / 2;
final int bigRadius = mFillRadius + mStrokeWidth;
final int startCircleY = getPaddingTop() + bigRadius;
final int childWidth = width / stepSize;
for (int i = 1; i <= stepSize; i++) {
drawableStep(canvas, i, halfFontHeightOffset, fontHeight, bigRadius,
childWidth * i - childWidth / 2, startCircleY);
}
final int halfLineLength = childWidth / 2 - bigRadius;
for (int i = 1; i < stepSize; i++) {
final int lineCenterX = childWidth * i;
drawableLine(canvas,i, lineCenterX - halfLineLength,
lineCenterX + halfLineLength, startCircleY);
}
}
private void drawableStep(Canvas canvas, int step, int halfFontHeightOffset, int fontHeight,
int bigRadius, int circleCenterX, int circleCenterY) {
final String text = mSteps.get(step - 1);
if(!cancelled) {
final boolean isSelected = step <= mCurrentStep;
if (isSelected) {
mPaint.setStrokeWidth(mStrokeWidth);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(mCircleColor);
canvas.drawCircle(circleCenterX, circleCenterY, mFillRadius + mStrokeWidth / 2, mPaint);
mPaint.setColor(mSelectedColor);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(circleCenterX, circleCenterY, mFillRadius, mPaint);
mPaint.setFakeBoldText(true);
mPaint.setColor(Color.WHITE);
drawCheckMark(canvas, circleCenterX, circleCenterY);
} else {
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mCircleColor);
canvas.drawCircle(circleCenterX, circleCenterY, bigRadius, mPaint);
mPaint.setFakeBoldText(true);
mPaint.setColor(Color.WHITE);
String number = String.valueOf(step);
canvas.drawText(number, circleCenterX, circleCenterY + halfFontHeightOffset, mPaint);
}
mPaint.setFakeBoldText(false);
mPaint.setColor(isSelected ? mSelectedColor : mTextColor);
for (String line : text.split("\n")) {
canvas.drawText(line, circleCenterX,
circleCenterY + bigRadius + mDrawablePadding + fontHeight / 2, mPaint);
circleCenterY += -mPaint.ascent() + mPaint.descent();
}
}else{
if(step == 1 || step ==5) {
mPaint.setStrokeWidth(mStrokeWidth);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(mCircleColor);
canvas.drawCircle(circleCenterX, circleCenterY, mFillRadius + mStrokeWidth / 2, mPaint);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(circleCenterX, circleCenterY, mFillRadius, mPaint);
mPaint.setFakeBoldText(true);
mPaint.setColor(Color.RED);
drawCrossMark(canvas, circleCenterX, circleCenterY);
mPaint.setFakeBoldText(false);
mPaint.setColor(Color.RED);
for (String line : text.split("\n")) {
canvas.drawText(line, circleCenterX,
circleCenterY + bigRadius + mDrawablePadding + fontHeight / 2, mPaint);
circleCenterY += -mPaint.ascent() + mPaint.descent();
}
}else{
mPaint.setStrokeWidth(mStrokeWidth);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(mCircleColor);
canvas.drawCircle(circleCenterX, circleCenterY, mFillRadius + mStrokeWidth / 2, mPaint);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(circleCenterX, circleCenterY, mFillRadius, mPaint);
mPaint.setFakeBoldText(true);
mPaint.setColor(Color.WHITE);
String number = String.valueOf(step);
canvas.drawText(number, circleCenterX, circleCenterY + halfFontHeightOffset, mPaint);
mPaint.setFakeBoldText(false);
mPaint.setColor(mTextColor);
for (String line : text.split("\n")) {
mPaint.setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
canvas.drawText(line, circleCenterX,
circleCenterY + bigRadius + mDrawablePadding + fontHeight / 2, mPaint);
circleCenterY += -mPaint.ascent() + mPaint.descent();
}
mPaint.setFlags(0);
}
}
}
private void drawableLine(Canvas canvas, int step,int startX, int endX, int centerY) {
if(!cancelled) {
final boolean isSelected = step < mCurrentStep;
if (isSelected) {
mPaint.setColor(mSelectedColor);
} else {
mPaint.setColor(mCircleColor);
}
mPaint.setStrokeWidth(mLineWidth);
if (step != mCurrentStep) {
canvas.drawLine(startX, centerY, endX, centerY, mPaint);
} else {
mPaint.setColor(mSelectedColor);
int midX = (endX + startX) / 2;
canvas.drawLine(startX, centerY, midX, centerY, mPaint);
mPaint.setColor(mCircleColor);
canvas.drawLine(midX, centerY, endX, centerY, mPaint);
}
}else{
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(mLineWidth);
canvas.drawLine(startX, centerY, endX, centerY, mPaint);
}
}
private void drawCheckMark(Canvas canvas, int circleCenterX, int circleCenterY) {
mPaint.setColor(Color.WHITE);
float width = stepNumberTextSize * 0.1f;
mPaint.setStrokeWidth(width);
Rect bounds = new Rect(
(int) (circleCenterX - width * 4.5),
(int) (circleCenterY - width * 3.5),
(int) (circleCenterX + width * 4.5),
(int) (circleCenterY + width * 3.5));
canvas.drawLine(
bounds.left + 0.5f * width,
bounds.bottom - 3.25f * width,
bounds.left + 3.25f * width,
bounds.bottom - 0.75f * width, mPaint);
canvas.drawLine(
bounds.left + 2.75f * width,
bounds.bottom - 0.75f * width,
bounds.right - 0.375f * width,
bounds.top + 0.75f * width, mPaint);
}
private void drawCrossMark(Canvas canvas, int circleCenterX, int circleCenterY) {
mPaint.setColor(Color.WHITE);
float width = stepNumberTextSize * 0.1f;
mPaint.setStrokeWidth(width);
Rect bounds = new Rect(
(int) (circleCenterX - width * 4.5),
(int) (circleCenterY - width * 3.5),
(int) (circleCenterX + width * 4.5),
(int) (circleCenterY + width * 3.5));
canvas.drawLine(
bounds.left,
bounds.bottom,
bounds.right,
bounds.top , mPaint);
canvas.drawLine(
bounds.left,
bounds.top,
bounds.right,
bounds.bottom , mPaint);
}
}
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:showDividers="middle"
android:divider="@color/divider_color">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:weightSum="3">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2">
<ImageView
android:id="@+id/marker_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_baseline_location_on_24"
android:background="@color/colorWhiteTransparent"/>
<TextView
android:id="@+id/address_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/marker_image"
android:layout_marginLeft="5dp"
android:hint="Address"
android:layout_centerVertical="true"
android:textColor="@color/black"
android:maxLines="1"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="1"
android:layout_gravity="center_vertical">
<Button
android:id="@+id/status_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:text="Status"
android:textAllCaps="false"
android:textSize="12sp"/>
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/step_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.ata.gogreenuser.View.StepView
android:id="@+id/step_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:background="@android:color/white"
android:paddingBottom="8dp"
android:paddingTop="8dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="2"
android:showDividers="middle"
android:padding="5dp"
android:divider="@color/divider_color">
<RelativeLayout
android:id="@+id/need_help_rl"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Need Help"
android:gravity="center"
android:drawablePadding="5dp"
android:drawableLeft="@drawable/ic_baseline_help_outline_24"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/view_details_rl"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="View Details"
android:gravity="center"
android:drawablePadding="5dp"
android:drawableLeft="@drawable/ic_baseline_wysiwyg_24"/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.ata.gogreenuser.Model.Request;
import com.ata.gogreenuser.R;
import com.ata.gogreenuser.View.StepView;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class RequestRecyclerAdapter extends RecyclerView.Adapter<RequestRecyclerAdapter.ViewHolder> {
private final List<Request> requestList;
private final Context context;
public RequestRecyclerAdapter(List<Request> requestList, Context context) {
this.requestList = requestList;
this.context = context;
}
@NonNull
@NotNull
@Override
public RequestRecyclerAdapter.ViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.request_history_card, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull @NotNull RequestRecyclerAdapter.ViewHolder holder, int position) {
Request request = requestList.get(position);
holder.setAddress("Address,address,ADDRESS");
holder.setStatus("Cancel Request");
//holder.setStepView(2);
holder.myStepView.forceLayout();
StepView mstepView = new StepView(context);
mstepView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
holder.frameLayout.addView(mstepView);
holder.statusButton.setOnClickListener(v->{
Toast.makeText(context,"Status Button",Toast.LENGTH_LONG);
});
holder.needHelp.setOnClickListener(v->{
Toast.makeText(context,"Need Help",Toast.LENGTH_LONG);
});
holder.viewDetails.setOnClickListener(v->{
Toast.makeText(context,"View Details",Toast.LENGTH_LONG);
});
}
@Override
public int getItemCount() {
return requestList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
View mView;
Button statusButton;
RelativeLayout needHelp;
RelativeLayout viewDetails;
StepView myStepView;
LinearLayout frameLayout;
public ViewHolder(@NonNull @NotNull View itemView) {
super(itemView);
mView = itemView;
statusButton = itemView.findViewById(R.id.status_btn);
needHelp = itemView.findViewById(R.id.need_help_rl);
viewDetails = itemView.findViewById(R.id.view_details_rl);
//myStepView = new StepView(context);
myStepView = itemView.findViewById(R.id.step_view);
frameLayout = itemView.findViewById(R.id.step_frame);
myStepView.cancel(false);
}
void setAddress(String address){
TextView addressView = mView.findViewById(R.id.address_tv);
addressView.setText(address);
}
void setStatus(String status){
this.statusButton.setText(status);
}
// void setStepView(int status){
// StepView stepView = mView.findViewById(R.id.step_view);
// if(status == 0){
// stepView.cancel(false);
// stepView.selectedStep(1);
// }else if(status == 1){
// stepView.cancel(false);
// stepView.selectedStep(2);
// }else if(status == 3){
// stepView.cancel(false);
// stepView.selectedStep(3);
// }else if(status == 5){
// stepView.cancel(false);
// stepView.selectedStep(4);
// }else{
// stepView.cancel(true);
// }
// }
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragment.HistoryFragment">
<RelativeLayout
android:id="@+id/histroyLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/history_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"/>
</RelativeLayout>
</FrameLayout>
package com.ata.gogreenuser.Fragment;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.ata.gogreenuser.Adapter.RequestRecyclerAdapter;
import com.ata.gogreenuser.Model.Request;
import com.ata.gogreenuser.R;
import com.ata.gogreenuser.View.StepView;
import com.facebook.shimmer.ShimmerFrameLayout;
import java.util.ArrayList;
import java.util.List;
public class HistoryFragment extends Fragment {
private RelativeLayout historyLayout;
private RecyclerView historyRV;
private List<Request> requestList;
private RequestRecyclerAdapter requestRecyclerAdapter;
public HistoryFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_history, container, false);
historyLayout = view.findViewById(R.id.histroyLayout);
historyRV = view.findViewById(R.id.history_rv);
historyRV.hasFixedSize();
historyRV.setLayoutManager(new LinearLayoutManager(getContext()));
requestList = new ArrayList<>();
Request request = new Request();
Request request123 = new Request();
requestList.add(request);
requestList.add(request123);
requestRecyclerAdapter = new RequestRecyclerAdapter(requestList,getContext());
historyRV.setAdapter(requestRecyclerAdapter);
return view;
}
}
我附上了截图
Recycler Adapter Layout Step View Visible when used directly in Fragment/Activity