LibGDX Listener in Actor in Stage doesn't work - events

The input listener doesn't fire in the Actor even if the Actor was already added to the stage and the input processor was already set to the stage. What could be the problem here?
Inside GameScreen (extends Screen) class:
public GameScreen(Game game) {
this.game = game;
stage = new Stage(800, 480, true);
number = new Number();
stage.addActor(number);
}
public void show() {
Gdx.input.setInputProcessor(stage);
}
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act(delta);
stage.draw();
}
Constructor of Number:
public Number() {
addListener(new InputListener() {
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
System.out.println("touch down");
return true;
}
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
System.out.println("touch up");
}
public boolean mouseMoved(InputEvent event, float x, float y) {
System.out.println("mouse moved");
return true;
}
});
}

Related

how create a simple object animation in processing

QUESTION
I'm trying to create a simple object "car" animation in Processing.
My code is:
Car car;
void setup(){
size(800, 600);
background(#818B95);
frameRate(30);
car = new Car(10,10);
}
void draw(){
//refresh background
background(#818B95);
print("-");
car.drawCar();
}
void mouseClicked() {
car.run();
}
public class Car implements Runnable{
private int pos_x, pos_y;
public Car(int pos_x, int pos_y){
this.pos_x = pos_x;
this.pos_y = pos_y;
}
public void drawCar(){
rect(pos_x,pos_y,10,10);
}
public void run(){
while(true){
pos_x += 10;
print("*");
delay(200);
}
}
}
I'm expecting to see the car/rectangle move right when I click the mouse button, but nothing happens.
I've added the two print in order to see if the draw method and my car.run are executed in parallel showing some * and - printed alternately.
What I see is a sequence of - until I click and then only * are printed.
Is it possible that starting a new object thread will stop the main draw cycle?
SOLUTION
This is just a variant of the suggested solution (by Mady Daby) without using threads.
Car car;
void setup(){
size(800, 600);
background(#818B95);
frameRate(30);
car = new Car(10,10);
}
void draw(){
//refresh background
background(#818B95);
print("-");
car.drawCar();
}
void mouseClicked() {
car.moving = true;
}
public class Car{
private int pos_x, pos_y;
boolean moving = false;
public Car(int pos_x, int pos_y){
this.pos_x = pos_x;
this.pos_y = pos_y;
}
public void drawCar(){
rect(pos_x,pos_y,10,10);
//animation
if(moving){
pos_x += 10;
print("*");
}
}
}
You could make the car move right by just introducing a boolean variable to track whether the car is supposed to be moving right moving and then increment pos_x if moving is true. You can also use the clicks to toggle between moving and not moving.
Car car;
void setup() {
size(800, 600);
background(#818B95);
frameRate(30);
car = new Car(10, 10);
}
void draw() {
//refresh background
background(#818B95);
print("-");
car.drawCar();
}
void mouseClicked() {
car.toggleMoving();
}
public class Car implements Runnable {
private int pos_x, pos_y;
private boolean moving = false;
public Car(int pos_x, int pos_y) {
this.pos_x = pos_x;
this.pos_y = pos_y;
}
public void toggleMoving() {
moving = !moving;
}
public void drawCar() {
if (moving) {
this.run();
}
rect(pos_x, pos_y, 10, 10);
}
public void run() {
pos_x += 10;
print("*");
delay(200);
}
}

Trying to pick up a battery. "NullReferenceException" error

Full error is "NullReferenceException: Object reference not set to an instance of an object
battery.OnTriggerStay (UnityEngine.Collider other) (at Assets/battery.cs:32)"
heres my screen in case its something i didnt do in the inspector: http://imgur.com/a/wWSGJ
here is my code (not sure if you need my flashlight code too):
public class battery : MonoBehaviour {
public float a;
public float b;
public float c;
public float d;
public bool showText;
public int Bat;
public GameObject Flight;
public int mainBat;
public bool safeRemove;
void Start()
{
showText = false;
}
void OnTriggerStay(Collider other)
{
showText = true;
if (!safeRemove)
{
if (Input.GetKeyUp (KeyCode.E))
{
mainBat = Flight.GetComponent<flashlight> ().batLevel;
Bat = 20;
Flight.GetComponent<flashlight> ().batLevel = Bat +- mainBat;
safeRemove = true;
if (safeRemove)
{
Destroy (this.gameObject);
}
}
}
}
void OnTriggerExit(Collider other)
{
showText = false;
}
void OnGUI()
{
if (showText)
{
GUI.Box(new Rect(Screen.width/ 2.66f, Screen.height/ 3.48f, Screen.width/ 3.78f, Screen.height/ 16.1f), "Press 'E' to pick up");
}
}
}

Modify methods so they are given an array index value of the moon whose name or radius is required

So the part of my question is ''Modify getMoonName() and getMoonRadius() so they are given an array index value of the moon whose name or radius is required.''
I've tried adding moons[i].getRadius but then end up getting ''The variable i does not exist''. Here's the code.
PLANET CLASS
public class Planet
{
private float angle=0.01;
// add class member variables here
private String name;
private float radius;
private float distance;
private float speed;
private Moon[] moons;
// add constructor here
public Planet(String n, float r, float d, float s, Moon[] m)
{
this.name=n;
this.radius=r;
this.distance=d;
this.speed=s;
this.moons=m;
}
// add other methods here
public String getName()
{
return name;
}
public float getRadius()
{
return radius;
}
public float getDistance()
{
return distance;
}
public float getSpeed()
{
return speed;
}
public Moon[] getMoons()
{
return moons;
}
public void setRadius(float r)
{
this.radius=r;
}
public String getMoonName()
{
return moons[i].getName();
}
public float getMoonRadius()
{
return moons[i].getRadius();
}
public String toString()
{
int n=0;
for (int i=0; i<moons.length; i++)
{
n++;
}
return "Planet" + name + ("Radius: " +radius +"Distance: " +distance) +n +"moons.";
}
public void printMoons()
{
for (int i=0; i<moons.length; i++)
{
System.out.println(moons[i]);
}
}
// This will display the moon when other code is completed. You don't need to understand this code.
public void display()
{
angle=angle+(0.01*speed);
pushMatrix();
rotate(angle);
translate(distance,0);
fill(255, 255, 255);
ellipse(0, 0, radius*2, radius*2);
for(Moon moon: getMoons())
moon.display();
popMatrix();
}
}`
MOON CLASS
public class Moon
{
private float angle=0.01;
// add class member variables here
private String name;
private float radius;
private float distance;
private float speed;
private int orbitalPeriod;
// add constructor here
public Moon(String n, float r, float d, float s, int o)
{
this.name=n;
this.radius=r;
this.distance=d;
this.speed=s;
this.orbitalPeriod=o;
}
// add other methods here
public String getName()
{
return name;
}
public float getRadius()
{
return radius;
}
public float getDistance()
{
return distance;
}
public float getSpeed()
{
return speed;
}
public float getOrbitalPeriod()
{
return orbitalPeriod;
}
public void setName(String n)
{
this.name=n;
}
public void setOrbitalPeriod(int o)
{
this.orbitalPeriod=o;
}
public String toString()
{
return ("Moon : " +name +" "+"orbit="+orbitalPeriod);
}
// This will display the moon when other code is completed. You don't need to understand this code.
public void display()
{
angle=angle+(0.01*speed);
pushMatrix();
rotate(angle);
translate(distance, 0);
fill(149, 149, 149);
ellipse(0, 0, radius*2, radius*2);
popMatrix();
}
}
Let's look at this function:
public String getMoonName()
{
return moons[i].getName();
}
Where do you think the i variable is defined? Your instructions say to take an argument, but this function does not take any arguments.
As a small example, let's say I had this function:
public void printMessage(){
println("Hello!");
}
If I wanted to modify that function to take a parameter, I would have to add that to the method like this:
public void printMessage(String message){
println(message);
}
You have to do something similar with your getMoonName() function.
If you're still stuck, please post a small example like mine instead of your whole sketch, and we'll go from there.

Hide FloatingActionButton on scroll of RecyclerView

I want to hide/show FloatingActionButton on scroll of RecyclerView.
My XML layout :
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview_eventlist"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab_createevent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/fab_margin"
app:layout_anchor="#id/recyclerview_eventlist"
app:layout_anchorGravity="bottom|right|end"
app:layout_behavior="com.eventizon.behavior.ScrollAwareFABBehavior"
android:src="#drawable/ic_edit"
app:backgroundTint="#color/custom_color_1"
app:borderWidth="0dp" />
</android.support.design.widget.CoordinatorLayout>
DrawerLayout is the parent layout of this layout.
public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
private static final String TAG = "ScrollAwareFABBehavior";
public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
super();
Log.e(TAG,"ScrollAwareFABBehavior");
}
#Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout,
FloatingActionButton child, View target, int dxConsumed,
int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
// TODO Auto-generated method stub
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed,
dxUnconsumed, dyUnconsumed);
Log.e(TAG,"onNestedScroll called");
if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
Log.e(TAG,"child.hide()");
child.hide();
} else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
Log.e(TAG,"child.show()");
child.show();
}
}
}
Used this layout behaviour for FloatingActionButton.
When I see logcat only constructor is getting called. onNestedScroll() doesn't get called when I scroll the list.
Easiest solution:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
{
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
{
if (dy > 0 ||dy<0 && fab.isShown())
{
fab.hide();
}
}
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState)
{
if (newState == RecyclerView.SCROLL_STATE_IDLE)
{
fab.show();
}
super.onScrollStateChanged(recyclerView, newState);
}
});
This should work for you:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx,int dy){
super.onScrolled(recyclerView, dx, dy);
if (dy >0) {
// Scroll Down
if (fab.isShown()) {
fab.hide();
}
}
else if (dy <0) {
// Scroll Up
if (!fab.isShown()) {
fab.show();
}
}
}
});
Ok, here is what you need:
First, since your FAB depends on the RecyclerView, add the following to your behavior class:
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
if(dependency instanceof RecyclerView)
return true;
return false;
}
Next, in order to receive onNestedScroll() calls, you need to override this:
public boolean onStartNestedScroll(CoordinatorLayout parent, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
//predict whether you will need to react to the RecyclerView's scroll;
//if yes, return true, otherwise return false to avoid future calls
//of onNestedScroll()
return true;
}
Good luck!
Update
Here is what your ScrollAwareFABBehavior should look like:
public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
private static final String TAG = "ScrollAwareFABBehavior";
public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
super();
}
public boolean onStartNestedScroll(CoordinatorLayout parent, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
return true;
}
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
if(dependency instanceof RecyclerView)
return true;
return false;
}
#Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout,
FloatingActionButton child, View target, int dxConsumed,
int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
// TODO Auto-generated method stub
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed,
dxUnconsumed, dyUnconsumed);
if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
child.hide();
} else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
child.show();
}
}
}
Also, it was tested using com.android.support:design:23.0.1
Short and Simple Solution:
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > 0 && mFloatingActionButton.getVisibility() == View.VISIBLE) {
mFloatingActionButton.hide();
} else if (dy < 0 && mFloatingActionButton.getVisibility() !=View.VISIBLE) {
mFloatingActionButton.show();
}
}
});
If you are using Material Components for Android and your FAB is inside a CoordinatorLayout then you can use the layout_behavior com.google.android.material.behavior.HideBottomViewOnScrollBehavior
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/filter_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
...
app:layout_behavior="#string/hide_bottom_view_on_scroll_behavior"
... />
If you are not using coordinator layout and want to hide and show FAB smoothly. And you want to implement your own logic to hide fab on scroll down, and show it on scrolling up.
Then here is the solution in kotlin,
Declare a variable,
var scrollingDown = false
After that create a listener,
recycler_view_id.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
if (scrollingDown && dy >= 0) {
scrollingDown = !scrollingDown
id_show_media_fab.startAnimation(
AnimationUtils.loadAnimation(
getApplicationContext(),
R.anim.fab_close
)
)
} else if (!scrollingDown && dy < 0) {
scrollingDown = !scrollingDown
id_show_media_fab.startAnimation(
AnimationUtils.loadAnimation(
getApplicationContext(),
R.anim.fab_open
)
)
}
}
})
create anim resource file
fab_open.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="300"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:interpolator="#android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="100%"
android:toXScale="0.9"
android:toYScale="0.9" />
<alpha
android:duration="300"
android:fromAlpha="0.0"
android:interpolator="#android:anim/accelerate_interpolator"
android:toAlpha="1.0" />
</set>
fab_close.xml
just change
android:fromXScale="0.8"
android:fromYScale="0.8"
This is how I did. It works for me! If you don't know how to implement, You can see detail in this link https://guides.codepath.com/android/floating-action-buttons
public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
public ScrollAwareFABBehavior(Context context, AttributeSet attributeSet){
super();
}
#Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
child.hide();
} else if (dyConsumed < 0 && child.getVisibility() == View.GONE) {
child.show();
}
}
#Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
}
I have created a custom RecyclerView which has OnUpDownScrollListener, OnLeftRightScrollListener ready:
Code:
MBRecyclerView.java
public class MBRecyclerView extends RecyclerView {
private OnScrollListener wrappedUpDownScrollListener;
private OnScrollListener wrappedLeftRightScrollListener;
public MBRecyclerView(Context context) {
super(context);
init();
}
public MBRecyclerView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public MBRecyclerView(Context context, #Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
}
// region Scrolling Listener for Up, Down, Left and Right
public void setOnUpDownScrollListener(final OnUpDownScrollListener onUpDownScrollListener) {
if (wrappedUpDownScrollListener == null) {
wrappedUpDownScrollListener = getWrappedUpDownScrollListener(onUpDownScrollListener);
addOnScrollListener(wrappedUpDownScrollListener);
}
}
public void removeOnUpDownScrollListener() {
if (wrappedUpDownScrollListener != null) {
removeOnScrollListener(wrappedUpDownScrollListener);
wrappedUpDownScrollListener = null;
}
}
public void setLeftOnRightScrollListener(final OnLeftRightScrollListener onLeftRightScrollListener) {
if (wrappedLeftRightScrollListener == null) {
wrappedLeftRightScrollListener = getWrappedLeftRightScrollListener(onLeftRightScrollListener);
addOnScrollListener(wrappedLeftRightScrollListener);
}
}
public void removeOnLeftRightScrollListener() {
if (wrappedLeftRightScrollListener != null) {
removeOnScrollListener(wrappedLeftRightScrollListener);
wrappedLeftRightScrollListener = null;
}
}
private OnScrollListener getWrappedUpDownScrollListener(final OnUpDownScrollListener onUpDownScrollListener) {
return new OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (onUpDownScrollListener != null) {
// Negative to check scrolling up, positive to check scrolling down
if (!recyclerView.canScrollVertically(-1)) {
onUpDownScrollListener.onScrolledToTop();
} else if (!recyclerView.canScrollVertically(1)) {
onUpDownScrollListener.onScrolledToBottom();
}
if (dy > 0) {
onUpDownScrollListener.onScrollDown(dy);
} else if (dy < 0) {
onUpDownScrollListener.onScrollUp(dy);
}
}
}
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (onUpDownScrollListener != null) {
onUpDownScrollListener.onScrollStopped();
}
}
}
};
}
private OnScrollListener getWrappedLeftRightScrollListener(final OnLeftRightScrollListener onLeftRightScrollListener) {
return new OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (onLeftRightScrollListener != null) {
// Negative to check scrolling left, positive to check scrolling right
if (!recyclerView.canScrollHorizontally(-1)) {
onLeftRightScrollListener.onScrolledToMostLeft();
} else if (!recyclerView.canScrollVertically(1)) {
onLeftRightScrollListener.onScrolledToMostRight();
}
if (dy > 0) {
onLeftRightScrollListener.onScrollRight(dx);
} else if (dy < 0) {
onLeftRightScrollListener.onScrollLeft(dx);
}
}
}
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (onLeftRightScrollListener != null) {
onLeftRightScrollListener.onScrollStopped();
}
}
}
};
}
public abstract class OnUpDownScrollListener {
public void onScrollUp(int dy) {}
public void onScrollDown(int dy) {}
public void onScrolledToTop() {}
public void onScrolledToBottom() {}
public void onScrollStopped() {}
}
public abstract class OnLeftRightScrollListener {
public void onScrollLeft(int dx) {}
public void onScrollRight(int dx) {}
public void onScrolledToMostRight() {}
public void onScrolledToMostLeft() {}
public void onScrollStopped() {}
}
// endregion
}
Usage (UpDownScrollListener):
mbRecyclerView.setOnUpDownScrollListener(new MBRecyclerView.OnUpDownScrollListener() {
#Override
public void onScrollUp(int dy) {
// show
}
#Override
public void onScrollDown(int dy) {
// hide
}
// aditional functions:
public void onScrolledToTop() {}
public void onScrolledToBottom() {}
public void onScrollStopped() {}
});
similarely you can handle the LeftRight scrolling by setting
setOnLeftRightScrollListener
I hope it can help somebody :)
The solution is in: F.A.B Hides but Doesn't Show
The problem is Android 25.0.x+ sets the view to GONE and thats why the listener is not reporting changes.
All the answers which goes on the Behavior path and onNestedScroll (instead of recyclerview listener) don't comment about the fact that onNestedScroll will be called many times while scrolling. This means that child.show() and child.hide() will be called many times as well. Although show() and hide() are designed to handle that scenario, they still run a lot of code and create some objects which multiplied by the times onNestedScroll is called, result in a lot of objects created unnecessarily.
Considering that and because I wanted to run a different animation instead of the default show() and hide(), I came up with the following Behavior implementation:
public class ScrollAwareFABBehavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
private static final String TAG = "ScrollAwareFABBehavior";
private boolean fabAnimationStarted = false;
private boolean flingHappened = false;
public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onStartNestedScroll(#NonNull CoordinatorLayout coordinatorLayout, #NonNull FloatingActionButton child, #NonNull View directTargetChild, #NonNull View target, int axes, int type) {
if (target instanceof RecyclerView) {
return true;
}
return false;
}
#Override
public void onStopNestedScroll(#NonNull CoordinatorLayout coordinatorLayout, #NonNull final FloatingActionButton child, #NonNull View target, int type) {
super.onStopNestedScroll(coordinatorLayout, child, target, type);
// If animation didn't start, we don't need to care about running the restore animation.
// i.e.: when the user swipes to another tab in a viewpager. The onNestedPreScroll is never called.
if (!fabAnimationStarted) {
return;
}
// Animate back when the fling ended (TYPE_NON_TOUCH)
// or if the user made the touch up (TYPE_TOUCH) but the fling didn't happen.
if (type == ViewCompat.TYPE_NON_TOUCH || (type == ViewCompat.TYPE_TOUCH && !flingHappened)) {
ViewCompat.animate(child).translationY(0).start();
fabAnimationStarted = false;
}
}
#Override
public boolean onNestedFling(#NonNull CoordinatorLayout coordinatorLayout, #NonNull FloatingActionButton child, #NonNull View target, float velocityX, float velocityY, boolean consumed) {
// We got a fling. Flag it.
flingHappened = true;
return false;
}
#Override
public void onNestedPreScroll(#NonNull CoordinatorLayout coordinatorLayout, #NonNull FloatingActionButton child, #NonNull View target, int dx, int dy, #NonNull int[] consumed, int type) {
if (!fabAnimationStarted) {
Log.d(TAG, "onStartNestedScroll: animation is starting");
fabAnimationStarted = true;
flingHappened = false;
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
ViewCompat.animate(child).translationY(child.getHeight() + lp.bottomMargin).start();
}
}
}
The floating action button will hide when there's scrolling and show when the scrolling stops.
recylerview.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
switch (newState) {
case RecyclerView.SCROLL_STATE_IDLE:
addExpenseBtn.show();
break;
default:
addExpenseBtn.hide();
break;
}
super.onScrollStateChanged(recyclerView, newState);
}
});
//lv = ListView
lv.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
fab.setVisibility(view.getFirstVisiblePosition() == 0 ? View.VISIBLE : View.INVISIBLE);
}
});
I used this in a RecyclerView.Adapter's onBindViewHolder method to set the bottom margin of the last item in the list to 72dp so that it will scroll up above the floating action button.
This does not require a dummy entry in the list.
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// other binding code goes here.
if (position + 1 == getItemCount()) {
// set bottom margin to 72dp.
setBottomMargin(holder.itemView, (int) (72 * Resources.getSystem().getDisplayMetrics().density));
} else {
// reset bottom margin back to zero. (your value may be different)
setBottomMargin(holder.itemView, 0);
}
}
public static void setBottomMargin(View view, int bottomMargin) {
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, bottomMargin);
view.requestLayout();
}
}
A little late, but it works for me.
//This only works on Android M and above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
recyclerView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
#Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
if (scrollY > oldScrollY && fab.isShown()) {
fab.hide();
} else if (scrollY < oldScrollY && !fab.isShown()) {
fab.show();
}
}
});
When scrollY is greater than oldScrollY, that means user has scroll down so, we just need to check FAB is showing. If it is, we hide it.
scrollY is less than oldScrollY means a scroll up. We check if FAB is still hidden to show it.
Try this
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//Customize your if statement
if (recyclerView.computeVerticalScrollOffset() > recyclerView.getHeight() * 2) {
if (!fab.isShown()) {
fab.show();
}
} else {
fab.hide();
}
}
});
enjoy.

call method from a method within the same class

I have a platformer class that creates a window and spawns platforms and a "character". It uses another class platform to make platforms. The character is supposed to jump up and land on the platforms. I use the getBounds and getTopY functions for collision detection but they only work for the first platform. How can i get them to work for multiple platforms?
public class Platformer extends JPanel {
Platform platform = new Platform(this);
Character character = new Character(this);
public Platformer() {
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
character.keyTyped(e);
}
#Override
public void keyReleased(KeyEvent e) {
character.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
character.keyPressed(e);
}
});
setFocusable(true);
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
platform.Location(150,200);
platform.paint(g2d);
platform.Location(200,120);
platform.paint(g2d);
character.paint(g2d);
}
private void move(){
character.move();
}
public static void main(String args[]){
JFrame frame = new JFrame("Mini Tennis");
//create new game
Platformer platformer = new Platformer();
//add game
frame.add(platformer);
//size
frame.setSize(400, 400);
frame.setVisible(true);
//set close condition
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true) {
platformer.move();
platformer.repaint();
try {
Thread.sleep(10);//sleep for 10 sec
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
public class Platform {
private static final int Height = 10;
private static final int Width = 60;
int x;
int Y;
private Platformer platformer;
public Platform(Platformer platformer) {
this.platformer = platformer;
}
public void Location(int xin, int yin) {
x = xin;
Y = yin;
}
public void paint(Graphics2D g) {
g.fillRect(x, Y, Width, Height);
}
public Rectangle getBounds() {
return new Rectangle(x, Y, Width, Height);
}
public int getTopPlat() {
return Y;
}
}
Actually you have only one platform. And you draw this platform twice in different places (paint function in Platformer):
platform.Location(150,200);
platform.paint(g2d);
platform.Location(200,120);
platform.paint(g2d);
Therefore I suppose you handle only one platform (with coordinates 200 and 120). You must keep all of your platforms and handle each of them separately.

Resources