Unable to programmatically scroll to top of ScrollView or SetFocus - android

I have a ScrollView with a nested LinearLayout that has some length to it. At the bottom I have a button that has a function that will need to act similarly to a Return to Top.
I've tried creating an onClickListener and with setFocusableInTouchMode and setFocusable set to true, use the listener to request focus. No luck.
I've tried the following without success.
scrollView.smoothScrollTo(0,0);
scrollView.fullScroll(scrollView.FOCUS_UP);
scrollGetStartedGetMostFromLearning.fullScroll(View.FOCUS_UP);
XML
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Title"
android:id="#+id/textgTitle"
android:textColor="#F0F0F0"
android:textSize="30sp"
android:focusable="true"
android:focusableInTouchMode="true"/>
<Button
android:id="#+id/btnTop"
android:text="To Top"
android:textSize="25sp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/white"
/>
</LinearLayout>
</ScrollView>
Java
btnTop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
scrollView.fullScroll(View.FOCUS_UP);
} //or any of the 3 used above
Any help or direction as to what I'm doing wrong is appreciated. Thanks!

Related

Android frame layout click listener not working

I've got a FrameLayout with two nested LinearLayouts. I want an onClickListener() for FrameLayout. After a search I got a solution clickable="false".
This is my Layout file:
<FrameLayout
android:id="#+id/flOuter"
android:paddingLeft="#dimen/half_margin"
android:paddingRight="#dimen/half_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:clickable="false"
android:gravity="center"
android:id="#+id/flAddIdProof"
android:background="#drawable/add_background"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:clickable="false"
android:id="#+id/ivIcon"
android:src="#drawable/ic_add_black_48dp"
android:background="#drawable/add_button_border"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:clickable="false"
android:id="#+id/llLinear"
android:alpha="0.5"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:enabled="false"
android:clickable="false"
android:drawablePadding="#dimen/half_margin"
android:drawableLeft="#drawable/ic_devices_black_24dp"
android:hint="Identity Proof"
android:inputType="none"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:enabled="false"
android:clickable="false"
android:drawableLeft="#drawable/ic_border_color_black_24dp"
android:hint="Identity Number"
android:drawablePadding="#dimen/half_margin"
android:inputType="none"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</FrameLayout>
Here is my click listener:
flOuter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(DeviceInMeeting.this, "detect", Toast.LENGTH_SHORT).show();
}
});
I don't know how to debug for onClick listeners, clickable="false" is not working in my case.
Try implementing android:clickable="true" in Following code snippet for FrameLayout
<FrameLayout
android:id="#+id/flOuter"
android:clickable="true"
android:focusable="true"
android:foreground="attr/selectableItemBackground"
android:paddingLeft="#dimen/half_margin"
android:paddingRight="#dimen/half_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content">
and adding android:clickable="false" in other nested layout.
<LinearLayout
android:id="#+id/flOuter"
android:clickable="false" />
You are using it wrong. Try using:
<FrameLayout
android:id="#+id/flOuter"
android:paddingLeft="#dimen/half_margin"
android:paddingRight="#dimen/half_margin"
android:layout_width="match_parent"
android:clickable="true"
android:layout_height="wrap_content">
// Other layouts there
</FrameLayout>
For fields you don't want to be clicked add clickable=false to them.
And for fields for which you wan't click event add clickable=true for them.
One thing to remember here is that if your child elements contain some clickable elements like buttons and edittexts and then you want to get click event on parent layout then add clickable false to the child and true to the parent.
You need to set OnTouchListener instead onClickListener. In onTouch method you can decide if touch event is pass to children (by returning false) or consume event.
On your case you should do your logic and return true.

OnClickListener Layout detection

I've a custom button layout: Its a FrameLayout as a background with a normal Button in the center with an icon next to the text.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/framelayout"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:background="#F00">
<android.support.v7.widget.AppCompatButton
android:id="#+id/buttonWithIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:background="#null"
android:drawableStart="#android:drawable/ic_delete"
android:gravity="center"
android:textAllCaps="false"
android:textColor="#FFF"/>
</FrameLayout>
I had an onClickListeners on the Button and I realized, clicks on the background (=FrameLayout) weren't detected. Because of this I want an onClickListener that detects clicks on the FrameLayout and also on the Button, without having two Listeners, that do the same.
I tried giving the RelativeLayout an ID, but the layout couldn't be found (=null).
Maybe my button layout isn't optimal. But I need a fullwidth button with a icon next to the text, without any spaces between the icon and the text.
The Icons gets set like this
button.setCompoundDrawablesWithIntrinsicBounds(R.mipmap.ic_icon, 0, 0,0);
Thank you
You can just add one OnClickListener to both views. That way, you only write your code once, and if you click either the FrameLayout or the Button that same code will run.
final View.OnClickListener mOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Add Your OnClick Code Here
}
};
framelayout.setOnClickListener(mOnClickListener);
buttonWithIcon.setOnClickListener(mOnClickListener);
You can put all of your views that you want them to be clickable and remove all clickListeners of entire views.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/linearlayout">
<FrameLayout
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:background="#F00">
<android.support.v7.widget.AppCompatButton
android:id="#+id/buttonWithIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:background="#null"
android:drawableStart="#android:drawable/ic_delete"
android:gravity="center"
android:textAllCaps="false"
android:textColor="#FFF"/>
</FrameLayout>
</LinearLayout>
and add this clickListener to LinearLayout:
LinearLayout linearlayout=(linearLayout)findViewById(R.id.linearlayout);
linearlayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Add Your Code Here
}
});
Create a function in your Activity with a View Argument, and in your layout, set the onClick to your two views.
Activity:
public void myAction(View v){
// Do what you want
}
Your Layout:
<FrameLayout
android:id="#+id/framelayout"
style="?android:attr/buttonStyle"
android:onClick="myAction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:background="#F00">
<android.support.v7.widget.AppCompatButton
android:id="#+id/buttonWithIcon"
android:onClick="myAction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:background="#null"
android:drawableStart="#android:drawable/ic_delete"
android:gravity="center"
android:textAllCaps="false"
android:textColor="#FFF"/>
</FrameLayout>
Maybe adding in just the FrameLayout may dispatch the event in the button also, i can't test right now :)

Scrollview with many buttons over an image

I want to do something similar to a Map behavior where I have a large Image (bigger than the phone screen) and a group of buttons I want to put over special XY locations over the image, and when the user scrolls the image (horizontally and vertically), the buttons keep the same position over the image (like markers do). Then the user can click over a button and open a new activity.
I want to do this in xml. Any suggestion?
I cant figure out how to attach the buttons with the image XY positions:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/map_view"
android:background="#drawable/myImage"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Position 1"
android:id="#+id/radioButton" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Position 2"
android:id="#+id/radioButton2" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Position 3"
android:id="#+id/radioButton3" />`
/>
</RelativeLayout>
</ScrollView>
Instead of scrollview you should change imageview position on touch. If user touches top-down , imageview position should goes to negative direction same as top-down pixels. Therefore your imageview can move to right-left as well.
Get the touch position inside the imageview in android
Android move view on touch event
Here, make sure the the ImageView should always be larger than the screen as you say.
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/map_view"
android:layout_width="1800px"
android:layout_height="1800px"
android:background="#drawable/the_large_image"/>
<RadioButton
android:id="#+id/radioButton"
android:layout_marginTop="20dp"
android:layout_marginLeft="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Position 1"/>
<RadioButton
android:id="#+id/radioButton2"
android:layout_marginTop="200dp"
android:layout_marginLeft="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Position 2"/>
<RadioButton
android:id="#+id/radioButton3"
android:layout_marginTop="80dp"
android:layout_marginLeft="60dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Position 3"/>
</RelativeLayout>
</ScrollView>
Thanks to #Sheychan that gave me some clue for getting this as I wanted.
First of all: the xml. Use 2 scroll views (one main that is vertical, and another horizontal), so that we can get horizontal and vertical scrolling. Then a RelativeLayout so that we can put the radiobuttons over the image in desired positions. Is important the "src" and "scaleType" in image so that we can get correct image dimensions. Here is the code for xml
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/svVertical">
<HorizontalScrollView android:id="#+id/hsvHorizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:isScrollContainer="true">
<ImageView
android:id="#+id/map_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/imagen"
android:scaleType="centerCrop"/>
<RadioButton
android:id="#+id/radioButton"
android:layout_marginTop="20dp"
android:layout_marginLeft="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Position 1"/>
<RadioButton
android:id="#+id/radioButton2"
android:layout_marginTop="200dp"
android:layout_marginLeft="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Position 2"/>
<RadioButton
android:id="#+id/radioButton3"
android:layout_marginTop="80dp"
android:layout_marginLeft="60dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Position 3"/>
</RelativeLayout>
</HorizontalScrollView>
</ScrollView>
But with this solution we got odd scrolling (only vertical or horizontal, not both at the same time: call it "diagonal" scrolling). To resolve this: a simple override on Activity holding this layout:
ScrollView scrollY;
HorizontalScrollView scrollYChild;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollY = (ScrollView)findViewById(R.id.svVertical);
scrollYChild = (HorizontalScrollView)findViewById(R.id.hsvHorizontal);
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
scrollYChild.dispatchTouchEvent(event);
scrollY.onTouchEvent(event);
return super.dispatchTouchEvent(event);
}
This start working better, but still in an odd way. Is like the move "jumps" while scrolling.
The solution: take away the action bar:
On the Manifest, add the "NoActionBar" theme in the application tag (or the activity tag)
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.Holo.NoActionBar.Fullscreen" >
...
</application>
But, be careful, cause the activity must not be an "ActionBarActivity", you must change it to "Activity".
And, just in case, by Android recommendation, add a compatible old SDK versions with a "hide the status bar" on the OnCreate of the Activity.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// If the Android version is lower than Jellybean, use this call to hide
// the status bar.
if (Build.VERSION.SDK_INT < 16) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
setContentView(R.layout.activity_main);
scrollY = (ScrollView)findViewById(R.id.svVertical);
scrollYChild = (HorizontalScrollView)findViewById(R.id.hsvHorizontal);
}
And that's all folks :) Hope it helps you as it helped me.

Setting focus on LinearLayout

I am trying to set focus on a LinearLayout view when returning to an activity from another activity. The scenario:
I have one activity with a bunch of LinearLayout items (with stuff in them), some of which are text, others photos. Let's say the top most of 20 is a TextView and the rest are photos. When I leave this activity (to take a picture), activity goes to the top of the list where the TextView is - no matter what I do.
How do I force the focus back on the item that I was on before the new activity was triggered?
I have already tried this with no success:
[How Linear Layout get Focus?
I am currently trying to force the focus by remembering the previous view without success (though I can see the code being executed). The in my main activity:
#Override
public void onResume() {
super.onResume();
// See if we had a field with focus previously...
if (mPreviousView != null) {
if (mPreviousView.isFocusable()) {
mPreviousView.requestFocus();
}
}
}
...
#Override
protected void onPause() {
super.onPause();
mPreviousView = this.getCurrentFocus();
}
I am dynamically setting the focus in the LinearLayout:
private void initialize() {
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.field_photo_picker, this);
// To allow focus to be returned to control after taking photo
this.setFocusableInTouchMode(true);
this.setFocusable(true);
this.setClickable(true);
And finally the XML for the LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="5dp"
android:paddingBottom="5dp">
<TextView
android:id="#+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="normal"
android:text="" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/photoValue"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="17sp"
android:textStyle="normal"
android:gravity="right|center_vertical"
android:layout_weight="1"
android:layout_marginRight="5dp"
android:text="" />
<ImageButton
android:id="#+id/photoPicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/form_photo"
android:padding ="5dp"
android:gravity="center_vertical"
android:focusableInTouchMode="false"
android:background="?android:attr/selectableItemBackground"
android:layout_weight="0"
/>
</LinearLayout>
<View
android:layout_marginTop="8dp"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/grey" />
</LinearLayout>
</merge>
make your textview and other views focusable, you made this.setFocusable(true); which doesn't make sense

Event passing to sibling on clicking a view

I have a simple LinearLayout(horizontal) with 3 TextViews. The background of these TextViews are set to a drawable that has two states, state_pressed and default. I simply change the background of each TextView to red on state_pressed.
But when i click one TextView, its click listener is invoked but background of all 3 changes to red. This is happening on Android 2.x and working fine on Android 4.0+.
<LinearLayout
android:id="#+id/back"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:paddingLeft="#dimen/swipe_list_leftoffest"
android:descendantFocusability="blocksDescendants"
android:background="#color/list_swipe_back"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:weightSum="3"
android:tag="back">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:clickable="true"
android:layout_weight="1"
android:gravity="center"
android:id="#+id/amenities_view"
android:padding="#dimen/padding_large"
android:background="#drawable/swipe_view_background"
android:drawablePadding="#dimen/padding_large"
android:textColor="#color/white"
android:text="#string/amenities_text"
android:drawableTop="#drawable/ic_amenities"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_weight="1"
android:clickable="true"
android:gravity="center"
android:ellipsize="end"
android:singleLine="true"
android:id="#+id/cancpolicy_view"
android:padding="#dimen/padding_large"
android:background="#drawable/swipe_view_background"
android:drawablePadding="#dimen/padding_large"
android:textColor="#color/white"
android:text="#string/canc_policy_text"
android:drawableTop="#drawable/ic_cancellation_policy"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_weight="1"
android:gravity="center"
android:clickable="true"
android:padding="#dimen/padding_large"
android:id="#+id/reviews_view"
android:background="#drawable/swipe_view_background"
android:drawablePadding="#dimen/padding_large"
android:textColor="#color/white"
android:text="#string/reviews_text"
android:drawableTop="#drawable/ic_reviews"
/>
</LinearLayout>
Tried putting focusable and focusableInTouchMode false for each of the TextViews, but that didnt help.
Do you have 3 separate onClickListeners for the TextViews? If you have only one, this may be the problem and you could solve it by doing something like this in the listener:
public void onClick(View v){
switch(v.getId()){
case R.id.amenities_view:
//Click first
break;
case R.id.cancpolicy_view:
//Click second
break;
case R.id.reviews_view:
//Click third
break;
}
}
If you do not create this switch, all the views associated with the listener will react to the click.

Categories

Resources