- 注解数据类型
注解是写在.java文件中,使用@interface作为关键字, 所以注解也是Java的一种数据类型,从广泛的定义来说,Class、Interface、Enum、Annotation都属于Class类型。
@Documented: 用于标记在生成javadoc时是否将注解包含进去
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
@Target:用于定义注解可以在什么地方使用
TYPE : 类、接口或enum声明
FIELD: 域(属性)声明
METHOD: 方法声明
PARAMETER: 参数声明
CONSTRUCTOR: 构造方法声明
LOCAL_VARIABLE:局部变量声明
ANNOTATION_TYPE:注释类型声明
PACKAGE: 包声明
@Retention:注解的保留位置(枚举RetentionPolicy),RetentionPolicy可选值:
SOURCE:注解仅存在于源码中,在class字节码文件中不包含
CLASS:默认的保留策略,注解在class字节码文件中存在,但运行时无法获得
RUNTIME:注解在class字节码文件中存在,在运行时可以通过反射获取到
@Inherited:声明子类可以继承此注解,如果一个类A使用此注解,则类A的子类也继承此注解,可以看到@Target(ElementType.ANNOTATION_TYPE),它只可以作用在注释类型的声明
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
下面是一个自定义注解的例子。底部弹出dialog里边是一个ListView,通过传入接口返回不同的bean对象添加注解,方便展示,不用再处理不用接口返回的数据。
adapter和一些动画就不贴出来了有需要的可以下载demo
1:需要展示的item
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ShowItemAnn {
}
2:bean类
class User {
@ShowItemAnn //列表中想展示name属性
var name: String? = null
var age: String? = null
var sex: String? = null
}
3:Dialog ,建造者模式,默认最多底部弹框4个item 可以通过设置pageShowItems 属性改变,通过获取并识别对应的注解,parseList通过反射获取要获取的值。
/**
* 注:
* bean需要显示的字段上添加 @ShowItemAnn 注解 并需要写 该字段的 get 方法
*/
public class BottomListDialog extends Dialog {
private Context context;
private BottomListDialog(@NonNull Context context) {
this(context, R.style.bottom_list_dialog_theme);
}
public BottomListDialog(@NonNull Context context, int themeResId) {
super(context, themeResId);
this.context = context;
setParams();
initView();
}
private void setParams() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.dialog_bottom_list);
}
private TextView mTitleTv;
private ListView mListView;
private void initView() {
mTitleTv = findViewById(R.id.bottom_title_tv);
mListView = findViewById(R.id.dialog_bottom_list);
}
/**
* 封装参数类
*/
private static class P<T> {
private Context context;
private String title = null;
private boolean cancelable = true;
private boolean canceledOnTouchOutside = true;
private AdapterView.OnItemClickListener onItemClickListener;
private List<T> items;
private int pageShowItems = 4;//组多同时展示几条列表数据,多的可以滑动
private int activePosition = -1;
}
public static class Builder {
private P p;
public Builder(Context context) {
p = new P();
p.context = context;
}
public Builder setActivePosition(int activePosition) {
p.activePosition = activePosition;
return this;
}
public Builder setSiglePageShowItems(int num) {
p.pageShowItems = num;
return this;
}
public Builder setTitle(String title) {
p.title = title;
return this;
}
public <T> Builder setItems(List<T> items) {
p.items = items;
return this;
}
public Builder setCancelable(boolean setCancelable) {
p.cancelable = setCancelable;
return this;
}
public Builder setCanceledOnTouchOutside(boolean setCanceledOnTouchOutside) {
p.canceledOnTouchOutside = setCanceledOnTouchOutside;
return this;
}
public Builder setOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener) {
p.onItemClickListener = onItemClickListener;
return this;
}
private BottomListDialog create() {
BottomListDialog bottomDialog = new BottomListDialog(p.context);
bottomDialog.setCancelable(p.cancelable);
bottomDialog.setCanceledOnTouchOutside(p.canceledOnTouchOutside);
if (p.title == null) {
bottomDialog.mTitleTv.setVisibility(View.GONE);
} else {
bottomDialog.mTitleTv.setVisibility(View.VISIBLE);
bottomDialog.mTitleTv.setText(p.title);
}
if (p.items != null && p.items.size() > 0) {
BottomListDialogAdapter adapter = new BottomListDialogAdapter(p.context, parseList(p.items), p.activePosition);
int totalHeight = 0;
int num = adapter.getCount() > p.pageShowItems ? p.pageShowItems : adapter.getCount();
for (int i = 0; i < num; i++) {
View listItem = adapter.getView(i, null, bottomDialog.mListView);
//计算子项View 的宽高 //统计所有子项的总高度
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight() + bottomDialog.mListView.getDividerHeight();
}
ViewGroup.LayoutParams params = bottomDialog.mListView.getLayoutParams();
params.height = totalHeight;
bottomDialog.mListView.setLayoutParams(params);
bottomDialog.mListView.setAdapter(adapter);
bottomDialog.mListView.setOnItemClickListener(p.onItemClickListener);
}
Window window = bottomDialog.getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.gravity = Gravity.BOTTOM;
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.BOTTOM;
bottomDialog.getWindow().setAttributes(lp);
return bottomDialog;
}
public BottomListDialog show() {
BottomListDialog dialog = create();
dialog.show();
return dialog;
}
}
private static <T> List<ItemBean> parseList(List<T> lists) {
if (lists == null) {
return null;
}
List<ItemBean> items = new ArrayList<>();
for (int i = 0; i < lists.size(); i++) {
T t = lists.get(i);
Class clazz = t.getClass();
ItemBean bean = new ItemBean();
if (t instanceof String) {
bean.setItem((String) lists.get(i));//如果是String类型的集合 直接添加到list
items.add(bean);
} else {
Field[] fields = clazz.getDeclaredFields();
if (fields != null) {
for (Field field : fields) {
boolean b = field.isAnnotationPresent(ShowItemAnn.class);
if (b) {
String fieldName = field.getName();
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
try {
Method getMethod = clazz.getMethod(getMethodName);
String invokeStr = (String) getMethod.invoke(t);
bean.setItem(invokeStr);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
items.add(bean);
}
}
return items;
}
/**
* 可以在里面添加其他属性 通过注解获取。不需要可以直接删除。list add String即可
*/
static class ItemBean {
String item;
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
}
}
最后在activity中使用
private fun showDialog() {
val userList = ArrayList<User>()
val user = User()
user.name = "Tom"
user.age = "100"
val user1 = User()
user1.name = "Jim"
user1.age = "20"
val user2 = User()
user2.name = "Tim"
user2.age = "100"
val user3 = User()
user3.name = "Hello"
user3.age = "100"
val user4 = User()
user4.name = "Hi"
user4.age = "100"
userList.add(user)
userList.add(user1)
userList.add(user2)
userList.add(user3)
userList.add(user4)
bottomListDialog = BottomListDialog.Builder(this).setTitle("请选择").setItems(userList).setActivePosition(activePosition).setOnItemClickListener { parent, view, position, id ->
//点击item回调
activePosition = position
Toast.makeText(this, userList.get(position).name, Toast.LENGTH_SHORT).show()
bottomListDialog!!.dismiss()
}.show()
}
最后展示如下
点击跳转demo下载地址
补充
- 获取注解的参数
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAnn {
String value();
}
public class MyBean {
@MyAnn("age")
private String name;
private int age;
public MyBean(String name, int age) {
this.name = name;
this.age = age;
}
// 省略 get set 方法
}
MyAnn annotation = field.getAnnotation(MyAnn.class);
if (annotation != null) {
// 获取到 value 之后就可以做自己的事情了
String value = annotation.value();
System.out.println(value);
}