您的位置:首页 > 产品设计 > UI/UE

Android进阶——GridView实现可长按item显示可删除的小图标的UI

2016-10-04 10:53 501 查看

引言

以前刚刚入门的时候,听别人说Adapter是一个好东西,一时没法体会……结合最近项目中有个需求,就是在界面显示已经配对了的设备的图标并且可以直接在显示界面做更新操作,包括删除,移动和组合的效果,并且长按时在所有item的右上角显示删除的小图标,类似于QQ的那种效果。最后利用GridView(项目中我用的是RecycleView)实现了,又正好整个博客系列中没有细讲过GridView这一知识点,为了知识体系的完整,遂有了以下的文章,重点是分享下自己解决这个问题的思想。

一、GridView概述

GridView与之前我们熟悉的ListView(现在基本已被RecycleView所替代)一样都是比较常用的多控件布局,他们都是AdapterView的子类,不同的是GridView可以一行显示多个item,具体显示多少个item取决于开发者的设置,实现网格布局的首选。与其他AdapterView的原理一样,可以理解为我们的GridView和ItemView提供了UI框架,而Adapter则是往这个框架里填充数据,所以每一次GridView的每一条item生成到的时候都会触发Adpater相关的生命周期方法。

二、GridView的应用

GridView的使用相信那已不是难点了,有些时候常常被困扰在一些看似酷炫高深的效果上,其实很多时候并不是不会也许是对于一些原理性的东西理解不透彻,很多初学者只是停留在会用,只知其然而不知其所以然,所以一以为过来人的身份建议初学者不要只满足于按照书本或者视频敲了代码,至少要懂得一个大致的原理流程,不至于以后需要实现稍微复杂的效果而一脸茫然。说了那么多,其实一开始看到这个效果,我也不是一下子就想到了方案的,下面就分享下思路历程,首先想到的是直接自定义View把它自己画出来,后面和产品一聊,果断放弃了这个方案,因为用户配对的设备数量(从服务器传过来)可能会有很多而且后期还需要实现自由移动,其实我心里一开始就有了思路的,只是想偷懒不想去做那么多的逻辑判断,可最后还是使用了现在的方案。核心思想就是:Adapter是个好东西,动态更新Adapter进而去更新UI。直接不好实现间接也是可以的。最后的效果大概是这样的(自由移动的代码被我精简掉了,而且这个demo是有小bug的,在项目中我已经解决了,主要是为了分享下体会和思想):



1、首先是定义我们Activity的布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="crazymo.train.gridviewtraining.MainActivity">

<GridView
android:id="@+id/id_grid_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnWidth="@dimen/activity_horizontal_margin"
android:numColumns="2">
</GridView>
</RelativeLayout>


2、接着是GirdView item的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="wrap_content">
<FrameLayout
android:id="@+id/id_img_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<ImageView
android:id="@+id/id_img_src"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="20dp"
android:src="@mipmap/ic_item"/>
<ImageView
android:id="@+id/id_imv_dele"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_margin="10dp"
android:layout_gravity="top|right"
android:layoutDirection="rtl"
android:src="@mipmap/ic_dele"
/>
<TextView
android:id="@+id/id_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_vertical|center"
android:layout_marginBottom="0dp"
android:textSize="24sp"
android:text="img name"/>
</FrameLayout>
</LinearLayout>


3、重点来了Adapter和Activity的实现

其实这只是一种方式,作为简单的demo,我直接是把数据源写死了,而且为了避免去封装bean什么的,我使用的是一个全局变量来标识是否需要显示删除小图标,真正在我的项目中由于要和服务器通信我使用的是把这一个字段一起封装到Bean中,然后在Adapter里判断,在Activity直接去更新Adpter再notifyDataSetChanged,但是核心思路是一样一样的。

package crazymo.train.gridviewtraining;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import crazymo.train.gridviewtraining.util.Util;

import static android.widget.AdapterView.OnItemClickListener;
import static android.widget.AdapterView.OnItemLongClickListener;
/**
* Created by CrazyMo on 2016/10/03.
*/
public class MainActivity extends AppCompatActivity {
private boolean isShowDelete = false;
private List names=new ArrayList();
private List imgs=new ArrayList();
private MainAdapter mainAdapter;
//@BindView(R.id.id_grid_main)
private GridView gridView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//ButterKnife.bind(this);
gridView= (GridView) findViewById(R.id.id_grid_main);
init();
mainAdapter=new MainAdapter(MainActivity.this,names,imgs);
gridView.setAdapter(mainAdapter);
gridView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mainAdapter.setClickItemIndex(position);
Log.d("TAG", "onItemClick: "+position);
}
});
gridView.setOnItemLongClickListener(new OnItemLongClickListener() {

@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (isShowDelete) {
isShowDelete = false;
} else {
isShowDelete = true;
}
Log.d("TAG","onItemLongClicked");
mainAdapter.setShowDelete(isShowDelete);
mainAdapter.setClickItemIndex(position);
return true;
}
});
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return super.onKeyDown(keyCode, event);
}

@Override
public void onBackPressed() {
if (mainAdapter.getShowDelete() == true) {
mainAdapter.setShowDelete(false);
} else {
finish();
}
}

private void init(){
initImg();
initName();
}

private void initImg() {
imgs.add(R.mipmap.ic_item);
imgs.add(R.mipmap.ic_item1);
imgs.add(R.mipmap.ic_item2);
imgs.add(R.mipmap.ic_item3);
imgs.add(R.mipmap.ic_item4);
imgs.add(R.mipmap.ic_item5);

}
private void initName(){
for(int i=0;i<6;i++) {
names.add("img name"+i);
}
}

class MainAdapter extends BaseAdapter{
private LayoutInflater inflater;
private List names;
private List icons;
private Context context;
private ImageView img;
private View deleteView;
private boolean isShowDelete;//根据这个变量来判断是否显示删除图标,true是显示,false是不显示
private int clickItemIndex=-1;//根据这个变量来辨识选中的current值

public MainAdapter(Context context,List names,List icons) {
inflater=LayoutInflater.from(context);
this.context=context;
this.names=names;
this.icons = icons;
}

protected void setShowDelete(boolean isShowDelete){
this.isShowDelete=isShowDelete;
notifyDataSetChanged();
}
protected boolean getShowDelete(){
return isShowDelete;
}
protected void setClickItemIndex(int postion){
this.clickItemIndex=postion;
}
@Override
public int getCount() {
return icons.size();
}

@Override
public Object getItem(int position) {
return icons.get(position);
}

@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder=null;
if(convertView==null){
convertView=inflater.inflate(R.layout.girdv_item_mian,null);
viewHolder=new ViewHolder();
viewHolder.name= (TextView) convertView.findViewById(R.id.id_name);
viewHolder.icon= (ImageView) convertView.findViewById(R.id.id_img_src);
viewHolder.dele= (ImageView) convertView.findViewById(R.id.id_imv_dele);
convertView.setTag(viewHolder);
}else{
viewHolder= (ViewHolder) convertView.getTag();
}
viewHolder.name.setText(names.get(position).toString());
viewHolder.icon.setBackgroundResource((Integer) icons.get(position));
viewHolder.icon.setClickable(false);
viewHolder.dele.setVisibility(isShowDelete?View.VISIBLE:View.GONE);
if(viewHolder.dele.getVisibility()==View.VISIBLE) {
if (position == clickItemIndex) {
viewHolder.dele.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "onClick: "+clickItemIndex);
Util.removeListEmlement(icons, (Integer) icons.get(clickItemIndex));
Util.removeListEmlement(names, names.get(clickItemIndex).toString());
notifyDataSetChanged();
}
});
}
}
return convertView;
}
}
class ViewHolder{
TextView name;
ImageView icon;
ImageView dele;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐