- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下代码来监听滑动操作以在我的 ViewFlipper 中的 GridView 之间导航。但是,它检测到的滑动不一致。我将手势监听器添加到每个 GridView 以及 GridView 中的每个项目。还有什么我想念的吗?
完整代码如下:
public class ListNewsActivity extends Activity implements OnGestureListener {
String TAG = "ListNewsActivity";
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private static final int DIALOG_PLEASE_WAIT = 100;
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
private Animation slideLeftIn;
private Animation slideLeftOut;
private Animation slideRightIn;
private Animation slideRightOut;
private static int MAX_STREAMS = AppSettings.getStreamList().size();
Context context;
ViewFlipper flipper;
StreamHeader header;
int currentStreamIndex = 0;
ArrayList<StreamNav> navList = new ArrayList<StreamNav>();
ArrayList<StreamGridView> gridList = new ArrayList<StreamGridView>();
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
context = getApplicationContext();
super.onCreate(savedInstanceState);
setContentView(R.layout.stream);
if (AppSettings.userToken == null) {
AppSettings.getUserToken(context);
}
header = (StreamHeader) findViewById(R.id.stream_header);
setHeaderTitle();
flipper = (ViewFlipper)findViewById(R.id.stream_flipper);
boolean loadData = false;
Log.v(TAG, "No. of streams: " + String.valueOf(AppSettings.getStreamList().size()));
for (Stream stream : AppSettings.getStreamList()) {
Log.v(TAG, "Checking Stream " + stream.getName());
if (stream.getPosts() == null || stream.getPosts().size() == 0) {
loadData = true;
Log.v(TAG, "Empty Stream for " + stream.getBlogId() + ". Data will be loaded.");
break;
}
else {
Log.v(TAG, "Stream " + stream.getName() + " is populated. Posts: " + String.valueOf(stream.getPosts().size()));
}
}
setupNavAndGrids();
if (loadData) {
new LoadStreamTask().execute();
}
else {
populateGrids();
}
slideLeftIn = AnimationUtils.loadAnimation(this, R.anim.stream_flipper_slidein_from_right);
slideLeftOut = AnimationUtils.loadAnimation(this, R.anim.stream_flipper_slideout_to_left);
slideRightIn = AnimationUtils.loadAnimation(this, R.anim.stream_flipper_slidein_from_left);
slideRightOut = AnimationUtils.loadAnimation(this, R.anim.stream_flipper_slideout_to_right);
gestureDetector = new GestureDetector(new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
return true;
}
return false;
}
};
}
public void setupNavAndGrids() {
LinearLayout llNav = (LinearLayout) findViewById(R.id.stream_nav_layout);
View.OnClickListener navOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
StreamNav nav = (StreamNav)v;
navigateToStream(nav.getStreamIndex());
}
};
for (int i = 0; i < MAX_STREAMS; i++) {
StreamNav nav = new StreamNav(context, null);
nav.setStreamIndex(i);
nav.setOnClickListener(navOnClickListener);
navList.add(nav);
llNav.addView(nav);
StreamGridView gv = new StreamGridView(context, null);
gv.setOnTouchListener(gestureListener);
gridList.add(gv);
flipper.addView(gv);
}
navList.get(0).setSelected(true);
}
void navigateToStream(int newStreamIndex) {
for (StreamNav nav : navList) {
if (nav.getStreamIndex() == newStreamIndex) {
nav.setSelected(true);
}
else {
nav.setSelected(false);
}
}
Log.v(TAG, "Navigate To Stream: currentStreamIndex=" + String.valueOf(currentStreamIndex) + " newStreamIndex " + String.valueOf(newStreamIndex));
if (currentStreamIndex < newStreamIndex) {
int ctr = newStreamIndex - currentStreamIndex;
for (int i = 0; i < ctr; i++) {
showNext();
}
}
else {
int ctr = currentStreamIndex - newStreamIndex;
for (int i = 0; i < ctr; i++) {
showPrevious();
}
}
}
public void showNext() {
Toast.makeText(context, "Show Next Page for Flipper", Toast.LENGTH_LONG);
flipper.setInAnimation(this, R.anim.stream_flipper_slidein_from_right);
flipper.setOutAnimation(this, R.anim.stream_flipper_slideout_to_left);
flipper.showNext();
setStreamIndex(1);
setHeaderTitle();
}
public void showPrevious() {
Toast.makeText(context, "Show Previous Page for Flipper", Toast.LENGTH_LONG);
flipper.setInAnimation(this, R.anim.stream_flipper_slidein_from_left);
flipper.setOutAnimation(this, R.anim.stream_flipper_slideout_to_right);
flipper.showPrevious();
setStreamIndex(-1);
setHeaderTitle();
}
void setStreamIndex(int step) {
if (step == 1) {
if (currentStreamIndex == MAX_STREAMS) {
currentStreamIndex = 0;
}
else {
currentStreamIndex++;
}
}
else {
// -1 which means previous
if (currentStreamIndex == 0) {
currentStreamIndex = MAX_STREAMS - 1;
}
else {
currentStreamIndex--;
}
}
}
void setHeaderTitle() {
header.setTitle(AppSettings.getStreamList().get(currentStreamIndex).getName());
}
void populateGrids() {
int pos = -1;
for (StreamGridView sgv : gridList) {
pos++;
Log.v(TAG, "Loading Stream for " + AppSettings.getStreamList().get(pos).getName() + "; Posts: " + String.valueOf(AppSettings.getStreamList().get(pos).getPosts().size()));
ArrayList<Post> posts = AppSettings.getStreamList().get(pos).getPosts();
sgv.adapter = new LazyPostItemAdapter(ListNewsActivity.this, posts, gestureListener);
sgv.gvStream.setAdapter(sgv.adapter);
}
}
class LoadStreamTask extends AsyncTask<Void, String, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(DIALOG_PLEASE_WAIT);
}
@Override
protected Void doInBackground(Void... unused) {
for (Stream stream : AppSettings.getStreamList()) {
if (stream.getBlogId().equalsIgnoreCase("popular")) {
stream.setPosts(Post.getPopularStream());
}
else if (stream.getBlogId().equalsIgnoreCase("recent")) {
stream.setPosts(Post.getRecentStream());
}
else {
Blog blog = Blog.getBlog(stream.getBlogId());
stream.setPosts(Post.getPostsForBlog(blog));
}
}
return null;
}
@Override
protected void onPostExecute(Void unused) {
populateGrids();
dismissDialog(DIALOG_PLEASE_WAIT);
}
}
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_PLEASE_WAIT:
ProgressDialog mProgressDialog;
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("Loading Streams...");
mProgressDialog.setCancelable(false);
mProgressDialog.show();
return mProgressDialog;
default:
return null;
}
}
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.v(TAG, "onFling");
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// right to left swipe
if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
flipper.setInAnimation(slideLeftIn);
flipper.setOutAnimation(slideLeftOut);
flipper.showNext();
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
flipper.setInAnimation(slideRightIn);
flipper.setOutAnimation(slideRightOut);
flipper.showPrevious();
}
} catch (Exception e) {
// nothing
}
return false;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureDetector.onTouchEvent(event))
return true;
else
return false;
}
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
最佳答案
我一直在 StackOverflow 上看到相同的滑动手势检测代码,因此我尝试稍微清理一下。这是一个通用的监听器,可以触发向右或向左滑动的事件(很容易扩展到其他
public class SwipeListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private SwipeHandler handler;
public SwipeHandler getHandler() {
return handler;
}
public void setHandler(SwipeHandler handler) {
this.handler = handler;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// left
if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
if (handler != null) {
handler.onLeft();
return true;
}
// right
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
if (handler != null) {
handler.onRight();
return true;
}
}
return super.onFling(e1, e2, velocityX, velocityY);
}
public static abstract class SwipeHandler{
public void onLeft() {}
public void onRight() {}
}
}
然后要在任何地方使用它,只需创建一个实例,设置您的滑动事件处理程序,然后附加它:
SwipeListener swipeListener = new SwipeListener();
swipeListener.setHandler(new SwipeListener.SwipeHandler() {
@Override
public void onRight() {
doSomething();
}
});
someView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
关于android - 使用多个 GridView 在 ViewFlipper 上实现滑动操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5162720/
我的 Activity 中有一个 ViewFlipper,用作 ListView 的页脚 View 。不久前,我发布了关于我在模拟器中看到的一个问题。参见 Activity has leaked In
当我将 ViewFlipper 用作 Widget 时,我在 ViewFlipper 中更新 subview 时遇到问题。 这是小部件的布局: 这是 AppWidget
您好,我正在创建如下所示的 ViewFlipper。 并处理像这样的事件 ViewFlipperSampleActivity.java public class ViewFlipperSamp
抱歉我的英语不好。我有一个画廊,当您单击特定图像时,它会出现在屏幕上。当图片占满整个屏幕时,我想做什么,它仍然可以滚动。为此,我使用 ViewFlipper。主要 Activity publi
我已经制作了一个不错的 ViewPager,现在,我希望只要用户在屏幕上双击,底部菜单栏就会出现/消失。我以为这会很容易,但是在阅读了很多论坛并尝试了许多可能的解决方案之后,我不得不承认我无法实现它。
我正在尝试开发一个应用程序,其中包含一个带 View 翻转器的画廊。 图库显示所有图像。我想要做的是, View 翻转器中显示的图像应该在图库中突出显示。 目前我可以在 onClick 上突出显示它。
我有一些基本的动画,当它们用于 Activity 之间的转换时,它们就像一个魅力。 问题是,当我在我的取景器上使用它们时,我看到了非常明显的延迟。这是我的 Activity 中的代码 fragment
我正在尝试像这样进行缩放:zoom the imageview on the double click in viewflipper in android 我尝试将该代码改编为我的项目,但它不起作用.
对不起我的英语。当图片填满屏幕时,我想做的就是可以用来滚动。为此,请使用 ViewFlipper。但它不起作用。是全屏显示图像的类。我做错了什么? public class FullScree
我正在尝试将 viewflipper 集成到已经有抽屉导航的 Activity 中,但 viewflipper 不工作,尽管抽屉导航正在工作。主题是滑动布局并显示数据。下面是我的代码XML:
在我的 Android 应用程序的一个 Activity 中,我有一个 ViewFlipper,里面有 3 个 ImageView,构建如下:
嘿,我查了很多教程和指南,但不知何故找不到... 我需要在我的 Android 应用中包含多张图片。它就像一个图像查看器/幻灯片。目前,我使用 ImageView 和适配器在/drawable-mdp
我想创建一个菜单,它以随机时间间隔在 viewflipper 的 5 个子级之间以随机顺序“翻转”。 我尝试了以下代码,我可以让 System.out.println 显示我的调试消息以随机时间间隔记
我正在使用 ViewFlipper,我的 viewFlipper 工作正常,直到我增加了图片的高度。 它给我 OutOfMemoryError。 这是我的包含 viewFlipper 的 Activi
我在 ViewFlipper 中有一些 ImageView。我想尊重图片的纵横比,这样布局就不会占用所有屏幕。我设置了一个简单的“幻灯片”动画,但 ViewFlipper 总是比里面的图像大一点。这会
我正在开发一个 Android 项目,我在其中使用 ViewFlipper 来翻转 child 。为此,我使用了定制的脚蹼。在此我覆盖了 onTouchEvent() 方法。鳍状肢包含每个 child
我的 xml 布局中有一个包含图像的 ViewFlipper。我想全屏显示这张图片。无论我为图像使用哪种 ScaleType,我都无法让图像全屏显示。 这是我的布局:
对于包含一些图像的取景器,我应该使用什么插值器来查看连续的图像,我的意思是看到图像的结尾向左,图像的开头来自右边? (对不起我的描述,我希望你明白我的意思)。我为 viewflipper 使用动画(向
在我的 Android 项目中,我使用 ViewFlipper 来翻转 child 。为此,我使用了定制的脚蹼。在这里,我重写了 onTouchEvent()。鳍状肢也包含每个 child 的图像。但
我正在使用带有两个 ListView 的 ViewFlipper。在 ViewFlipper 上设置背景可绘制时,“翻转”时执行的动画只渲染前景,背景是黑色的!动画完成后,背景出现。动画 View 的
我是一名优秀的程序员,十分优秀!