项目需求中遇到了单选与多选以及横向listview的需求,问题解决了,下面简单记录一下实现方式。完整项目demo由于某种原因我就不贴出来了,我把那一模块实现代码贴出来,供大家参考,数据部分获取我会说明,本文采用的json格式的解析和XUtils网络访问框架获取数据的,当然这不是重点。下面是实现效果:
Oh my,没想到美工的效果图这么大..................O(∩_∩)O~~
整个模块我封装在了showMoveDialog()方法里面了,简单说一下实现方法:
GrideView单选:我将要显示的信息封装成一个个对象,里面添加了一条属性用于标记是否选择了,因为单选可以取消的所以显示红点的标准就是,用户当前选择了这个item而且它的状态是selected = false;
ListView多选:在adapter中通过存储选择item的位置和状态改变实现UI显示,为了便于显示选择的都有谁,也封装了一个item的对象并添加选择状态的属性。
我们来看:
1.布局:
① 对话框布局layout_remove_dialog.xml
② 选择的item布局
GrideView的item_photo_remove.xml
HorizontalListView的item_photo_remove_stu.xml
and “”<-----------我是图片
2.逻辑
①。横向的ListView控件
package com.jshjw.mywidget;
import java.util.LinkedList;
import java.util.Queue;
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Checkable;
import android.widget.ListAdapter;
import android.widget.Scroller;
public class HorizontalListView extends AdapterView {
public boolean mAlwaysOverrideTouch = true;
protected ListAdapter mAdapter;
private int mLeftViewIndex = -1;
private int mRightViewIndex = 0;
protected int mCurrentX;
protected int mNextX;
private int mMaxX = Integer.MAX_VALUE;
private int mDisplayOffset = 0;
protected Scroller mScroller;
private GestureDetector mGesture;
private Queue mRemovedViewQueue = new LinkedList();
private OnItemSelectedListener mOnItemSelected;
private OnItemClickListener mOnItemClicked;
private OnItemLongClickListener mOnItemLongClicked;
private boolean mDataChanged = false;
public HorizontalListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
private synchronized void initView() {
mLeftViewIndex = -1;
mRightViewIndex = 0;
mDisplayOffset = 0;
mCurrentX = 0;
mNextX = 0;
mMaxX = Integer.MAX_VALUE;
mScroller = new Scroller(getContext());
mGesture = new GestureDetector(getContext(), mOnGesture);
}
@Override
public void setOnItemSelectedListener(
AdapterView.OnItemSelectedListener listener) {
mOnItemSelected = listener;
}
@Override
public void setOnItemClickListener(AdapterView.OnItemClickListener listener) {
mOnItemClicked = listener;
}
@Override
public void setOnItemLongClickListener(
AdapterView.OnItemLongClickListener listener) {
mOnItemLongClicked = listener;
}
private DataSetObserver mDataObserver = new DataSetObserver() {
@Override
public void onChanged() {
synchronized (HorizontalListView.this) {
mDataChanged = true;
}
invalidate();
requestLayout();
}
@Override
public void onInvalidated() {
reset();
invalidate();
requestLayout();
}
};
@Override
public ListAdapter getAdapter() {
return mAdapter;
}
@Override
public View getSelectedView() {
// TODO: implement
return null;
}
@Override
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mDataObserver);
}
mAdapter = adapter;
mAdapter.registerDataSetObserver(mDataObserver);
reset();
}
private synchronized void reset() {
initView();
removeAllViewsInLayout();
requestLayout();
}
@Override
public void setSelection(int position) {
int positionX = position * this.getWidth();
int maxWidth = this.getChildCount() * this.getWidth();
if (positionX <= 0) {
positionX = 0;
}
if (positionX > maxWidth) {
positionX = maxWidth;
}
scrollTo(positionX);
}
private void addAndMeasureChild(final View child, int viewPos) {
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
}
addViewInLayout(child, viewPos, params, true);
child.measure(
MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
}
@Override
protected synchronized void onLayout(boolean changed, int left, int top,
int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mAdapter == null) {
return;
}
if (mDataChanged) {
int oldCurrentX = mCurrentX;
initView();
removeAllViewsInLayout();
mNextX = oldCurrentX;
mDataChanged = false;
}
if (mScroller.computeScrollOffset()) {
int scrollx = mScroller.getCurrX();
mNextX = scrollx;
}
if (mNextX <= 0) {
mNextX = 0;
mScroller.forceFinished(true);
}
if (mNextX >= mMaxX) {
mNextX = mMaxX;
mScroller.forceFinished(true);
}
int dx = mCurrentX - mNextX;
removeNonVisibleItems(dx);
fillList(dx);
positionItems(dx);
mCurrentX = mNextX;
if (!mScroller.isFinished()) {
post(new Runnable() {
@Override
public void run() {
requestLayout();
}
});
}
}
private void fillList(final int dx) {
int edge = 0;
View child = getChildAt(getChildCount() - 1);
if (child != null) {
edge = child.getRight();
}
fillListRight(edge, dx);
edge = 0;
child = getChildAt(0);
if (child != null) {
edge = child.getLeft();
}
fillListLeft(edge, dx);
}
private void fillListRight(int rightEdge, final int dx) {
while (rightEdge + dx < getWidth()
&& mRightViewIndex < mAdapter.getCount()) {
View child = mAdapter.getView(mRightViewIndex,
mRemovedViewQueue.poll(), this);
addAndMeasureChild(child, -1);
rightEdge += child.getMeasuredWidth();
if (mRightViewIndex == mAdapter.getCount() - 1) {
mMaxX = mCurrentX + rightEdge - getWidth();
}
if (mMaxX < 0) {
mMaxX = 0;
}
mRightViewIndex++;
}
}
private void fillListLeft(int leftEdge, final int dx) {
while (leftEdge + dx > 0 && mLeftViewIndex >= 0) {
View child = mAdapter.getView(mLeftViewIndex,
mRemovedViewQueue.poll(), this);
addAndMeasureChild(child, 0);
leftEdge -= child.getMeasuredWidth();
mLeftViewIndex--;
mDisplayOffset -= child.getMeasuredWidth();
}
}
private void removeNonVisibleItems(final int dx) {
View child = getChildAt(0);
while (child != null && child.getRight() + dx <= 0) {
mDisplayOffset += child.getMeasuredWidth();
mRemovedViewQueue.offer(child);
removeViewInLayout(child);
mLeftViewIndex++;
child = getChildAt(0);
}
child = getChildAt(getChildCount() - 1);
while (child != null && child.getLeft() + dx >= getWidth()) {
mRemovedViewQueue.offer(child);
removeViewInLayout(child);
mRightViewIndex--;
child = getChildAt(getChildCount() - 1);
}
}
private void positionItems(final int dx) {
if (getChildCount() > 0) {
mDisplayOffset += dx;
int left = mDisplayOffset;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
int childWidth = child.getMeasuredWidth();
child.layout(left, 0, left + childWidth,
child.getMeasuredHeight());
left += childWidth + child.getPaddingRight();
}
}
}
public synchronized void scrollTo(int x) {
mScroller.startScroll(mNextX, 0, x - mNextX, 0);
requestLayout();
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean handled = super.dispatchTouchEvent(ev);
handled |= mGesture.onTouchEvent(ev);
return handled;
}
protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
synchronized (HorizontalListView.this) {
mScroller.fling(mNextX, 0, (int) -velocityX, 0, 0, mMaxX, 0, 0);
}
requestLayout();
return true;
}
protected boolean onDown(MotionEvent e) {
mScroller.forceFinished(true);
return true;
}
private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
return HorizontalListView.this.onDown(e);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return HorizontalListView.this
.onFling(e1, e2, velocityX, velocityY);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
synchronized (HorizontalListView.this) {
mNextX += (int) distanceX;
}
requestLayout();
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (isEventWithinView(e, child)) {
if (mOnItemClicked != null) {
mOnItemClicked.onItemClick(HorizontalListView.this,
child, mLeftViewIndex + 1 + i,
mAdapter.getItemId(mLeftViewIndex + 1 + i));
}
if (mOnItemSelected != null) {
mOnItemSelected.onItemSelected(HorizontalListView.this,
child, mLeftViewIndex + 1 + i,
mAdapter.getItemId(mLeftViewIndex + 1 + i));
}
break;
}
}
return true;
}
@Override
public void onLongPress(MotionEvent e) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (isEventWithinView(e, child)) {
if (mOnItemLongClicked != null) {
mOnItemLongClicked.onItemLongClick(
HorizontalListView.this, child, mLeftViewIndex
+ 1 + i,
mAdapter.getItemId(mLeftViewIndex + 1 + i));
}
break;
}
}
}
private boolean isEventWithinView(MotionEvent e, View child) {
Rect viewRect = new Rect();
int[] childPosition = new int[2];
child.getLocationOnScreen(childPosition);
int left = childPosition[0];
int right = left + child.getWidth();
int top = childPosition[1];
int bottom = top + child.getHeight();
viewRect.set(left, top, right, bottom);
return viewRect.contains((int) e.getRawX(), (int) e.getRawY());
}
};
}
②。两个item的实体类
package com.jshjw.teschoolforandroidmobile.vo;
public class MoveSceneInfo {
private boolean isSelect = false;
private String sceneName;
private String sceneType;
public MoveSceneInfo() {
}
public MoveSceneInfo(boolean isSelect, String sceneName, String sceneType) {
super();
this.isSelect = isSelect;
this.sceneName = sceneName;
this.sceneType = sceneType;
}
public boolean isSelect() {
return isSelect;
}
public void setSelect(boolean isSelect) {
this.isSelect = isSelect;
}
public String getSceneName() {
return sceneName;
}
public void setSceneName(String sceneName) {
this.sceneName = sceneName;
}
public String getSceneType() {
return sceneType;
}
public void setSceneType(String sceneType) {
this.sceneType = sceneType;
}
@Override
public String toString() {
return "MoveSceneInfo [isSelect=" + isSelect + ", sceneName="
+ sceneName + ", sceneType=" + sceneType + "]";
}
}
package com.jshjw.teschoolforandroidmobile.vo;
public class MoveStuInfo {
private boolean isSelect;
private String stuName;
private String stuId;
public MoveStuInfo() {
}
public MoveStuInfo(boolean isSelect, String stuName, String stuId) {
super();
this.isSelect = isSelect;
this.stuName = stuName;
this.stuId = stuId;
}
public boolean isSelect() {
return isSelect;
}
public void setSelect(boolean isSelect) {
this.isSelect = isSelect;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getStuId() {
return stuId;
}
public void setStuId(String stuId) {
this.stuId = stuId;
}
@Override
public String toString() {
return "MoveStuInfo [isSelect=" + isSelect + ", stuName=" + stuName
+ ", stuId=" + stuId + "]";
}
}
showMoveDialog()方法:
private void showRemoveDialog() {
View view = LayoutInflater.from(this).inflate(R.layout.layout_remove_dialog, null);
view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(view);
final AlertDialog dialog = builder.create();
dialog.show();
Button cancleBtn = (Button) view.findViewById(R.id.cancle);
Button moveBtn = (Button) view.findViewById(R.id.sure);
sceneGridView = (GridView) view.findViewById(R.id.select_scene_gv);
WindowManager windowManager = (WindowManager) MyPhotoInformation.this.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(metrics);
sceneGridView.setColumnWidth(metrics.widthPixels / 3);
mHorizontalListView = (HorizontalListView) view.findViewById(R.id.select_stu_lv);
if (sceneName != null) {
moveSceneInfos = new ArrayList();
for (int i = 0; i < sceneName.length; i++) {
MoveSceneInfo moveSceneInfo = new MoveSceneInfo();
moveSceneInfo.setSelect(false);
moveSceneInfo.setSceneName(sceneName[i]);
moveSceneInfo.setSceneType(sceneType[i]);
moveSceneInfos.add(moveSceneInfo);
}
mSelectSceneAdapter = new SelectSceneAdapter(MyPhotoInformation.this, moveSceneInfos);
sceneGridView.setAdapter(mSelectSceneAdapter);
}
if (stuName != null) {
moveStuInfos = new ArrayList();
for (int i = 1; i < stuName.length; i++) {
MoveStuInfo moveStuInfo = new MoveStuInfo();
moveStuInfo.setSelect(false);
moveStuInfo.setStuName(stuName[i]);
moveStuInfo.setStuId(stuId[i]);
moveStuInfos.add(moveStuInfo);
}
mHorizontalListViewAdapter = new HorizontalListViewAdapter(MyPhotoInformation.this, moveStuInfos);
mHorizontalListView.setAdapter(mHorizontalListViewAdapter);
}
sceneGridView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> arg0, View view, int arg2,
long arg3) {
sceneImageViewSelect = (ImageView) view.findViewById(R.id.select_dot);
if (sceneImageViewSelect.getVisibility() == View.INVISIBLE) {
}else {
move_to_scene_type = "";
}
mSelectSceneAdapter.setSelect(arg2);
mSelectSceneAdapter.notifyDataSetChanged();
}
});
mHorizontalListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> arg0, View view, int arg2,
long arg3) {
ViewHolder holder = (ViewHolder) view.getTag();
holder.cb.toggle();
HorizontalListViewAdapter.getIsSelected().put(arg2, holder.cb.isChecked());
if (holder.cb.isChecked() == true) {
moveStuInfos.get(arg2).setSelect(true);
} else {
moveStuInfos.get(arg2).setSelect(false);
}
}
});
cancleBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
dialog.dismiss();
}
});
moveBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
StringBuffer sb = new StringBuffer();
for (SceneInformation info : scene_information) {
if (info.isSelected()) {
sb.append(info.getId() + ",");
}
}
String ids = sb.deleteCharAt(sb.length() - 1).toString();
for (int i = 0; i < moveSceneInfos.size(); i++) {
if (moveSceneInfos.get(i).isSelect()) {
move_to_scene_type = moveSceneInfos.get(i).getSceneType();
}
}
if (move_to_scene_type == "") {
Toast.makeText(MyPhotoInformation.this, "请选择场景!", Toast.LENGTH_SHORT).show();
return;
}
int count = 0;
StringBuffer jxt_code_temp = new StringBuffer();
for (int i = 0; i < moveStuInfos.size(); i++) {
if (moveStuInfos.get(i).isSelect()) {
count ++;
jxt_code_temp.append(moveStuInfos.get(i).getStuId() + ",");
}
}
if (moveSceneInfos.size() == count) {
move_to_jxt_code = "all";
}else if (jxt_code_temp.toString() == "" || jxt_code_temp.toString() == null) {
Toast.makeText(MyPhotoInformation.this, "请选择学生!", Toast.LENGTH_SHORT).show();
return;
}else {
move_to_jxt_code = jxt_code_temp.deleteCharAt(jxt_code_temp.length() - 1).toString();
}
new Api(MyPhotoInformation.this, new CallBack() {
@Override
public void onSuccess(String response) {
dialog.dismiss();
try {
JSONObject jsonObject = new JSONObject(response);
if (jsonObject.has("reCode") && "0".equals(jsonObject.getString("reCode"))) {
Toast.makeText(MyPhotoInformation.this, "移动成功", Toast.LENGTH_SHORT).show();
getData(true);
}
} catch (JSONException e) {
Toast.makeText(MyPhotoInformation.this, "获取数据失败",
Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(String message) {
dialog.dismiss();
Toast.makeText(MyPhotoInformation.this, "获取数据失败",
Toast.LENGTH_SHORT).show();
}
}).movePhotos(ids, move_to_scene_type, move_to_jxt_code,
getIntent().getExtras().getString("schid"),
getIntent().getExtras().getString("recvid"),
getIntent().getExtras().getString("recvname"),
getIntent().getExtras().getString("areaid"));
}
});
}
private String flag_mark;
////////////////////////////////////////////////////////////////////////
private GridView sceneGridView;
private HorizontalListView mHorizontalListView;
private SelectSceneAdapter mSelectSceneAdapter;
private HorizontalListViewAdapter mHorizontalListViewAdapter;
private String areaId;
private String[] sceneName = {"上课表现", "午餐点心", "课间游戏",
"精彩表演", "郊游活动", "节日庆典",
"午间休息", "宝贝作品", "其他" };
private String[] sceneType = {"SKBX", "WCDX", "KJYX",
"JCBY", "JYHD", "JRQD",
"WJXX", "BBZP", "QT" };;
private String[] stuName;
private String[] stuId;
private String move_to_scene_type = "";
private String move_to_jxt_code = "";
private ArrayList moveSceneInfos;
private ArrayList moveStuInfos;
private String[] stuName;
private String[] stuId;
这两个都是从上一界面传过来的数据,基本形式和上面已知的数组一样
下面就是两个adapter的处理了:
package com.jshjw.teschoolforandroidmobile.adapter;
import java.util.ArrayList;
import com.jshjw.child.activity.R;
import com.jshjw.teschoolforandroidmobile.vo.MoveSceneInfo;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class SelectSceneAdapter extends BaseAdapter {
private ArrayList sceneNameList;
private LayoutInflater mInflater;
private int index = -1;
public SelectSceneAdapter(Context context, ArrayList moveSceneInfos) {
mInflater = LayoutInflater.from(context);
this.sceneNameList = moveSceneInfos;
}
public void setSelect(int index) {
this.index = index;
}
@Override
public int getCount() {
return sceneNameList.size();
}
@Override
public Object getItem(int arg0) {
return sceneNameList.get(arg0);
}
@Override
public long getItemId(int arg0) {
return arg0;
}
@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
View view = arg1;
ViewHolder viewHolder = null;
if (view == null) {
view = mInflater.inflate(R.layout.item_photo_remove, null);
viewHolder = new ViewHolder();
viewHolder.dot = (ImageView) view.findViewById(R.id.select_dot);
viewHolder.sceneTextView = (TextView) view.findViewById(R.id.select_tv);
view.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.sceneTextView.setText(sceneNameList.get(arg0).getSceneName());
if (arg0 == index && !sceneNameList.get(arg0).isSelect()) {
sceneNameList.get(arg0).setSelect(true);
viewHolder.dot.setVisibility(View.VISIBLE);
}else {
viewHolder.dot.setVisibility(View.INVISIBLE);
sceneNameList.get(arg0).setSelect(false);
}
return view;
}
private static class ViewHolder{
private ImageView dot;
private TextView sceneTextView;
}
}
package com.jshjw.teschoolforandroidmobile.adapter;
import java.util.ArrayList;
import java.util.HashMap;
import com.jshjw.child.activity.R;
import com.jshjw.teschoolforandroidmobile.vo.MoveStuInfo;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.TextView;
public class HorizontalListViewAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ArrayList stuNameList;
private static HashMap isSelected;
@SuppressLint("UseSparseArrays")
public HorizontalListViewAdapter(Context context, ArrayList moveStuInfos) {
mInflater = LayoutInflater.from(context);
this.stuNameList = moveStuInfos;
this.isSelected = new HashMap();
initDate();
}
private void initDate() {
for (int i = 0; i < stuNameList.size(); i++) {
getIsSelected().put(i, false);
}
}
@Override
public int getCount() {
return stuNameList.size();
}
@Override
public Object getItem(int arg0) {
return stuNameList.get(arg0);
}
@Override
public long getItemId(int arg0) {
return arg0;
}
@Override
public View getView(final int position, View arg1, ViewGroup arg2) {
View view = arg1;
ViewHolder viewHolder = null;
if (view == null) {
view = mInflater.inflate(R.layout.item_photo_remove_stu, null);
viewHolder = new ViewHolder();
viewHolder.cb = (CheckBox) view.findViewById(R.id.item_cb);
viewHolder.sceneTextView = (TextView) view.findViewById(R.id.select_tv_stu);
view.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.sceneTextView.setText(stuNameList.get(position).getStuName());
viewHolder.cb.setChecked(getIsSelected().get(position));
return view;
}
public static HashMap getIsSelected() {
return isSelected;
}
public static void setIsSelected(HashMap isSelected) {
HorizontalListViewAdapter.isSelected = isSelected;
}
public static class ViewHolder{
public CheckBox cb;
private TextView sceneTextView;
}
}
—— lovey hy.
【欢迎上码】
【微信公众号搜索 h2o2s2】