Android实现带垂直连线的公交站点追踪自定义ListView布局
实现带状态圆圈和垂直线的公交站点ListView布局
看起来你需要的是一个左侧带贯穿式垂直线、且垂直线穿过状态圆圈中心的列表项布局,同时根据站点途经状态切换圆圈颜色。我帮你调整布局和Adapter代码,来实现这个效果:
1. 修改列表项布局文件(listBusStops.xml)
首先调整布局,添加垂直线View,并确保它与圆圈中心对齐,同时让圆圈覆盖在线上(保证视觉上线穿过圆圈中心):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingVertical="16dp"> <!-- 垂直线:位于圆圈中心,宽度2dp --> <View android:id="@+id/vertical_line" android:layout_width="2dp" android:layout_height="match_parent" android:layout_marginStart="14dp" <!-- 计算方式:圆圈中心(15dp) - 线宽一半(1dp) = 14dp --> android:background="@color/gray" /> <!-- 状态圆圈:覆盖在线上,中心与线对齐 --> <ImageView android:id="@+id/ivstatus" android:layout_width="30dp" android:layout_height="30dp" /> <!-- 站点名称:在圆圈右侧,垂直居中 --> <TextView android:id="@+id/tvname" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@id/ivstatus" android:layout_alignBottom="@id/ivstatus" android:layout_toEndOf="@id/ivstatus" android:layout_marginStart="12dp" android:gravity="center_vertical" /> </RelativeLayout>
2. 优化Custom_list Adapter代码
接下来调整Adapter,动态控制垂直线的显示范围(第一个项只显示下半段线,最后一个项只显示上半段线,中间项显示完整线),同时优化代码结构降低耦合:
import android.app.Activity; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.core.content.ContextCompat; import java.util.ArrayList; class Custom_list extends ArrayAdapter<String> { private final Activity context; private final ArrayList<String> stopNames; private final ArrayList<String> statusList; private final int greenCircleRes; private final int redCircleRes; private final int circleHalfHeight; public Custom_list(Activity context, ArrayList<String> stopNames, ArrayList<String> statusList) { super(context, R.layout.list_bus_stops, stopNames); this.context = context; this.stopNames = stopNames; this.statusList = statusList; this.greenCircleRes = R.drawable.circle_green; this.redCircleRes = R.drawable.circle_red; // 获取圆圈高度的一半(30dp的一半是15dp) this.circleHalfHeight = context.getResources().getDimensionPixelSize(R.dimen.circle_half_height); } @Override public View getView(int position, View convertView, ViewGroup parent) { // 复用convertView提升性能 View rowView = convertView; if (rowView == null) { LayoutInflater inflater = context.getLayoutInflater(); rowView = inflater.inflate(R.layout.list_bus_stops, parent, false); } // 获取控件实例 TextView tvName = rowView.findViewById(R.id.tvname); ImageView ivStatus = rowView.findViewById(R.id.ivstatus); View verticalLine = rowView.findViewById(R.id.vertical_line); // 设置站点名称 tvName.setText(stopNames.get(position)); // 设置圆圈颜色 if (statusList.get(position).equalsIgnoreCase("yes")) { ivStatus.setImageResource(greenCircleRes); } else { ivStatus.setImageResource(redCircleRes); } // 动态调整垂直线的显示范围 RelativeLayout.LayoutParams lineParams = (RelativeLayout.LayoutParams) verticalLine.getLayoutParams(); if (position == 0) { // 第一个项:线从圆圈中心开始向下延伸 lineParams.topMargin = circleHalfHeight; lineParams.bottomMargin = 0; } else if (position == stopNames.size() - 1) { // 最后一个项:线从顶部延伸到圆圈中心 lineParams.topMargin = 0; lineParams.bottomMargin = circleHalfHeight; } else { // 中间项:线贯穿整个项的高度 lineParams.topMargin = 0; lineParams.bottomMargin = 0; } verticalLine.setLayoutParams(lineParams); // 可选:根据前后站点状态设置线的颜色(已途经区间用绿色,未途经用灰色) if (position > 0) { boolean prevVisited = statusList.get(position - 1).equalsIgnoreCase("yes"); boolean currentVisited = statusList.get(position).equalsIgnoreCase("yes"); if (prevVisited && currentVisited) { verticalLine.setBackgroundColor(ContextCompat.getColor(context, R.color.green)); } else { verticalLine.setBackgroundColor(ContextCompat.getColor(context, R.color.gray)); } } else { // 第一个项的线默认灰色 verticalLine.setBackgroundColor(ContextCompat.getColor(context, R.color.gray)); } return rowView; } }
3. 添加辅助资源
在res/values/dimens.xml中添加圆圈半高的定义:
<dimen name="circle_half_height">15dp</dimen>
在res/values/colors.xml中添加需要的颜色:
<color name="gray">#808080</color> <color name="green">#4CAF50</color>
关键说明
- 垂直线对齐:通过计算
layout_marginStart让垂直线正好处于圆圈的中心位置,同时让圆圈覆盖在线上,实现"线穿过圆圈中心"的视觉效果。 - 连贯线效果:通过动态设置垂直线的上下margin,让整条线在列表中连贯,不会在第一个/最后一个项出现多余的延伸。
- 可选优化:添加了根据前后站点状态切换线颜色的逻辑,让已途经的区间线显示绿色,更符合公交追踪的业务逻辑。
内容的提问来源于stack exchange,提问作者Asish Dash
相关产品推荐
相关产品推荐

