I found a weird behavior on Android.
Let's say I have a list View and each row is a Linear layout containing a textView.
I set a longClickListener on the listView. Also, I set an onTouchEvent on the textView.
The behavior I want is that if the user press the textView in the list, onTouchEvent should be run. If the user Long-presses outside the textView, it should perform what's defined in the longClickListener.
However, in Android 4.2.1, this behavoir doesn't seem to work.
I found that Google changed the code so that ChildView shares pressed state from its parent view in Jelly Bean. Is this right?
If this is the case, how can I implement the way I want?
On other words, I want the childView and parentView behave independently!!
Any answer would be appreciated!
Below is my CustomTextView.java
public class CustomTextView extends TextView {
public CustomTextView(Context context) {
super(context);
setPressed(false);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setPressed(false);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setPressed(false);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
Intent.... something
Start a new activity... pretty straightforward
return super.onTouchEvent(event);
}
}
Below is the textview of my list_item.xml
<com.keek.widget.CustomTextView
android:id="#+id/caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/thumbnail_overlay"
android:lineSpacingExtra="1dp"
android:textColor="#android:color/black"
android:textSize="#dimen/text_11"
android:duplicateParentState="false"
android:longClickable="false"
android:textColorLink="#color/linkify_blue" />
My list is pretty straightforward. It is a plain listView with onLongClickListener which opens a dialog box.
The this is that when I press the textView, both the dialogbox and new activity open at the same time. What I want is that when I press textView, it should open a new activity only not a dialog.
Related
My layout has a lot of elements and I want to divide them using "divider":
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="#android:color/black"/>
But I don't want to add the same divider 10 times in layout. Can I do something to help me to add divider only one time? With button I have the same question. I have 3 button in different places in my layout, but this button doing the same. How can i bind one action for three button and add only one time in layout?
If you have a lot of Items that use the same layout, ie. they look a lot like each other, ListView with an ArrayAdapter is very, very useful.
You can done this type of job by creating custom button. Custom button extends the Button class. Something like this e.g:
public class MyButton extends Button {
public MyButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.your_custom_button_layout, this, true);
}
public MyButton(Context context) {
super(context);
}
}
I am using TabHost inside ScrollView in my Activity but when ever I select tab it automatically scrolls my view vertically to end.
In this case child view getting focus due to that it get scrolled upward.
for resolve this you need to create custom ScrollView that extend ScrollView.
code snipt will look like this.
public class MyScrollView extends ScrollView {
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void requestChildFocus(View child, View focused) {
// if (focused instanceof TabHost) // here
return;
//super.requestChildFocus(child, focused);
// here you need to return instead of **super.requestChildFocus(child, focused);**
}
and xml looks like this
<com.views.widget.MyScrollView
android:focusable="false"
android:focusableInTouchMode="false"
android:id="#+id/root_scroll_view"
android:layout_width="match_parent"
android:fillViewport="true"
android:layout_height="wrap_content">
</com.views.widget.MyScrollView >
Based on Er Pragati Singh's answer I did not override requestChildFocus(View child, View focused) but computeScrollDeltaToGetChildRectOnScreen(Rect rect).
Overriding requestChildFocus will also prevent activating the on screen keyboard when touching an EditText which already has focus, while computeScrollDeltaToGetChildRectOnScreen is only used to calculate the delta scroll inside requestChildFocus to bring the View in sight. So overriding this function keeps all other routines intact.
Java:
public class MyScrollView extends ScrollView {
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
// This function calculates the scroll delta to bring the focused view on screen.
// -> To prevent unsolicited scrolling to the focued view we'll just return 0 here.
//
return 0;
}
}
XML:
<YOUR.PAKAGE.NAME.MyScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
</YOUR.PAKAGE.NAME.MyScrollView>
I have Fragment with a View which contains some clickable elements (ToggleButtons and a GridView).
I have set an onTouchListener on the View which I use to detect simple swipe gestures, this works perfectly well as long as the swipe doesn't start on any of the clickable items. I would like the swipe to work regardless of where it starts.
I understand that the ToggleButtons and GridView are probably consuming the touch event and in classes which extend ViewGroup I could override onInterceptTouchEvent or dispatchTouchEvent in subclasses of Activity.
Any ideas how I could deal with this situation when extending Fragment?
The closest I've found here is: Android adding onInterceptTouchEvent to a fragment Unfortunately there have been no replies to this question.
Thanks in anticipation.
Okay, got there in the end.
I create a subclass of RelativeLayout which is the root of my layout and then within this I override onInterceptTouchEvent.
public class RootLayout extends RelativeLayout {
public RootLayout(Context context) {
super(context);
}
public RootLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RootLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
return true;
}
}
Then replace the RelativeLayout in my xml with the new subclass.
<com.walker.leigh.dipswitch2.RootLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
Thanks for your help :)
I use a HorizontalScrollView to contain a bunch of dynamic TextView elements. They are dropped into a LinearLayout container that is the only child of the scroll view:
<HorizontalScrollView android:id="#+id/outline_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:requiresFadingEdge="horizontal"
android:fadingEdgeLength="16dp">
<LinearLayout android:id="#+id/outline"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</HorizontalScrollView>
This is to ensure that if (and only if) there's more text than the available width can show, the user can scroll horizontally through the texts.
BUT: in many, many cases, the texts are short enough to be shown on screen. The LinearLayout container with id outline thus fits completely within the HorizontalScrollView.
Problem is: horizontal swipe gestures are still caught but should not be, because the whole thing is within a ViewPager which itself would like to handle the horizontal swipes!
I am looking for a solution that enables this HorizontalScrollView's scrolling only if the room for the contents is too limited.
In order to prevent the HorizontalScrollView from scroll, you have to override the onTouchEvent method to return false. That led me to create my own HSV like so:
public class MyHorizontalScrollView extends HorizontalScrollView{
boolean tooSmall = true;
public MyHorizontalScrollView(Context context) {
super(context);
}
public MyHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setTooSmall(boolean tooSmall){
this.tooSmall = tooSmall;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
if(tooSmall)
return false;
else
return super.onTouchEvent(ev);
}
}
Then, after you replace your HSV with this custom view, you need monitor the size of your LinearLayout(R.id.outline) to see if it is smaller or larger than your HSV. Adding this snippet helped me achieve that goal.
ll = (LinearLayout) view.findViewById(R.id.outline);
hsv = (MyHorizontalScrollView) view.findViewById(R.id.outline_container);
ll.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Log.d("widths", ll.getWidth() + " : " + hsv.getWidth());
hsv.setTooSmall(ll.getWidth() < hsv.getWidth());
}
});
I have custom view which extends imageview (with glow touch). I want to add elements like buttons, textviews, to make glow touch when they are touched. I read that custom view cannot have children because only layouts can have them.
Is there any workaround to solve this stuff?
Code:
public class CustomView extends ImageView{
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomView(Context context) {
super(context);
.........
}
With regards
You are correct about the fact that only layouts (ViewGroups) can contain Views, and Views itself can not.
Instead of making a custom View, you can make a custom ViewGroup. In there you can add the Views you need, like the ImageViews and the others you mention (Buttons, EditText, etc).