0

我需要用你在 UI-Mockup 中看到的行来实现 ListView:

布局

我设法根据行的数据处理不同的行布局。问题是,您将采用哪种方式来实现显示的时间线布局?我开始使用RelativeLayouts,使用边距将标记和文本放置在时间轴上的正确位置,但是在滚动列表时会产生很多麻烦。TextViews 并不总是在绝对正确的位置。

这是行布局的重要部分(图像的第二行带有长蓝线):

<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 没有正确定位?

4

1 回答 1

1

如果使用标准小部件和布局进行自定义显示变得太难,请通过子类化View创建自定义小部件。这样做很容易:在您的情况下,您可能只需要覆盖onDraw即可绘制自定义显示。

于 2012-05-21T11:00:40.357 回答