思路:用反射的方法,调用listview中的方法,使listview自动滑动一定的距离。
难点:得到要滑动的距离
步骤:
1、监听键盘的弹出,在回调方法中,计算应该滑动的距离,
2、发送message给handler。在handler中用反射调用方法,使listview滑动一定的距离
/**
* Created by 张玉水 on 2014/6/20.
*/
public class NotesAndAskFragment extends BaseFragment implements OnActionViewClickListener {
private PullableListView noteAskListView;
private NoteAndAskAdapter noteAndAskAdapter;
private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener;
private View rootView;
private AutoLinearLayout llView;
private View myView;
//在handler中用反射调用方法,使listview滑动一定的距离
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int rex = (int) msg.obj;
//调用的方法
scrollVertical(noteAskListView, getActivity(), rex + llView.getMeasuredHeight());
ToastUtil.showNormalShortToast(“–total–”+( rex + llView.getMeasuredHeight()));
myView = null;
}
};
private boolean isScroll = false;
private JSONObject mJsonObject;
private AutoLinearLayout all_newnote;
private EditText et_newnote;
private Button btn_newnote;
private String bcType;
private Boolean isAddNewNote=true;
private String objectId;
private String fUserId;
private Boolean isFromHome;
@Override
protected View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_noteandask, container, false);
return rootView;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
**//键盘弹出,将relativelayout悬浮的输入框和回复按钮顶上去的必要方法配置**
getActivity().getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
}
@Override
protected void initData(View view, Bundle savedInstanceState) {
//setTitleColor(view,R.color.merchanttextcolor);
noteAskListView = (PullableListView) view.findViewById(R.id.note_ask_listview);
noteAndAskAdapter = new NoteAndAskAdapter(getContext());
noteAndAskAdapter.setOnActionViewClickListener(this);
noteAskListView.setAdapter(noteAndAskAdapter);
((View) view.findViewById(R.id.actionbar_back))
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
rootView.getViewTreeObserver()
.removeGlobalOnLayoutListener(
onGlobalLayoutListener);
onGlobalLayoutListener = null;
popBackStack();
}
});
llView = (AutoLinearLayout) view.findViewById(R.id.edittext_btn);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.note_num:
Integer tag = (Integer) v.getTag();
showInputKeyboard(tag);
myView = v;
isScroll = true;
break;
case R.id.btn_newnote:
addNewNote();
break;
// case R.id.delete:
// Integer tagItemDelete = (Integer) v.getTag();
// showDeleteItemDelog(tagItemDelete);
// break;
case R.id.myNoteAskId:// 10000 点击的是动态添加textview的回复
clickTextReply(v);
break;
}
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// 比较Activity根布局与当前布局的大小
int heightDiff = rootView.getRootView().getHeight()
- rootView.getHeight();
if (et_newnote.hasFocus()){
//当增加新的noteAndAsk的时候。不要显示llview。直接return掉
return;
}
if (heightDiff > 500) {
// 大小超过100时,一般为显示虚拟键盘事件
// ToastUtil.showNormalShortToast(rootView.getRootView().getHeight()+"显示键盘"+rootView.getHeight());
llView.setVisibility(View.VISIBLE);
llView.findViewById(R.id.et).requestFocus();
if (isScroll && myView != null) {
//在回调事件中,计算应该滑动的距离
int offset = getOffset(myView, heightDiff);
//ToastUtil.showNormalShortToast("==offset==:"+offset);
Message message = new Message();
message.obj = offset;
//发送消息
handler.sendMessage(message);
isScroll = false;
}
all_newnote.setVisibility(View.GONE);
} else {
// 大小小于100时,为不显示虚拟键盘或虚拟键盘隐藏
// ToastUtil.showNormalShortToast("隐藏键盘");
llView.setVisibility(View.GONE);
}
}
};
rootView.getViewTreeObserver().addOnGlobalLayoutListener(
onGlobalLayoutListener);
}
/**
* 显示键盘和输入框
*
* @param tag
* @author 张玉水
* @date 2016-5-16 下午6:41:11 TODO
*/
private void showInputKeyboard(final int... tag) {
llView.setVisibility(View.VISIBLE);
final EditText et = (EditText) llView.findViewById(R.id.et);
et.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
et.requestFocus();
Button btn = (Button) llView.findViewById(R.id.btn_response);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String content = et.getText().toString().trim();
if (!TextUtils.isEmpty(content)) {
// 1、将评论内容发送到服务器,2、并在返回成功的回调中更新UI
sendCommentToService(content, noteAndAskAdapter.getData(), tag);
}
llView.setVisibility(View.GONE);
KeyboardUtil.hideKeyBoard(getActivity());
et.setText("");
}
});
KeyboardUtil.showKeyBoard(getActivity());
}
//得到条目应该滚动的距离
public int getOffset(View v, int heightDiff) {
int offset = getLocationBottom(v) - (Config.displayHeight - heightDiff);
AutoLinearLayout ll_note_ask_content = (AutoLinearLayout) v.getRootView().findViewById(R.id.ll_note_ask_content);
if (ll_note_ask_content==null){
ll_note_ask_content= (AutoLinearLayout) ((ArrayList)v.getTag()).get(1);
}
ll_note_ask_content.measure(0,0);
int measuredHeight = ll_note_ask_content.getMeasuredHeight();
return offset+measuredHeight;
}
// //得到条目底部到 屏幕的距离
public int getLocationBottom(View v) {
int[] loc = new int[4];
int[] location = new int[2];
v.getLocationOnScreen(location);
loc[0] = location[0];
loc[1] = location[1];
int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
v.measure(w, h);
loc[2] = v.getMeasuredWidth();
loc[3] = v.getMeasuredHeight()+loc[1];//底部距离 屏幕上边的 高
//base = computeWH();
return loc[3];
}
/**
* scroll Vertical
*
* @param y 垂直滑动的距离
*/
public void scrollVertical(final ListView listView, Activity activity, final int y) {
if (listView == null)
return;
activity.runOnUiThread(new Runnable() { //执行自动化测试的时候模拟滑动需要进入UI线程操作
@Override
public void run() {
invokeMethod(listView, "trackMotionScroll", new Object[]{0, -y}, new Class[]{int.class, int.class});
}
});
}
/**
* 遍历当前类以及父类去查找方法,例子,写的比较简单
*
* @param object
* @param methodName
* @param params
* @param paramTypes
* @return
*/
public Object invokeMethod(Object object, String methodName, Object[] params, Class[] paramTypes) {
Object returnObj = null;
if (object == null) {
return null;
}
Class cls = object.getClass();
Method method = null;
for (; cls != Object.class; cls = cls.getSuperclass()) { //因为取的是父类的默认修饰符的方法,所以需要循环找到该方法
try {
method = cls.getDeclaredMethod(methodName, paramTypes);
break;
} catch (NoSuchMethodException e) {
// e.printStackTrace();
} catch (SecurityException e) {
// e.printStackTrace();
}
}
if (method != null) {
method.setAccessible(true);
try {
returnObj = method.invoke(object, params);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return returnObj;
}
}