自定义图像按钮,最简单的单选按钮界面要覆盖哪种方法?



我正在制作一个自定义视图,该视图本质上是一个带有附加逻辑的ImageButton,因此它也具有RadioButton的行为。我想做的只是将其内置到视图中,当用户单击按钮时,图像会更改,内部布尔值被标记为 true 以注意它已被选中,并调用一个接口方法,让 RadioGroup 它的一部分取消选择其中的所有其他视图。我不想影响基本ImageButton的现有行为。

我之前只制作过另一个自定义视图,那就是几乎完全按照字母遵循教程,并且由于 View 固有的许多不同的方法处理点击/触摸(即 onTouch、onClick、运动事件等(把它全部纳入让我有点困惑。我写界面本身很好,这是对 ImageButton 的修改,我不太确定如何攻击它。

所以,我问大家:我需要覆盖什么方法或方法来添加这个简单的功能,同时不影响 ImageButton 的当前行为,也不会搞砸为按钮设置 onTouchListener 的能力,该按钮将在单击时执行其他操作,而不会影响这个内置的单选按钮逻辑?如果我需要覆盖会弄乱我提到的默认行为的内容,我需要在新方法中放入什么来恢复该功能?

这是我到目前为止所拥有的:

public class RadioImageButton extends AppCompatImageButton implements RadioCheckable {
//Default constructor
public RadioImageButton(Context context) {
super(context);
initView();
}
//Constructor with defined attributes
public RadioImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
parseAttributes();
initView();
}
//Constructor with defined attributes and attributes taken from style defaults that aren't defined
public RadioImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

//=========================================================================
// Setup
//=========================================================================
private void initView()
{
}
private void parseAttributes()
{
}

}

我想采取的方法是这样的:

...All other code I already showed
mChecked = false;
@Overide
void onClick(...)
{
mChecked = true;
setImageSource(R.example.checked_image); // Or I can use a selector resource
*Call to Radio Interface*;
mOnTouchListener.onTouch(v, event); //Handle user onTouchListener
}
...   

并且不要管所有其他代码,尽管我确信它不是那么简单。

我认为一个好的开始是尝试找到默认 ImageButton 类的源代码并将我的设置为近副本,以便我可以了解它的工作原理,然后从那里进行修改,但我真正能找到的只是这个:

https://android.googlesource.com/platform/frameworks/base/+/android-7.0.0_r35/core/java/android/widget/ImageButton.java

而且这不可能是实际的来源,因为按 Ctrl+O 会显示 ImageButton 定义的更多函数,这些函数不是从另一个类继承的;无论如何,该链接根本没有帮助,因为它基本上是一个巨大的注释,几乎没有代码。

感谢您的任何建议,这些建议将帮助我以最直接的方式完成此操作。

编辑:@pskink - 浏览您提供的代码,似乎它正在尝试生成一个矩阵,以便转换提供的可绘制对象(src(,使其适合新的矩形(dst(,同时保持纵横比和定位(因此ScaleToFit.CENTER(。我假设目标矩形将是包含可绘制对象的视图的边界,在本例中是 RadioButton,但是在逐步执行"draw(("方法的覆盖时,它似乎并没有这样做,尽管我不太确定如何解析 cavas.concat(matrix(,所以我不肯定。不管它似乎没有按预期工作,或者我不知何故用错了。

虽然可能不是最健壮的方法,但它似乎是处理我想做的最直接但最有效的方法是利用 Matrix 类及其强大的缩放/转换工具,特别是"setRectToRect(("。创建一个扩展 RadioButton 而不是 ImageButton 的自定义视图使我能够利用现有的 RadioGroup,同时在新类 Constructor 中操作按钮可绘制对象的特征实现了我正在寻找的行为。

自定义单选按钮类:

public class RadioImageButton extends android.support.v7.widget.AppCompatRadioButton {
int stateDrawable; //Resource ID for RadioButton selector Drawable
D scaledDrawable; //Post-scaling drawable
public RadioImageButtonTwo(Context context) {
super(context);
initView();
}
public RadioImageButtonTwo(Context context, AttributeSet attrs) {
super(context, attrs);
parseAttributes(attrs);
initView();
}

private void parseAttributes(AttributeSet attrs)
{
TypedArray styledAttrs = getContext().obtainStyledAttributes(attrs,R.styleable.RadioImageButtonTwo);
try {
// Obtain selector drawable from attributes
stateDrawable = styledAttrs.getResourceId(R.styleable.RadioImageButtonTwo_button_sDrawable, R.drawable.test_draw2);
} finally {
styledAttrs.recycle(); //Required for public shared view
}
}
private void initView()
{
scaledDrawable = new D(getResources(),stateDrawable); // Create scaled drawable
setBackground(scaledDrawable); // Apply scaled drawable
setButtonDrawable(android.R.color.transparent); // "Disable" button graphic
}
}

在此处查看有关设置自定义视图的更多信息:https://developer.android.com/training/custom-views/create-view#customattr

自定义可绘制类"D",包括 fitCenter 缩放,这要归功于@pskink:

class D extends StateListDrawable {
private Rect bounds = new Rect();
private RectF src = new RectF();
private RectF dst = new RectF();
private Matrix matrix = new Matrix();
public D(Resources r, int resId) {
try {
XmlResourceParser parser = r.getXml(resId);
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.START_TAG && parser.getName().equals("selector")) {
inflate(r, parser, Xml.asAttributeSet(parser));
break;
}
}
} catch (XmlPullParserException | IOException e) {
e.printStackTrace();
}
}
@Override
public void draw(Canvas canvas) {
Drawable current = getCurrent();
bounds.set(0, 0, current.getIntrinsicWidth(), current.getIntrinsicHeight());
current.setBounds(bounds);
src.set(bounds);
dst.set(getBounds());
matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);
canvas.concat(matrix);
super.draw(canvas);
}
}

请注意,无论出于何种原因,将按钮可绘制对象本身设置为此自定义可绘制对象都会破坏缩放,因此将背景更改为自定义可绘制对象并将按钮可绘制对象设置为透明是唯一可行的方法。可以轻松扩展此自定义可绘制对象以具有更多缩放类型选项,并且可以定义另一个视图属性以允许用户通过 XML 选择缩放类型。

这个模仿(pskink也指出(的自定义ImageView也可以证明对这项任务很有帮助,因为它也利用Matrix类来实现多种类型的图像缩放:https://github.com/yqritc/Android-ScalableImageView

最新更新