目录
Android提供了很多的 View,但有时候并不能满足需求,这个时候就需要自己来设计 View 。通常需要重写 onDraw() 方法来绘制需要显示的内容。
本文转自: https://www.jianshu.com/p/369f66035666
本文不会详细描述,已经有很多成熟的文章了,但好记性不如烂笔头,大致描述下我所关注到的(本篇不包含View的绘制流程,仅仅是如何进行自定义View)
好文(系列)推荐:https://blog.csdn.net/carson_ho/article/details/62037696 (我也赶紧去学习一波)
20200507:过了一遍受益匪浅,结论 > 自己对着源码分析是最靠谱的,ViewProject我也顺便更新了下。
不贴详细代码了,代码已经上传: https://github.com/cl18652469346/ViewProject
附上ViewProject的效果图
实现自定义View的三种方式
- 扩展 -- 对现有控件进行扩展
- 组合 -- 将不同的控件组合在一起形成新的控件
- 重写 -- 通过重写来实现全新的控件
方式1: 扩展 -- 对现有控件进行扩展
主要: super.onDraw(canvas); 的前后进行需要内容的绘制。
Tips: 可参照ViewProject中的CustomTextView.java
方式2: 组合 -- 将不同的控件组合在一起形成新的控件
1. 自定义属性 (自定义属性后,在布局中使用CustomView时可设置所需要的数据,提高代码易读性)
attrs.xml 中进行属性的声明
<declare-styleable name="MultiChoiceView">
<attr name="iconSize_" format="integer"/>
<attr name="viewArea_" format="integer"/>
<attr name="imagePoints" format="reference"/>
</declare-styleable>
xml中使用MultiChoiceView
<com.android.viewProject.MultiChoiceView
android:id="@+id/multiChoiceView"
android:layout_width="600px"
android:layout_height="600px"
app:iconSize_="80"
app:viewArea_="600"
app:imagePoints="@array/imagePoints"
android:visibility="visible">
</com.android.viewProject.MultiChoiceView>
MultiChoiceView中如何获取属性值
private int iconSize;
private int viewArea;
private CharSequence imagePointsS[];
public MultiChoiceView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.MultiChoiceView);
resloveTypedArray(typedArray);
typedArray.recycle();
setWillNotDraw(false); // 解决onDraw不执行
// initView();
}
private void resloveTypedArray(TypedArray typedArray) {
iconSize = typedArray.getInt(R.styleable.MultiChoiceView_iconSize_,0);
viewArea = typedArray.getInt(R.styleable.MultiChoiceView_viewArea_,0);
imagePointsS = typedArray.getTextArray(R.styleable.MultiChoiceView_imagePoints);
}
2. 组合控件
我所知道的两种方式:
(1)布局文件中加入其他所需要的原生控件后,在onLayout方法中使用
getChildAt(i).setLayoutParams(layoutParams[i]);
(2)在构造方法中,使用
LayoutParams leftParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
addView(leftButton, leftParams); // 重点
组合控件可参照:AppView.java/MultiChoiceView.java/MyTopBar.java
方式3: 重写 -- 通过重写来实现全新的控件
看例子即可, 参照MyView.java
自定义本身的理解有限,不对的指摘,谢谢。
自定义View与Activity的交互:回调
// 目的:自定义View某个点击事件向传输数据给Activity (广播等方式也是可以的,但回调方式更佳)
// 第一步: 自定义View中增加接口并提供接口设置的方法
private AppIconListener appIconListener;
public interface AppIconListener{
void onAppIconClick(int Index); // 可根据需要传递各种数据类型
}
public void setAppIconListener(AppIconListener listener) {
appIconListener = listener;
}
appIcon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
appIconListener.onAppIconClick(1); // 调用Activity中接口实现的onAppIconClick方法
}
});
// 第二步: Activity或者Fragment中实现接口(接口自定义的方法)
(1)public class MainActivity extends AppCompatActivity implements AppView.AppIconListener
(2)实现接口定义的方法
@Override
public void onAppIconClick(int Index) {
appView.setAppIcon(ApplicationUtil.getIcon(this,"com.android.settings"));
}