Android读书笔记(四)

自定义控件

首先需要自定义一个布局类,然后通过构造函数借助LayoutInflater动态加载布局文件,从而获得布局文件中的空间,然后为控件添加事件,如图:

public TitleLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.title, this);
        Button titleBack = (Button) findViewById(R.id.title_back);
    }
}

inflate方法的第一个参数是布局文件,第二个参数是指定的父布局。在这个布局文件中可以指定自定义的控件。

ListView

将ListView直接添加在布局文件中,然后在活动中用适配器为ListView添加内容,这里使用数组的方式定义适配器,如图:

  protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FruitAdapter adapter = new ArrayAdapter(MainActivity.this, R.layout.simple_list_item_1, data);
        ListView listView = (ListView) findViewById(R.id.list_view);
        listView.setAdapter(adapter);
    }

adapter中的第二个参数是子布局文件,这里的子布局文件使用了android内置的。

定制ListView界面
  1. 首先我们自定义一个实体类作为适配器的类型
public class Fruit {
    private String name;
    private int imageId;
    public Fruit(String name, int imageId) {
        this.name = name;
        this.imageId = imageId;
    }
    public String getName() { name;}
    public int getImageId() {return imageId;}
}
  1. 然后定义一个ListView的子项布局fruit_item.xml
  2. 自定义适配器
    首先构造函数中传入了三个参数,第一个参数用于传入上下文,第二个参数用于传入子项布局的id从而找到布局资源,第三个参数用于传入实体对象。然后需要重写getView方法,首先我们根据getItem方法得到当前的实例,然后利用LayoutInflater来为ListView添加布局,inflate方法中有三个参数,第一个参数表示子项布局,第二个参数就是ListView本身,需要把第三个参数设置为false,表示不为当前的view添加父布局,因为添加了父布局之后就不能添加到ListView中了。之后就是为布局设置布局资源和实体资源。
public class NewFruitAdapter extends ArrayAdapter<Fruit> {
    private  int resourceId;
    public NewFruitAdapter(@NonNull Context context, int resource, @NonNull List<Fruit> objects) {
        super(context, resource, objects);
        this.resourceId = resource;
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        Fruit fruit = getItem(position);
        View view  = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
        ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
        TextView fruitText = (TextView) view.findViewById(R.id.fruit_name);
        fruitImage.setImageResource(fruit.getImageId());
        fruitText.setText(fruit.getName());
        return view;
    }
}

4.在活动中初始化适配器,并为ListView添加适配器即可。

对ListView进行优化

可以用convertView对布局进行缓存,用ViewHolder对控件实例进行缓存,这样就不会重复加载布局和控件实例了,如图:

    public View getView(int position, View convertView, ViewGroup parent) {
        Fruit fruit = getItem(position); // 获取当前项的Fruit实例
        View view;
        ViewHolder viewHolder;
        if (convertView == null) {
            view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
            viewHolder = new ViewHolder();
            viewHolder.fruitImage = (ImageView) view.findViewById (R.id.fruit_image);
            viewHolder.fruitName = (TextView) view.findViewById (R.id.fruit_name);
            view.setTag(viewHolder); // 将ViewHolder存储在View中
        } else {
            view = convertView;
            viewHolder = (ViewHolder) view.getTag(); // 重新获取ViewHolder
        }
        viewHolder.fruitImage.setImageResource(fruit.getImageId());
        viewHolder.fruitName.setText(fruit.getName());
        return view;
    }

在活动中为ListView添加点击事件

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                                int position, long id) {
            Fruit fruit = fruitList.get(position);
            Toast.makeText(MainActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show();
1. 1.         }
    });

RecycleView

自定义一个FruitAdapter,实现静态的ViewHolder方法,对子项布局的布局文件进行配置,重写onCreateViewHolder,onBindViewHolder,getItemCount方法,onCreateViewHolder为ListView添加布局文件,并配置控件的点击事件,onBindViewHolder添加控件实例,getItemCount返回总共的子项实例。

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder>{

    private List<Fruit> mFruitList;

    static class ViewHolder extends RecyclerView.ViewHolder {
        View fruitView;
        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(View view) {
            super(view);
            fruitView = view;
            fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
            fruitName = (TextView) view.findViewById(R.id.fruit_name);
        }
    }

    public FruitAdapter(List<Fruit> fruitList) {
        mFruitList = fruitList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
        final ViewHolder holder = new ViewHolder(view);
        holder.fruitView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(), "you clicked view " + fruit.getName(), Toast.LENGTH_SHORT).show();
            }
        });
        holder.fruitImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(), "you clicked image " + fruit.getName(), Toast.LENGTH_SHORT).show();
            }
        });
        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitImage.setImageResource(fruit.getImageId());
        holder.fruitName.setText(fruit.getName());
    }

    @Override
    public int getItemCount() {
        return mFruitList.size();
    }

}

recycle还可以通过layoutmanager来实现水平滚动和瀑布流的效果,这是ListView所没有的。

RecycleView的点击事件

首先在适配器中定义一个静态类ViewHolder来处理视图,ViewHolder有一个构造函数,构造函数传入子项的布局,并保存起来,一起传入的还有子项布局中的图片和文字控件。

    static class ViewHolder extends RecyclerView.ViewHolder {
        View fruitView;
        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(View view) {
            super(view);
            fruitView = view;
            fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
            fruitName = (TextView) view.findViewById(R.id.fruit_name);
        }
    }

然后需要重写onCreateViewHolder方法,实例化ViewHolder,重写holder中空间的点击事件,然后返回holder。

 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
        final ViewHolder holder = new ViewHolder(view);
        holder.fruitView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(), "you clicked view " + fruit.getName(), Toast.LENGTH_SHORT).show();
            }
        });
        holder.fruitImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(), "you clicked image " + fruit.getName(), Toast.LENGTH_SHORT).show();
            }
        });
        return holder;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值