【问题标题】:How to make your custom view focusable?如何使您的自定义视图具有焦点?
【发布时间】:2017-10-05 23:12:01
【问题描述】:

我正在创建一个自定义视图。这基本上是一个带有边框的矩形框。我希望边框在用户单击时更改颜色并使其具有焦点。如果矩形失去焦点,我希望边框恢复原始颜色。我想用这个背景作为表单背景。我已经尝试过 android 文档和堆栈溢出答案,但我无法做到这一点。我已将其设为可点击,但我无法继续进行。

public class FormBackgroundView extends View implements View.OnClickListener{

    private int _borderColor;
    Paint fillPaint, strokePaint;
    Canvas canvas;

    public FormBackgroundView(Context context) {
        super(context);
        init();
    }

    public FormBackgroundView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FormBackgroundView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public FormBackgroundView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init(){
        super.setOnClickListener(this);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        fillPaint = new Paint();
        strokePaint = new Paint();

        fillPaint.setStyle(Paint.Style.FILL);
        fillPaint.setColor(Color.WHITE);

        strokePaint.setStyle(Paint.Style.FILL);
        strokePaint.setColor(Color.BLACK);
        strokePaint.setAntiAlias(true);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            canvas.drawRoundRect(0,0,getWidth(),getHeight(), 10, 10, strokePaint);
            canvas.drawRoundRect(0 + 3,0 + 3,getWidth() - 3,getHeight() - 3, 7, 7, fillPaint);
        } else {
            canvas.drawRect(0,0,getWidth(),getHeight(), strokePaint);
            canvas.drawRect(0 + 4,0 + 4,getWidth() -4 ,getHeight() -4, fillPaint);
        }

        this.canvas = canvas;
    }



    @Override
    public void onClick(View view) {

    }


}

【问题讨论】:

标签: java android android-layout android-custom-view


【解决方案1】:

您的视图在触摸模式下不会自动聚焦。如果您希望视图在单击(触摸)时获得焦点,则必须调用“setFocusableInTouchMode()”。虽然过时了,但我发现this explanation 对描述触摸模式很有用。

所以,在您的init() 中添加setFocusableInTouchMode(true)

其次,无论视图是否聚焦,您都不会在 onDraw() 中做任何不同的事情。将其更改为以下内容:

protected void onDraw(Canvas canvas) {
    // your paint code
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        if (isFocused()) { // draw the border
            canvas.drawRoundRect(0, 0, getWidth(), getHeight(), 10, 10, strokePaint);
            canvas.drawRoundRect(0 + 3, 0 + 3, getWidth() - 3, getHeight() - 3, 7, 7, fillPaint);
        } else { // don't draw the border
            canvas.drawRoundRect(0, 0, getWidth(), getHeight(), 7, 7, fillPaint);
        }
    } else {
        //similar here
    }
    // The rest of your code
}

【讨论】:

  • 感谢您的回答。我想问一件事什么时候调用 onDraw()。我以为它只被调用了一次。焦点改变时是否再次调用它?
  • 或者当我们调用 invalidate() 时?
  • @killerprince182 是的,它被调用了。对于可聚焦视图,通常有一些视觉指示表明该视图具有焦点,因此调用 onDraw() 是有意义的。
【解决方案2】:

试试这个:

public class FormBackGroundView extends View {

    private int _borderColor;
    Paint fillPaint, strokePaint;
    Canvas canvas;
    private boolean isFocused;

    public FormBackGroundView(Context context) {
        super(context);
        init();
    }

    public FormBackGroundView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FormBackGroundView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        fillPaint = new Paint();
        strokePaint = new Paint();
        fillPaint.setStyle(Paint.Style.FILL);
        strokePaint.setStyle(Paint.Style.FILL);
        strokePaint.setAntiAlias(true);
        setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (motionEvent.getAction() == MotionEvent.ACTION_DOWN && !isFocused) {
                    isFocused = true;
                    invalidate();
                } else if (motionEvent.getAction() == MotionEvent.ACTION_UP && isFocused) {
                    isFocused = false;
                    invalidate();
                }
                return true;
            }
        });
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        fillPaint.setColor(Color.WHITE);

        strokePaint.setColor(isFocused? Color.RED:Color.BLACK);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            canvas.drawRoundRect(0, 0, getWidth(), getHeight(), 10, 10, strokePaint);
            canvas.drawRoundRect(0 + 3, 0 + 3, getWidth() - 3, getHeight() - 3, 7, 7, fillPaint);
        } else {
            canvas.drawRect(0, 0, getWidth(), getHeight(), strokePaint);
            canvas.drawRect(0 + 4, 0 + 4, getWidth() - 4, getHeight() - 4, fillPaint);
        }
    }
}

【讨论】:

  • 这段代码有一个问题。一旦表格停止接触,表格就会恢复正常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-20
  • 1970-01-01
  • 2019-08-10
  • 2015-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多