4

主な目的は、CNNニュース速報スタイルのバーを下部に表示し、いくつかの写真を表示することです。2 つのカスタム ビューを作成しました。1 つは写真を表示するためのもので、もう 1 つはバーを表示するためのものです。指定された時間、一度に 1 つの画像を表示し、現在の画像をキューの次の画像と交換します。

下部バーのテキストをアニメーション化するには、canvas、onDraw()、および handler.postDelayed を使用しました。この解決策は悪い結果をもたらします。特に画像の入れ替えに関しては、テキストの動きが滑らかではありません。

キャンバスの代わりに何を使用すればよいですか? このタスクを比較的楽にできる OpenGL ベースのライブラリはありますか? AndEngine を使用しようとしましたが、ドキュメントの欠如とスレッドの問題により、それを使用する気が失せました。

public class Infobar extends View {

    private List<Message> messages;

    private Handler handler;

    private Paint boxPaint;
    private Paint defaultTextPaint;
    private Paint importantTextPaint;

    private long offset = 0;
    private long maxOffset = 1000;
    private int textWidth = 1000;
    private int textHeight = 50;

    private int measuredWidth;
    private int measuredHeight;

    private Runnable animateRunnable = new Runnable() {
        public void run() {
            animateMessage();
        }
    };

    long startTime = new Date().getTime();

    private int backgroundCol = Color.parseColor("#ffff00");
    private int textColor = Color.parseColor("#000000");

    private static final int FRAME_DELAY = 10;
    private static final int FRAME_SHIFT    = 3;

    private static final int EMPTY_SPACE = 2;
    private static final String SEPARATOR = "  ✩  ";

    private static final int TEXT_SIZE = 35;


    public Infobar(Context context, AttributeSet attrs) {
        super(context, attrs);

        handler = new Handler();
        messages = new ArrayList<Message>();

        boxPaint = new Paint();

        defaultTextPaint = new Paint();
        defaultTextPaint.setColor(getResources().getColor(R.color.info_bar_default_text_color));

        importantTextPaint = new Paint();
        importantTextPaint.setColor(getResources().getColor(R.color.info_bar_important_text_color));

        handler.postDelayed(animateRunnable, FRAME_DELAY);

    }

    public void setMessagesList(List<Message> list) {
        messages = list;
    }

    public void setBackgroundColor(String color) {
        backgroundCol = Color.parseColor(color);
    }

    public void setTextColor(String color) {
        textColor = Color.parseColor(color);
    }

    public List<Message> getMessagesList() {
        return messages;
    }

    private String getMessagesString() {
        StringBuilder builder = new StringBuilder();
        for(Message message : messages) {
            builder.append(message.content);
            if(messages.indexOf(message) != (messages.size() - 1)) {
                builder.append(SEPARATOR);
            }
        }
        return builder.toString();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);   
        measuredWidth = getMeasuredWidth();
        measuredHeight = getMeasuredHeight();

    }

    @Override
    protected void onDraw(Canvas canvas) {

        drawBackground(canvas, false);
        drawMessage(canvas, getMessagesString());


        super.onDraw(canvas);
    }

    private void drawBackground(Canvas canvas, boolean important) {

        boxPaint.setColor(backgroundCol) ;

        canvas.drawRect(0, 0, measuredWidth, measuredHeight, boxPaint);
    }

    private void drawMessage(Canvas canvas, String message) {
        defaultTextPaint.setTextSize(TEXT_SIZE);

        Rect bounds = new Rect();
        defaultTextPaint.getTextBounds(message, 0, message.length(), bounds);
        defaultTextPaint.setColor(textColor);

        textWidth = bounds.width();
        textHeight = bounds.height();

        int positionX = measuredWidth - (int)offset;
        int positionY = measuredHeight - textHeight/2;      

        if(offset  > (measuredWidth + textWidth)) {
            offset = 0;
            positionX = measuredWidth;
        }

        canvas.drawText(message, positionX, positionY, defaultTextPaint);
    }

    private void animateMessage() {
        offset += FRAME_SHIFT; 
        //offset = Math.round((new Date().getTime() - startTime) * 0.2) % (measuredWidth + textWidth);
        invalidate();
        handler.removeCallbacks(animateRunnable);
        handler.postDelayed(animateRunnable, FRAME_DELAY);
    }



}
4

1 に答える 1

6

特別な理由がない限り、TextView の組み込みマーキー機能を使用できます。

<LinearLayout>
<TextView
    android:id="@+id/myText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:lines="1"
    android:ellipsize="marquee"
    android:fadingEdge="horizontal"
    android:marqueeRepeatLimit="marquee_forever"
    android:scrollHorizontally="true"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:text="Your long text goes here. You can also change it programmatically" />
</LinearLayout>

次に、アクティビティ コードで:

TextView myText=(TextView) findViewById(R.id.myText);
myText.setSelected(true); //needs this to work
于 2012-12-04T17:46:40.530 に答える