我需要使用您在UI-Mockup中看到的行实现ListView:
我设法根据行的数据处理不同的行布局。 问题是,您将采用哪种方式实现显示的时间轴布局? 我开始使用RelativeLayouts,使用边距将标记和文本放在时间轴上的正确位置,但是滚动列表时会遇到很多麻烦。 TextViews并不总是处于绝对正确的位置。
这是行布局的重要部分(带有长蓝线的图像的第2行):
<LinearLayout
android:id="@+id/progress"
android:layout_height="50dp"
android:layout_width="fill_parent"
android:paddingBottom="10dp"
android:paddingRight="10dp"
android:layout_gravity="bottom">
<RelativeLayout
android:id="@+id/progressContainer"
android:layout_height="fill_parent"
android:layout_gravity="bottom"
android:layout_width="0px"
android:layout_weight="6"
>
<RelativeLayout
android:id="@+id/blue"
android:background="#FF33B5E5"
android:layout_width="fill_parent"
android:layout_height="7dp"
android:layout_alignParentBottom="true"
/>
<tv.px.android.play.widget.CustomImageView android:id="@+id/progressMarker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/marker"
android:layout_alignParentBottom="true"
/>
<tv.px.android.play.widget.CustomTextView android:id="@+id/periodIndicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:layout_above="@id/progressMarker"
android:paddingBottom="2dp"
/>
</RelativeLayout>
<RelativeLayout
android:layout_height="fill_parent"
android:layout_gravity="bottom"
android:layout_weight="1"
android:layout_width="0px"
>
<RelativeLayout
android:id="@+id/red"
android:background="@drawable/red_fadeout_linear_gradient"
android:layout_alignParentBottom="true"
android:layout_width="fill_parent"
android:layout_height="7dp"
/>
<TextView android:id="@+id/periodEndIndicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sa"
android:layout_above="@id/red"
android:layout_alignParentLeft="true"
android:paddingBottom="2dp"
/>
</RelativeLayout>
</LinearLayout>
在CustomImageView
我覆盖onMeasure
方法来计算位置(leftMargin),这很有效:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int widthPerDay = width / daysTotal;
int margin = (daysOver * widthPerDay) - getWidth()/2;
((RelativeLayout.LayoutParams) this.getLayoutParams()).leftMargin = margin;
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
在CustomTextView
中,我尝试了类似的方式,但却产生了不同的立场。我想在回收适配器中的视图时会出现问题,例如TextView的宽度未更新。 编辑:我刚发现parentWidth因行而异。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int widthPerDay = parentWidth / daysTotal;
int margin = (daysOver * widthPerDay) - getWidth() / 2;
if (margin < 0) {
margin = 0;
}
if (margin + getWidth() >= parentWidth) {
margin = parentWidth - getWidth() - 10;
}
((RelativeLayout.LayoutParams) this.getLayoutParams()).setMargins(margin, 0, 0, 0);
this.requestLayout();
}
最后但并非最不重要的是适配器的getView实现:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View v = convertView;
TimeLineItem ci = getItem(position);
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
holder = new ViewHolder();
v = vi.inflate(R.layout.cleaning_list_item, null);
holder.marker = (CustomImageView) v.findViewById(R.id.progressMarker);
holder.periodIndicator = (CustomTextView) v.findViewById(R.id.periodIndicator);
}
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
if (ci != null) {
int daysTotal = 6;
int daysOver = ci.getTotal();
// CustomTextView
holder.periodIndicator.setDaysTotal(daysTotal);
holder.periodIndicator.setDaysOver(daysOver);
if (daysTotal - daysOver == 1) {
holder.periodIndicator.setText("in einem Tag");
} else {
holder.periodIndicator.setText("in " + (daysTotal - daysOver) + " Tagen");
}
// CustomImageView
holder.marker.setDaysTotal(daysTotal);
holder.marker.setDaysOver(daysOver);
holder.marker.requestLayout();
}
return v;
}
所以,第一个问题是:我是否正确地实施这样一个复杂的布局? 如果是这样,我做错了什么?为什么CustomTextView没有正确定位?
答案 0 :(得分:1)
如果使用标准窗口小部件和布局进行自定义显示变得太难,请通过继承View创建自定义窗口小部件。这样做非常简单:在您的情况下,您可能只需要覆盖onDraw
来绘制自定义显示。