Image gone After Focusing

2020-05-08 08:08发布

问题:

This is before focus state. It work fine.

This is on focusing state. It work fine.

This is after focus state. It occurred problem where the image gone.

It works fine for the top right but top left image got problem.

Here is my custom VerticalFieldManager:

public class Custom_TopField extends HorizontalFieldManager implements
    FieldChangeListener {

private Bitmap bg = Bitmap.getBitmapResource("header_bar.png");
private Bitmap download = Bitmap.getBitmapResource("btn_download.png");
private Bitmap downloadactive = Bitmap
        .getBitmapResource("btn_download_active.png");
private Bitmap refresh = Bitmap.getBitmapResource("icon_refresh.png");
private Bitmap refreshactive = Bitmap
        .getBitmapResource("icon_refresh_active.png");
private Bitmap back = Bitmap.getBitmapResource("btn_back.png");
private Bitmap backctive = Bitmap.getBitmapResource("btn_back_active.png");
private Bitmap news = Bitmap.getBitmapResource("icon_news.png");
private Bitmap newsactive = Bitmap
        .getBitmapResource("icon_news_active.png");

private Custom_ButtonField downloadbtn, refreshbtn, backbtn, newsbtn;
private Custom_LabelField title;

Custom_TopField(final MainScreen mainscreen) {
    Background background = BackgroundFactory.createBitmapBackground(bg);
    setBackground(background);
    title = new Custom_LabelField("东方日报", DrawStyle.ELLIPSIS
            | LabelField.USE_ALL_WIDTH | DrawStyle.HCENTER
            | Field.FOCUSABLE, Color.WHITE) {
        protected boolean navigationClick(int status, int time) {
            Main.getUiApplication().pushScreen(new Main_AllLatestNews());
            Main.getUiApplication().popScreen(mainscreen);
            return true;
        }
    };
    title.setFont(Font.getDefault().derive(Font.BOLD, 33));
    add(title);

    downloadbtn = new Custom_ButtonField(download, downloadactive,
            downloadactive);
    downloadbtn.setChangeListener(this);
    add(downloadbtn);

    refreshbtn = new Custom_ButtonField(refresh, refreshactive,
            refreshactive);
    refreshbtn.setChangeListener(this);
    add(refreshbtn);

    backbtn = new Custom_ButtonField(back, backctive, backctive);
    backbtn.setChangeListener(this);
    add(backbtn);

    /*newsbtn = new Custom_ButtonField(news, newsactive, newsactive);
    newsbtn.setChangeListener(this);
    add(newsbtn);*/
}

protected void sublayout(int width, int height) {
    Field field = getField(0);
    layoutChild(field, 120, Font.getDefault().getHeight());
    setPositionChild(field, (getPreferredWidth() - title.getWidth()) / 2,
            15);

    field = getField(1);
    layoutChild(field, download.getWidth(), download.getHeight());
    setPositionChild(field, getPreferredWidth()
            - (download.getWidth() + 10),
            getPreferredHeight() - (download.getHeight() + 5));

    field = getField(2);
    layoutChild(field, refresh.getWidth(), refresh.getHeight());
    setPositionChild(field,
            getPreferredWidth() - (refresh.getWidth() + 10),
            getPreferredHeight() - (refresh.getHeight() + 5));

    field = getField(3);
    layoutChild(field, back.getWidth(), back.getHeight());
    setPositionChild(field, 10, 5);

    /*field = getField(4);
    layoutChild(field, news.getWidth(), news.getHeight());
    setPositionChild(field, 10, 5);*/

    width = Math.min(width, getPreferredWidth());
    height = Math.min(height, getPreferredHeight());
    setExtent(width, height);
}

public int getPreferredHeight() {
    return 70;
}

public int getPreferredWidth() {
    return Display.getWidth();
}

public void paint(Graphics graphics) {
    int rectHeight = getPreferredHeight();
    int rectWidth = getPreferredWidth();

    graphics.drawRect(0, 0, rectWidth, rectHeight);
    super.paint(graphics);
}

public void fieldChanged(Field field, int context) {
    if (field == downloadbtn) {

    } else if (field == refreshbtn) {

    } else if (field == backbtn) {

    } else if (field == newsbtn) {

    }
}
}

Here is custom button field

public class Custom_ButtonField extends ButtonField {
Bitmap mNormal;
Bitmap mFocused;
Bitmap mActive;

int mWidth;
int mHeight;

private int color = -1;
String text;

public Custom_ButtonField(Bitmap normal, Bitmap focused, Bitmap active) {
    super(CONSUME_CLICK | Field.FOCUSABLE);
    mNormal = normal;
    mFocused = focused;
    mActive = active;
    mWidth = mNormal.getWidth();
    mHeight = mNormal.getHeight();
    setMargin(0, 0, 0, 0);
    setPadding(0, 0, 0, 0);
    setBorder(BorderFactory.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
    setBorder(VISUAL_STATE_ACTIVE,
            BorderFactory.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
}

public Custom_ButtonField(String text, Bitmap normal, Bitmap focused,
        Bitmap active, int color) {
    super(CONSUME_CLICK | Field.FOCUSABLE);
    this.color = color;
    mNormal = normal;
    mFocused = focused;
    mActive = active;
    mWidth = mNormal.getWidth();
    mHeight = mNormal.getHeight();
    setMargin(0, 0, 0, 0);
    setPadding(0, 0, 0, 0);
    setBorder(BorderFactory.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
    setBorder(VISUAL_STATE_ACTIVE,
            BorderFactory.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
    this.text = text;
}

protected void onFocus(int direction) {
    super.onFocus(direction);
}

protected void onUnfocus() {
    super.onUnfocus();
}

protected void paint(Graphics graphics) {
    Bitmap bitmap = null;
    switch (getVisualState()) {
    case VISUAL_STATE_NORMAL:
        bitmap = mNormal;
        break;
    case VISUAL_STATE_FOCUS:
        bitmap = mFocused;
        break;
    case VISUAL_STATE_ACTIVE:
        bitmap = mActive;
        break;
    default:
        bitmap = mNormal;
    }
    graphics.drawBitmap(0, 0, bitmap.getWidth(), bitmap.getHeight(),
            bitmap, 0, 0);
    graphics.setFont(Font.getDefault().derive(Font.BOLD, 25));
    graphics.setColor(color);
    graphics.drawText(text, (mNormal.getWidth() - Font.getDefault()
            .getAdvance(text)) / 2, ((mNormal.getHeight() - Font
            .getDefault().getHeight()) / 2) + 10, DrawStyle.HCENTER
            | DrawStyle.VCENTER);
}

public int getPreferredWidth() {
    return mWidth;
}

public int getPreferredHeight() {
    return mHeight;
}

protected void layout(int width, int height) {
    setExtent(mWidth, mHeight);
}
}

回答1:

This is the second problem just like this I've seen in the last couple weeks.

Background

To understand the solution, first you should understand the basic UI classes in BlackBerry.

First, we have the Field class. A Field is the base class of the normal UI components. If you write a UI component yourself, from scratch, then you would subclass Field:

public class MyWidget extends Field {

However, if there already exists a BlackBerry class that does almost what you need, and you just need to change its behaviour a bit, then you would subclass something else. For example:

public class MyButtonWidget extends ButtonField {

The same pattern exists for the Manager class. If you are writing a Manager from scratch, then extend Manager:

public class MyManager extends Manager {

which involves doing this, according to the BlackBerry docs:

Implementing your own layout manager

If you have particular needs, you can implement your own manager. Extend the Manager class, and implement sublayout, getPreferredWidth, and getPreferredHeight. For efficiency, you may optionally override subpaint.

However, if an existing Manager subclass already does most of what you need, and you just want to customize it, then you might consider extending that subclass:

public class MyHorizontalManager extends HorizontalFieldManager {

In your case, your Custom_TopField is doing all of the required work for a fully custom Manager (see the highlighted quote above from the javadocs). So, there's not really any reason for you to extend HorizontalFieldManager. A HorizontalFieldManager is used when you just want to add() your fields, and have them all laid out horizontally. But, you do that explicitly in your sublayout() code. As it turns out, it looks like your logic is competing with the base class.

Solution

So, what you should do, is have your class just extend Manager:

public class Custom_TopField extends Manager implements FieldChangeListener {

If you do that, you will need to call a different super constructor. Something like this (you might want to pick different style constants depending on your needs):

Custom_TopField(final MainScreen mainscreen) {
   super(Manager.USE_ALL_WIDTH | Manager.NO_VERTICAL_SCROLL | Manager.NO_HORIZONTAL_SCROLL);

Another alternative would be to simply not implement sublayout(), extend HorizontalFieldManager like you originally had, and then control layout with the child fields' margins and long style flags. But, since the solution I gave above requires only changing 2 lines of code, that's probably the easiest for you this time.

Other Problem(s)

I also noticed in your code, and screenshots, that the Download button doesn't show up. I don't know the exact size of all your png images, but if the refresh and download images are the same size, then your current logic is just laying out the refresh button right over the download button. So, the download button is hidden. That's probably not what you want?