Implement interface using custom ScrollView class - Android - java

I need to know when the user scroll up or down. I managed to achieve that but now I am stuck getting the result back to my main class where I need it. Specifically I don't know how to pass the results to an interface I created.
Here is the error I get:
Attempt to invoke interface method 'void
com.app.android.interfaces.ScrollDirection.Down(int)' on a
null object reference
And here is my custom ScrollView:
public class CustomScrollView extends ScrollView {
private ScrollDirection scrolldirection;
public CustomScrollView(Context context) {
super(context);
scrolldirection = (ScrollDirection) context;
}
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onScrollChanged(int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
super.onScrollChanged(scrollX, scrollY, oldScrollX, oldScrollY);
if(scrollY<oldScrollY){
scrolldirection.Down(1);
}else{
scrolldirection.Down(-1);
}
}
public interface ScrollDirection{
public void Down(int direction);
}
}

you need to add this line scrolldirection = (ScrollDirection) context; inside every constructor
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
scrolldirection = (ScrollDirection) context;
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
scrolldirection = (ScrollDirection) context;
}
To allow Android Studio to interact with your view, at a minimum you must provide a constructor that takes a Context and an AttributeSet object as parameters
Docs link
Update : The recent issue was the implementation of CustomScrollView inside Fragment but Fragment do not have their context. To implement this ,make parent Activity implements the ScrollDirection and make some function in Fragment and call them from Activity's Down function.

Related

How to implement horizontal auto scroll of recyclerview

I am trying to implementing a custom linear layout manager in android. For getting a horizontal auto sliding recyclerview. but I am facing some issues when I try to call my custom class into my main java class.
The issues I am facing with my codes are listed below.
public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
Error which i am getting is: Constructor 'CustomLinearLayoutManager(android.content.Context, int, boolean)' is never used
public CustomLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
Error which i am getting is: Constructor 'CustomLinearLayoutManager(android.content.Context, android.util.AttributeSet, int, int)' is never used
customLinearLayoutManager.smoothScrollToPosition();
An error which I am facing for this line is:
smoothScrollToPosition() in CustomLinearLayoutManager cannot be applied to:
Expected Parameters: Actual Arguments:
recyclerView: RecyclerView
state: State
position: int
Custom Java Class
public class CustomLinearLayoutManager extends LinearLayoutManager {
public CustomLinearLayoutManager (Context context) {
super(context);
}
public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
public CustomLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
final LinearSmoothScroller linearSmoothScroller =
new LinearSmoothScroller(recyclerView.getContext()) {
private static final float MILLISECONDS_PER_INCH = 200f;
#Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return CustomLinearLayoutManager.this
.computeScrollVectorForPosition(targetPosition);
}
#Override
protected float calculateSpeedPerPixel
(DisplayMetrics displayMetrics) {
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
}
};
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}
}
Main Java Class:
CustomLinearLayoutManager customLinearLayoutManager = new CustomLinearLayoutManager(getContext());
customLinearLayoutManager.smoothScrollToPosition();
recyclerViewHeaderSlider = view.findViewById(R.id.bannerSlider);
SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(recyclerViewHeaderSlider);
recyclerViewHeaderSlider.setHasFixedSize(true);
recyclerViewHeaderSlider.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false));
headerSliderAdapter.setOnClick(this);
recyclerViewHeaderSlider.setAdapter(headerSliderAdapter);
Please tell the solution of the above-mentioned error. also, please exact code in order to achieve horizontal auto-slide recyclerview. with the custom linear layout manager which I have mentioned.
Why not use the normal linear layout manager and set the orientation to horizontal

init method in non-static block Android

I am extending ScrollView and in that i have used non-static block after constructors to initialize some of the variables.
Code
public ScrollViewExtended(Context context) {
super(context);
}
public ScrollViewExtended(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScrollViewExtended(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public ScrollViewExtended(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
private void init(Context context) {
activity = (Activity) context;
userActivityLogDao = new UserActivityLogDao();
activity_name = activity.getClass().getSimpleName();
}
{
init(getContext());
}
I don't want to call init(context) method in each constructor. Thats why i have used non-static block. Can you please suggest if this is the correct way of doing it?
*I am able to run this code without any error.
you can't use the static context. If your problem is the fact that you don't want to call init in each constructor just use this instead of super (explicit constructor invocation). Eg
public ScrollViewExtended(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScrollViewExtended(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(this);
}

Android Extended Button detect onClick

I have extended the Button class and not implemented onClick in extended button. And I am using the extended button every where and setting the onClick listener in each activity.
How can I detect the button is clicked in the Extended class.
public class ButtonExtended extends Button {
public ButtonExtended(Context context) {
super(context);
}
public ButtonExtended(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ButtonExtended(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public ButtonExtended(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
//onClick(){ here i want to detect the click }
}
In this ButtonExtended class, I want to detect, if the button is clicked just for the logging purpose. How can I achieve this?
You can override performClick() behavior to get the clicked state.
public class ButtonExtended extends AppCompatButton{
public ButtonExtended(Context context) {
super(context);
}
public ButtonExtended(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ButtonExtended(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public boolean performClick() {
Log.d("Button","performClick");
return super.performClick();
}
}
performClick() will get called first before the the listener. Do not omit return super.performClick() in method performClick() this consume the event and your listener will not get called.

Is this a good method to make ImageView square?

Parent layout has a specified width value (50dp), and height set to MATCH_PARENT. In that layout I am adding a few ImageView widgets using Java, and because parent layout has specified width, I can set width and height of each ImageView to MATCH_PARENT and using Java I can make that ImageView square by setting its height as width.
This is my code:
public class Icon extends ImageView {
public AppIcon(final Context context)
{
super(context);
}
public AppIcon(final Context context, final AttributeSet attrs)
{
super(context, attrs);
}
public AppIcon(final Context context, final AttributeSet attrs, final int defStyle)
{
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(final int width, final int height)
{
setMeasuredDimension(width, width);
}
}
Is this a good method to make each ImageView square? I think it's too simple, like something is missing.
P.S.: My method works, but I need to be sure, that everything is fine.
Your code is working one but it can be enhanced. See my code:
Updated my code.
The image will be scaled based on the measured width and height and whichever is smaller.
public class Icon extends ImageView {
public Icon(final Context context) {
super(context);
}
public Icon(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public Icon(final Context context, final AttributeSet attrs,
final int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int width, int height) {
super.onMeasure(width, height);
int measuredWidth = getMeasuredWidth();
int measuredHeight = getMeasuredHeight();
if (measuredWidth > measuredHeight) {
setMeasuredDimension(measuredHeight, measuredHeight);
} else {
setMeasuredDimension(measuredWidth, measuredWidth);
}
}
}

Basic constructor chaining calls

I hope this is not a silly question.
Having 3 basic constructors
public MyClass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public MyClass(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public MyClass(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
Each calls the super class constructor first. So does it mean all common constructor code I have to put in a private method like this?:
public MyClass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
common(context);
}
public MyClass(Context context, AttributeSet attrs) {
super(context, attrs);
common(context);
}
public MyClass(Context context) {
super(context);
common(context);
}
private void common(Context context) { ... }
I though that I could chain the constructor for common code, but I get an error saying constructor calls must be the first statement in the code.
public MyClass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this(context, attrs);
}
public MyClass(Context context, AttributeSet attrs) {
super(context, attrs);
// Some code
this(context);
}
public MyClass(Context context) {
super(context);
// Some more code
}
And the first statement is either the super constructor call or the class constructor call, cannot be both.
Constructor call must be the first statement in a constructor
The best way is to use this() - You don't need to create a new method, and you respect the DRY principle (Don't Repeat Yourself)
public MyClass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// your code here
}
public MyClass(Context context, AttributeSet attrs) {
// Assuming 0 is the default value of defStyle, else pass the default value
this(context, attrs, 0);
}
public MyClass(Context context) {
// Assuming null is the default value for attrs
this(context, null);
}
You don't have to create another method, you respect the DRY principle and it's easy.
public MyClass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// your code here
}
public MyClass(Context context, AttributeSet attrs) {
this(context, attrs,null);
}
public MyClass(Context context) {
this(context,null,null);
}
you can use in this way
What I suggest is put the common code in the most parameterizable constructor and call that constructor from every other (less parameterizable) constructor, with some default values of course for the now missing arguments (you can chain same class constructors with a this(...) statement). If the superclass you're extending is properly designed, you should be able to use your most parameterizable constructor to call its most parameterizable constructor by chaining (with a super(...) statement).
If that doesn't work for your case, then a private method is a very fine way to deal with this, there's usually no benefit in trying to work around it further.
Well, put the common code in a constructer and make sure to call it from every other constructer take care with last parameter int defStyle, I am assuming that 0 is default for defStyle.
public MyClass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
common(context);
}
public MyClass(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MyClass(Context context) {
this(context,null,0);
}
private void common(Context context) { ... }

Categories