Locking Horizontal ScrollView - Android - android

I'm writting an application and it looks like this:
How you can see there is SeekBar on top and several buttons in HorizontalScrolView below. I would like to use SeekBar to scrolling buttons and this works fine now, but I can't turn off the default way to scroll View (draginng screen). I found similat topic on forum:
Similar Topic
But the problem is, that this way locking whole ScrollView and I cant use it by seekBar and default way - maybe I'm doing something wrong (I did it the same like in the link and this not wort even if I have TRUE in mScrollable parameter). The second problem is that my buttons (which have fill_parent height parameter) are really small.
Question: There is any good way to Lock Scrolling View in default way and use SeekBar to do this??
My Code (default HorizontalScrollView):
public class MainActivity extends Activity implements SeekBar.OnSeekBarChangeListener {
static private String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
SeekBar seek = (SeekBar) findViewById(R.id.seekBar);
final HorizontalScrollView hsv = (HorizontalScrollView)findViewById(R.id.hsv);
seek.setMax(948);
seek.setProgress(474);
seek.setOnSeekBarChangeListener(this);
hsv.post(new Runnable() {
#Override
public void run() {
hsv.scrollTo(474, 0);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
HorizontalScrollView hsv = (HorizontalScrollView)findViewById(R.id.hsv);
hsv.scrollTo(progress, 0);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
Log.d(TAG, "Tracking on");
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
Log.d(TAG, "Tracking off");
}
activity_main:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#0A0A0A"
android:orientation="vertical" >
<SeekBar
android:id="#+id/seekBar"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<HorizontalScrollView
android:id="#+id/hsv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="none" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<!-- BUTTONS CODE - NOT IMPORTANT -->
</RelativeLayout>
</HorizontalScrollView>
</LinearLayout>

There is any good way to Lock Scrolling View in default way and use
SeekBar to do this??
Edit:
The solution seems to be much simpler, override the HorizontalScrollView class and pass the touch events through the view:
public class MyHScroll extends HorizontalScrollView {
// the constructors
#Override
public boolean onTouchEvent(MotionEvent ev) {
return false;
}
}
The use this class in the layout instead of the default HorizontallScrollView:
<com.your.package.MyHScroll
android:id="#+id/hsv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="none" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<!-- BUTTONS CODE - NOT IMPORTANT -->
</RelativeLayout>
</com.your.package.MyHScroll>
Try placing an overlay view on top of the HorizontalScrollView to "absorb" touch events without messing with the HorizontalScrollView itself:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#0A0A0A"
android:orientation="vertical" >
<SeekBar
android:id="#+id/seekBar"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout android:layout_width="wrap_content"
android:layout_height="fill_parent">
<HorizontalScrollView
android:id="#+id/hsv"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:scrollbars="none" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<!-- BUTTONS CODE - NOT IMPORTANT -->
</RelativeLayout>
</HorizontalScrollView>
<View android:id="#+id/overlay" android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</FrameLayout
</LinearLayout>
and then add a OnTouchListener for the overlay widget in the onCreate method to further block touch events:
findViewById(R.id.overlay).setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
The second problem is that my buttons (which have fill_parent height
parameter) are really small.
See the layout file above.

Related

Clicking a scroll view

I have a scroll view that has a Linearlayout child and this linearlayout has a drawingview.
the problem : I tried almost all the available answers on this topic and none of them worked, I cant understand why click is not fired for (scrollview, linear layout and even drawingview).
note : I tried setting on click for each of the three and none worked.
the xml code:
<ScrollView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#id/scrollview"
android:clickable="true"
>
<LinearLayout
android:setorientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#id/linear"
android:clickable="false">
<Customview
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#id/draw"
android:clickable="false"/>
</LinearLayout>
</ScrollView>
First your ScrollView ,layout_height is wrapped! and for children you gave match_parent i doubt your view won't even display. Isn't it?
Then no idea why you use setorientation and android:id="#id/draw" instead of android:orientation and android:id="#+id
If you want to check scrolling works use
scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
Log.d("TAG", "onScrollChanged: ");
// DO SOMETHING WITH THE SCROLL COORDINATES
}
});
You are using unnecessary attributes check this example :
<?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:background="#8768"
android:orientation="vertical">
<ScrollView
android:id="#+id/scrollIndicatorDown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#823">
<LinearLayout
android:id="#+id/first_child"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#900"
android:orientation="vertical">
<LinearLayout
android:id="#+id/linear_layout"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#000"
android:orientation="vertical"></LinearLayout>
<LinearLayout
android:id="#+id/web_view"
android:layout_width="match_parent"
android:layout_height="500dp"
android:background="#987"
android:orientation="vertical"></LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
If you write an onClickListner to the id linear_layout it just work normally!
Answer :The child Views of your ScrollView are consuming the click events you do on the ScrollView.
The solution to this problem is to set the onClickLIstener to the immediate child of the ScrollView(It's child).
So according to my example if i want to find out the ScrollView onClick i write my listener to its child.
scrolChild =(LinearLayout) findViewById(R.id.first_child) ;
scrolChild .setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(YourActivityName.this, "You Clicked Me OH yeaaaaa", Toast.LENGTH_SHORT).show();
}
});
Read here when you need androidclickable-true android:clickable="true" mean's that it's not clickable?
This is my activity
public class MainActivity extends AppCompatActivity {
private ScrollView scrollView;
private LinearLayout scroolChild;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.web);
scrollView = (ScrollView) findViewById(R.id.scrollIndicatorDown);
scroolChild =(LinearLayout) findViewById(R.id.first_child) ;
scroolChild.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "You Clicked Me OH yeaaaaa", Toast.LENGTH_SHORT).show();
}
});
scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
Log.d("TAG", "GotAScrollChanged: ");
// DO SOMETHING WITH THE SCROLL COORDINATES
}
});
}
}
You have set android:clickable="false" for both make it true it will work for you
<ScrollView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#id/scrollview"
android:clickable="true"
>
<LinearLayout
android:setorientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#id/linear"
android:clickable="true">
<Customview
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#id/draw"
android:clickable="true"/>
</LinearLayout>
</ScrollView>

ListView cannot show after being invsibile during onCreate

I have problem I want to hide the listVeiw during onCreate,but the problem is that when I hide my listview to invisible, the setOnTouchListener will not work.but if I remove lstv.setVisibility(View.INVISIBLE); before the setOnTouchListener, the setOnTouchListener is working,but I need to hide first my listview during start up or onCreate.
Thank you in advance.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lstv.setVisibility(View.INVISIBLE);
vdo.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
lstv.setVisibility(View.VISIBLE);
lstv.postDelayed(new Runnable() {
#Override
public void run() {
lstv.setVisibility(View.INVISIBLE);
}
}, 3000);
return true;
}
});
}
activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#000000"
tools:context=".MainActivity" >
<VideoView
android:id="#+id/vdo"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/listview"
android:layout_width="229dp"
android:layout_height="fill_parent"
android:smoothScrollbar="true"
android:soundEffectsEnabled="true"
/>
</FrameLayout >
For hide ListView and receive onTouchEvent on vdo
You should change
lstv.setVisibility(View.INVISIBLE);
to
lstv.setVisibility(View.GONE);
Hope this help
You can hide the listview in the layout(xml) itself. Like this
<ListView
....
....
android:visibility="gone"
/>

Android SeekBarChangeListener and TouchListener No Events

I'm having an issue with button click events and seekbar events not firing. When I drag on my seekbar, the slider changes position visually but there's no event being fired in my OnSeekBarChangedListener. I also have an ImageButton that should receive click events but it does not fire either. The MyView at the bottom here handles touch events properly. It holds a GLSurfaceView that I can pan around and pinch-zoom on. What could be causing the events to not fire?
Here's my layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/tec_root">
<ImageButton
android:id="#+id/button_star"
android:contentDescription="#string/star_description"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginTop="16dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:src="#drawable/star_empty"
android:background="#00000000"
android:scaleType="fitXY"/>
<LinearLayout
android:id="#+id/view_plot"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_below="#id/button_star"/>
<SeekBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#id/button_star"
android:layout_toStartOf="#id/button_star"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:progress="50"
android:layout_alignBaseline="#id/button_star"
android:id="#+id/seekbar" />
</RelativeLayout>
And here are the listeners:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
starred = prefs.getBoolean("starred", false);
final ImageButton starButton = (ImageButton) findViewById(R.id.button_star);
starButton.setImageDrawable(ContextCompat.getDrawable(this, (starred ? R.drawable.star_filled :
R.drawable.star_empty)));
starButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
starred = !starred;
prefsEditor = prefs.edit();
prefsEditor.putBoolean("starred", starred);
prefsEditor.apply();
starButton.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(),
(starred ? R.drawable.star_filled : R.drawable.star_empty)));
}
});
((SeekBar) findViewById(R.id.seekbar)).setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
Log.e("TEST", "Seekbar onProgressChanged called");
Toast.makeText(getApplicationContext(), "Seekbar fired", Toast.LENGTH_SHORT).show();
// respond to update
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
MyView myView = new MyView(this, points, false);
((LinearLayout) findViewById(R.id.view_plot)).addView(myView);
}
try this, replace LinearLayout with FrameLayout, it's not best at perfomance but works well
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tec_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<SeekBar
android:id="#+id/seekbar"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:background="#ABABAB"
android:layout_weight="1"
android:progress="50" />
<ImageButton
android:id="#+id/button_star"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="#00000000"
android:contentDescription="#string/star_description"
android:scaleType="fitXY"
android:src="#drawable/star_empty" />
</LinearLayout>
<FrameLayout
android:id="#+id/view_plot"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
/>
</LinearLayout>
Try changing your code to this:
MyView myView = new MyView(this, points, false);
myView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
((LinearLayout) findViewById(R.id.view_plot)).addView(myView);
Could this be reproduced by removing the GLSurfaceView?
If so, changing SurfaceView.setZOrderOnTop might help.
http://developer.android.com/reference/android/view/SurfaceView.html#setZOrderOnTop(boolean)
there may be issue of layout design so please rearrange the components of ui.
seekbar is over imagebutton so android platform is not able to detect touch event.
set layout_below in seekbar
One possible reason for this could be touch handling in custom MyView. We have to be very careful about return value of onTouchEvent() function. Try returning "true" from your onTouchEvent() if you are consuming event else return "false".

Android RelativeLayout onclicklistener doesn't get fired

This is my XML layout - it's an info window.
i want that when the user clicks the #+id/fragment_info_relativelayout_content layout - the info window will be closed.
This is my XML:
<RelativeLayout
android:id="#+id/fragment_info_relativelayout_content"
android:layout_width="fill_parent"
android:layout_height="70dp"
android:background="#drawable/background_info_window"
android:clickable="true" >
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerInParent="true"
android:layout_margin="5dp" >
<!-- The info textView -->
<com.coapps.pico.NillanTextView
android:id="#+id/fragment_info_textview_info"
style="#style/text_shadow_black"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp"
android:gravity="center"
android:text="Some Text "
android:textColor="#android:color/white"
app:isBold="true" />
</ScrollView>
<!-- Tap to close -->
<com.coapps.pico.NillanTextView
android:id="#+id/fragment_info_textview_tap_to_close"
style="#style/text_shadow_black"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:gravity="right"
android:paddingRight="5dp"
android:text="#string/button_tap_to_close"
android:textColor="#android:color/white"
app:isBold="true" />
</RelativeLayout>
This is my code:
public InfoWindow(ViewGroup rootView)
{
this.container = rootView;
infoWindowView = LayoutInflater.from(rootView.getContext()).inflate(INFO_WINDOW_LAYOUT_ID, null);
//find info window's view
contentLayout = infoWindowView.findViewById(R.id.fragment_info_relativelayout_content);
contentLayout.setClickable(true);
contentLayout.setOnClickListener(this);
}
#Override
public void onClick(View v) {
//close the info window
close();
}
my problem is that the onClick method isn't being fired on every click on the layout...
it's weird since it does fire after clicking some clicks, or click at the bottom right on the textview...
any ideas ??
My suggestion, is that the ScrollView in the RelativeLayout handles all touch events, and don't let the RelativeLayout handle any touch events.
In this case, you should extend the ScrollView and make the onTouchEvent return false
#Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
return false;
}
And the same to onInterceptTouchEvent
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
super.onInterceptTouchEvent(ev);
return false;
}
Just try it out and tell me what you got =)

How can i check that the LinearLayout is clicked or not

This is my xml file and as you can see it is nested many times by Linear layout.
What i want to acheive is when I click on the area of llOptionA(First
Linear Layout) i will get notified by a toast.
I have also put a toast on llOptionA.setonclickListener()
But when i click on the text it does nothing.
then I also set onclicklisteners on each of them giving me different toasts -> svTest ,layout_inner ,tvOptionA. and also i clicked everywhere to see which part is showing which toast.
<LinearLayout
android:id="#+id/llOptionA"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#ff00ff"
android:paddingLeft="30dp"
android:paddingRight="30dp"
android:paddingTop="5dp" >
<HorizontalScrollView
android:id="#+id/svTest"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:id="#+id/layout_inner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/tvOptionA"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="A - Option A "
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#ffffff"
android:textStyle="bold" />
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
First a LinearLayout does not listen for click events by default even when you set an OnClickListener. You also need to add this attribute to your LinearLayout llOptionA:
android:clickable="true"
Second a click starts at the highest level, TextView tvOptionA, and works it's way down until a View consumes this event. So before it reaches llOptionA your HorizontalScrollView intercepts the click in it's default OnTouchListener and doesn't pass it down to your llOptionA... You can listener for a click event with an OnTouchListener in your HorizontalScrollView to call the appropriate method.
Third perhaps this is a simplified layout, but the LinearLayout layout_inner only has one child and therefor is not necessary, you can simply use this:
<LinearLayout ...>
<HorizontalScrollView ...>
<TextView .../>
</HorizontalScrollView>
</LinearLayout>
Of course llOptionA only has one child so you could simplify it more:
<HorizontalScrollView ...>
<TextView .../>
</HorizontalScrollView>
Addition from comments
Here is how to put it all together:
public class Example extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.llOptionA);
linearLayout.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
toast();
}
});
HorizontalScrollView hsv = (HorizontalScrollView) findViewById(R.id.svTest);
hsv.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP)
toast();
return false;
}
});
}
public void toast() {
Toast.makeText(this, "Click", Toast.LENGTH_SHORT).show();
}
}

Categories

Resources