本博客运用GridView、ViewFlipper、ImageView等进行界面布局,使用自定义适配器显示图片。通过GestureDetector事件监听,可手势滑动查看图片,并设置图片左右滑动出、入的效果。
同时这也是中国大学慕课移动终端应用开发的网课作业12,我会持续更新我的作业,如果有需要关注一下吧
说明
1.图片资源来自于阿里巴巴矢量图标库
2.部分内容参考了此篇博客
3.注意版本和AndroidManifest.xml文件的修改
效果图
代码部分
主Activity:HomeworkActivity.java
此Activity需要在AndroidManifest.xml上注册并设置为首页
public class HomeworkActivity extends Activity implements GestureDetector.OnGestureListener{
private GridView mGridView1,mGridView2,mGridView3,mGridView4;//定义四个grid view
private int[] mImages1,mImages2,mImages3,mImages4;//定义四个数据集
private HomeWorkAdapter mAdapter1,mAdapter2,mAdapter3,mAdapter4; //定义四个适配器
private GestureDetector mGestureDetector;//定义手势监测
private ViewFlipper mViewFlipper;//定义view flipper
private Animation[] mAnimations;//定义过渡动画数组
private final int MIN_DISTANCE = 50;//定义触发滑动最短距离
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_homework);
mViewFlipper = findViewById(R.id.homework_view_flipper);
initData();
initView();
initAnim();
mGestureDetector = new GestureDetector(this,this);
}
//初始化动画数组
private void initAnim(){
mAnimations = new Animation[]{
AnimationUtils.loadAnimation(this,R.anim.left_in)
,AnimationUtils.loadAnimation(this,R.anim.left_out)
,AnimationUtils.loadAnimation(this,R.anim.right_in)
,AnimationUtils.loadAnimation(this,R.anim.right_out)
};
}
//初始化子页面
private void initView(){
mGridView1 = findViewById(R.id.homework_grid_view1);
mAdapter1 = new HomeWorkAdapter(mImages1,HomeworkActivity.this);
mGridView1.setAdapter(mAdapter1);
mGridView1.setNumColumns(3);
//由于子view布局覆盖了父view的监听事件,所以设置子view的监听也是gestureDetector.onTouchEvent()
mGridView1.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
mGridView2 = findViewById(R.id.homework_grid_view2);
mAdapter2 = new HomeWorkAdapter(mImages2,HomeworkActivity.this);
mGridView2.setAdapter(mAdapter2);
mGridView2.setNumColumns(3);
mGridView2.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
mGridView3 = findViewById(R.id.homework_grid_view3);
mAdapter3 = new HomeWorkAdapter(mImages3,HomeworkActivity.this);
mGridView3.setAdapter(mAdapter3);
mGridView3.setNumColumns(3);
mGridView3.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
mGridView4 = findViewById(R.id.homework_grid_view4);
mAdapter4 = new HomeWorkAdapter(mImages4,HomeworkActivity.this);
mGridView4.setAdapter(mAdapter4);
mGridView4.setNumColumns(3);
mGridView4.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
}
//初始化 数据
private void initData(){
int a = R.drawable.img1;
int b = R.drawable.img2;
int c = R.drawable.img3;
int d = R.drawable.img4;
mImages1 = new int[]{a, a, a, a, a, a, a, a, a, a, a, a};
mImages2 = new int[]{b, b, b, b, b, b, b, b, b, b, b, b};
mImages3 = new int[]{c, c, c, c, c, c, c, c, c, c, c, c};
mImages4 = new int[]{d, d, d, d, d, d, d, d, d, d, d, d};
}
/**
* 以下方法是监听事件
* */
@Override
public boolean onTouchEvent(MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float moveLength = e1.getX() - e2.getX(); //获取移动距离
Log.d("homeworkTag","e1.getX"+e1.getX());
Log.d("homeworkTag","e2.getX"+e2.getX());
if(moveLength < -MIN_DISTANCE){ //如果距离为负的,即往右边滑动大于最小临界值
mViewFlipper.setInAnimation(mAnimations[0]);
mViewFlipper.setOutAnimation(mAnimations[1]);
mViewFlipper.showNext();//展示下一个
return true;
}else if( moveLength > MIN_DISTANCE ) { //如果距离为正的,即往左边滑动大于最小临界值
mViewFlipper.setInAnimation(mAnimations[2]);
mViewFlipper.setOutAnimation(mAnimations[3]);
mViewFlipper.showPrevious();//展示上一个
return true;
}
return false;
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
}
主布局文件:activity_homework.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ViewFlipper
android:id="@+id/homework_view_flipper"
android:flipInterval="2000"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="@+id/homework_grid_view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</GridView>
<GridView
android:id="@+id/homework_grid_view2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</GridView>
<GridView
android:id="@+id/homework_grid_view3"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</GridView>
<GridView
android:id="@+id/homework_grid_view4"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</GridView>
</ViewFlipper>
</LinearLayout>
子布局界面:homework_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="120dp">
<ImageView
android:layout_centerInParent="true"
android:id="@+id/item_image"
android:layout_width="80dp"
android:layout_height="80dp"/>
</RelativeLayout>
自定义适配器:HomeWorkAdapter.java
继承自BaseAdapter类
public class HomeWorkAdapter extends BaseAdapter {
private int[] images;
private Context mContext;
public HomeWorkAdapter(int[] images, Context context) {
this.images = images;
mContext = context;
}
@Override
public int getCount() {
return images.length;
}
@Override
public Object getItem(int position) {
return images[position];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
convertView = LayoutInflater.from(mContext).inflate(R.layout.homework_item,parent,false);
holder = new ViewHolder();
holder.mImageView = convertView.findViewById(R.id.item_image);
convertView.setTag(holder); //将Holder存储到convertView中
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.mImageView.setImageResource(images[position]);
return convertView;
}
class ViewHolder{
private ImageView mImageView;
}
}
动画文件
在res文件夹下新建anim目录,将以下代码复制进去
left_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="-100%"
android:toXDelta="0"
android:duration="1000"/>
</set>
left_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0"
android:toXDelta="100%"
android:duration="1000"/>
</set>
right_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%"
android:toXDelta="0"
android:duration="1000"/>
</set>
right_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0"
android:toXDelta="-100%"
android:duration="1000"/>
</set>
聊一聊实现的一些细节
1.关于事件监听
由于子view覆盖了父view绝大多数地方,导致事件监听不到,所以我将子view的onTouch()方法也设置为gestureDetector.onTouchEvent()。
mGridView1.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
2.关于滑动方向
在onfling()方法中获取移动前X轴距离与滑动后X轴距离,通过互减,得出方向与移动距离,并设置最小临界移动距离,判断是否要通知mViewFlipper进行切换view
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float moveLength = e1.getX() - e2.getX(); //获取移动距离
Log.d("homeworkTag","e1.getX"+e1.getX());
Log.d("homeworkTag","e2.getX"+e2.getX());
if(moveLength < -MIN_DISTANCE){ //如果距离为负的,即往右边滑动大于最小临界值
mViewFlipper.setInAnimation(mAnimations[0]);
mViewFlipper.setOutAnimation(mAnimations[1]);
mViewFlipper.showNext();//展示下一个
return true;
}else if( moveLength > MIN_DISTANCE ) { //如果距离为正的,即往左边滑动大于最小临界值
mViewFlipper.setInAnimation(mAnimations[2]);
mViewFlipper.setOutAnimation(mAnimations[3]);
mViewFlipper.showPrevious();//展示上一个
return true;
}
return false;
}
3.关于数据初始化
我设置了四个页面,都是GridView,为了偷懒,我将每一个页面的图片都设置为相同的,但是如果愿意的话,可以设置成完全不同的,就和作业要求一样了
private void initData(){
int a = R.drawable.img1;
int b = R.drawable.img2;
int c = R.drawable.img3;
int d = R.drawable.img4;
mImages1 = new int[]{a, a, a, a, a, a, a, a, a, a, a, a};
mImages2 = new int[]{b, b, b, b, b, b, b, b, b, b, b, b};
mImages3 = new int[]{c, c, c, c, c, c, c, c, c, c, c, c};
mImages4 = new int[]{d, d, d, d, d, d, d, d, d, d, d, d};
}
4.关于BaseAdapter的getView()写法
我推荐大家在菜鸟教程进行相关学习
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
convertView = LayoutInflater.from(mContext).inflate(R.layout.homework_item,parent,false);
holder = new ViewHolder();
holder.mImageView = convertView.findViewById(R.id.item_image);
convertView.setTag(holder); //将Holder存储到convertView中
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.mImageView.setImageResource(images[position]);
return convertView;
}
最后
可能我会粗心大意漏写些啥在博客里,如果有错误,希望大家指出,我会尽快修正。
咳咳!关注不迷路哈