Java Question Help with ScrollView

derez

Expert
Licensed User
Longtime User
I finally got the SeekBar example sorted out, and tried to make a similar one for a scrollview, since all my ideas for new library involve this view.

Can someone make the seekbar example work for ScrollView ?

Then I'll need help in adding a Label to the panel and in getting the scroll event working inside the library as well as in the B4A application.

Thanks in advance...

Here is the seekbar code:
B4X:
package derez.libs;

import android.widget.SeekBar;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.DontInheritEvents;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.Hide;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.objects.ViewWrapper;


@ActivityObject
@ShortName("SeekBar")
@Author("xxx")
@Version(1f)
@DontInheritEvents
@Events(values={"ValueChanged (Value As Int, UserChanged As Boolean)"})
public class SeekBarWrapper extends ViewWrapper<SeekBar>
{
    @Override
    @Hide
    public void innerInitialize(final BA ba, final String eventName, boolean keepOldObject)
    {
        if (!keepOldObject)
            setObject(new SeekBar(ba.context));
        super.innerInitialize(ba, eventName, true);
        if (ba.subExists(eventName + "_valuechanged"))
        {
            getObject().setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
            {

                @Override
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
                {
                    ba.raiseEvent(getObject(), eventName + "_valuechanged", progress, fromUser);
                }

                @Override
                public void onStartTrackingTouch(SeekBar arg0) 
                {
                }

                @Override
                public void onStopTrackingTouch(SeekBar arg0) 
                {
                }
                
            });
        }
    }
    /**
     * Gets or sets the maximum allowed value.
     */
    public int getMax() {
        return getObject().getMax();
    }
    public void setMax(int value) {
        getObject().setMax(value);
    }
    /**
     * Gets or sets the current value.
     */
    public int getValue() {
        return getObject().getProgress();
    }
    public void setValue(int value) {
        getObject().setProgress(value);
    }
}
 
Last edited:

thedesolatesoul

Expert
Licensed User
Longtime User
I can post the ScrollView code if you like. However it is probably better to let the user pass an existing ScrollView to your library instead of duplicating the code.
How is it possible to handle the events for the passed scrollview from within the library (and also externally)?
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
Here is the code of ScrollView:
B4X:
package anywheresoftware.b4a.objects;

import java.util.HashMap;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.ScrollView;
import android.widget.TextView;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BALayout;
import anywheresoftware.b4a.DynamicBuilder;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.DontInheritEvents;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.Hide;
import anywheresoftware.b4a.BA.ShortName;

/**
 * ScrollView is a view that contains other views and allows the user to vertically scroll those views.
 *See the <link>ScrollView tutorial|http://www.b4x.com/forum/basic4android-getting-started-tutorials/6612-scrollview-example.html</link> for more information.
 *The ScrollView has an inner panel which actually contains the child views.
 *You can add views by calling: <code>ScrollView1.Panel.AddView(...)</code>
 *Note that it is not possible to nest scrolling views. For example a multiline EditText cannot be located inside a ScrollView.
 */
@ActivityObject
@ShortName("ScrollView")
@Events(values={"ScrollChanged(Position As Int)"})
@DontInheritEvents
public class ScrollViewWrapper extends ViewWrapper<ScrollView>{
   private PanelWrapper pw = new PanelWrapper();
   /**
    * Initializes the ScrollView and sets its inner panel height to the given height.
    *You can later change this height by calling ScrollView.Panel.Height.
    *<code>
    *Dim ScrollView1 As ScrollView
    *ScrollView1.Initialize(1000dip)</code>
    */
   public void Initialize(final BA ba, int Height) {
      Initialize2(ba, Height, "");
   }
   /**
    * Similar to Initialize. Sets the Sub that will handle the ScrollChanged event.
    */
   public void Initialize2(final BA ba, int Height, String EventName) {
      super.Initialize(ba, EventName);
      PanelWrapper p = new PanelWrapper();
      p.Initialize(ba, "");
      getObject().addView(p.getObject(), LayoutParams.FILL_PARENT, Height);
   }
   @Override
   @Hide
   public void innerInitialize(final BA ba, final String EventName, boolean keepOldObject) {
      if (!keepOldObject)
         setObject(new MyScrollView(ba.context));
      super.innerInitialize(ba, EventName, true);
      if (ba.subExists(EventName + "_scrollchanged")) {
         if (getObject() instanceof MyScrollView) {
            MyScrollView m = (MyScrollView)getObject();
            m.ba = ba;
            m.eventName = EventName;
         }
      }
   }
   /**
    * Returns the panel which you can use to add views to.
    *Example:<code>
    *ScrollView1.Panel.AddView(...)</code>
    */
   public PanelWrapper getPanel() {
      pw.setObject((ViewGroup) this.getObject().getChildAt(0));
      return pw;
   }
   /**
    * Scrolls the scroll view to the top or bottom.
    */
   public void FullScroll(boolean Bottom) {
      getObject().fullScroll(Bottom ? View.FOCUS_DOWN : View.FOCUS_UP);
   }
   /**
    * Gets or sets the scroll position.
    */
   public int getScrollPosition() {
      return getObject().getScrollY();
   }
   public void setScrollPosition(int Scroll) {
      getObject().smoothScrollTo(0, Scroll);
   }
   
   @SuppressWarnings("unchecked")
   @Hide
   public static View build(Object prev, HashMap<String, Object> props, boolean designer, Object tag) throws Exception{
      if (prev == null) {
         prev = new MyScrollView((Context)tag);
      }
      ScrollView v = (ScrollView) ViewWrapper.build(prev, props, designer);
      if (v.getChildCount() > 0)
         v.removeAllViews();
      BALayout b = new BALayout((Context)tag);
      v.addView(b, LayoutParams.FILL_PARENT, (int) (BALayout.getDeviceScale() * (Integer)props.get("innerHeight")));
      HashMap<String, Object> drawProps = (HashMap<String, Object>) props.get("drawable");
      Drawable d = DynamicBuilder.build(prev, drawProps, designer, null);
      b.setBackgroundDrawable(d);
      return v;
   }
   @Hide
   public static class MyScrollView extends ScrollView  {
      public String eventName;
      public BA ba;
      public MyScrollView(Context context) {
         super(context);
      }
      @Override
      protected void onScrollChanged(int l, int t, int oldl, int oldt) {
         super.onScrollChanged(l, t, oldl, oldt);
         if (ba != null)
            ba.raiseEvent(this, eventName + "_scrollchanged", t);
      }
   }
}

The build method is required for the designer. You do not need it.
 

derez

Expert
Licensed User
Longtime User
Thank you.
I'll probably come back with more questions later...
 

derez

Expert
Licensed User
Longtime User
Erel
I managed to add the labels.

I want to read the scroll position and do something with it, from inside the library. How can I define this event ?
 

derez

Expert
Licensed User
Longtime User
I tried but it is in another class and I can't use the setscroll and getscroll, because I don't know enough java...:BangHead: I followed the eclipse but to dead end.

Edit: I got it working !!!!
 
Last edited:

birnesoft

Active Member
Licensed User
Longtime User
I|m also no Java Expert, but getScrollPosition() und setScrollPosition() are public.

public int getScrollPosition() {
return getObject().getScrollY();
}
public void setScrollPosition(int Scroll) {
getObject().smoothScrollTo(0, Scroll);
}

how you implement the package

or make it like Erel say

public int l_p, t_p, oldl_p, oldt_p;


public int getl_p(){

return l_p;

}
public int gett_p(){

return t_p;

}
public int getoldl_p(){

return oldl_p;

}
public int getoldt_p(){

return oldt_p;

}

protected void getSrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);

l_p=l;
t_p=t;
oldl_p=oldl;
oldt_p=oldt;

if (ba != null)
ba.raiseEvent(this, eventName + "_scrollchanged", t);
}
}
}


gruss Björn
 

derez

Expert
Licensed User
Longtime User
Now for the next issue:
I'm trying to set a bitmap to a panel named overlay.
with this code:
B4X:
 getObject().addView(overlay.getObject(), LayoutParams.FILL_PARENT);
 BitmapWrapper bmp ;
 bmp.Initialize(File.getDirAssets(),"bg1.png");
 overlay.SetBackgroundImage(bmp);

The last line creates the error
The method SetBackgroundImage(Bitmap) in the type ViewWrapper<ViewGroup> is not applicable for the arguments (CanvasWrapper.BitmapWrapper)

How can I cast it to Java Bitmap ? or use another method that use BitmapWrapper ?

Another problem:
B4X:
 public void setTextSize(int TextSize)
 {
       int n = p.getNumberOfViews() ;
       for (int i=0;i<n;i++)
       p.GetView(i).setTextSize(TextSize);
 }

The last line doesn't work with the following error:
The method setTextSize(int) is undefined for the type ConcreteViewWrapper
all the views on the panel p are LabelWrapper labels.
How can I make them change the textsize ?

Thanks.
 
Last edited:

derez

Expert
Licensed User
Longtime User
Thanks Erel, it did the trick.
I got around the text problem but still would like to know how to do it with getting the views of a parent.

I managed to do the timer event so it is only cleanup, documentation and some testing to do:)
 

derez

Expert
Licensed User
Longtime User
Well, it's not the end still...
I want to add the panel with the bitmap to the scrollview, to cover the exact size of it (not the scrolling panel !)
I can't add this view, except to the moving panel which is not what I want.
This is what I tried, in the initialize method:
B4X:
overlay.Initialize(ba, "");
BitmapWrapper bmp = new BitmapWrapper() ;
bmp.Initialize(File.getDirAssets(),"cover.png");
overlay.SetBackgroundImage(bmp.getObject());
getObject().addView(overlay.getObject(), 50 ,100); // this line fails !!!
overlay.BringToFront();

Alternatively, it will be OK if the panel is not attached to the scrollview, but added to the parent of the scrollview (activity or panel) and lay on top of it exactly (use the same parameters of place and size as the scrollview object).

Please ?
 

derez

Expert
Licensed User
Longtime User
Why don't you return the object and let the user add it to the ScrollView from Basic4android?
That of course is the simplest solution but I thought to make the library as one package. If it is to complicated - I'll use this way.

What error do you get?

It just fails in the initialization, but I'll try to get the log.
 
Top