14

私は水平RecyclerViewleftPadding = 48dptopPadding = 24dpclipToPadding = falseです。それは、左の空白で始まりますが、ユーザがリストをスクロールすると、そのアイテムは(以前は空の)スペースに描画されます。上部スペースは常に空です。Recyclerview:パディングのクリックイベントを聞く

enter image description here

このRecyclerViewforeground = selectableItemBackgroundとでframeLayoutの内側にあります。

私の問題はRecyclerView消費とは、OnClickListenerがトリガされることはありません意味、左と上のスペースにタッチを無視しているという事実から来ているの両方FrameLayoutまたはRecyclerViewに取り付けたとき。

私はすでにRecyclerViewclickable = falsefocusable = falseと試みたが、それは動作しません。

私は何を探しています:

  1. スクロールRecyclerView enter image description here
  2. クリッカブルRecyclerView項目RecyclerView's空のスペースが
  3. (代替3)がクリックされ enter image description here
  4. FrameLayoutクリックイベントクリッカブルRecyclerView's空白 enter image description here enter image description here

編集:私は私が話している問題を示して単純なプロジェクトを作成しました:https://github.com/dadino/recyclerviewemptyspacestest 2コミット私は親ビューのクリックをキャッチしようとする最初のものであります、もう1つは、RecyclerView自体のクリックを捕らえようとしています。どちらも動作しません。

+0

あなたのコードを表示してください。 – HassanUsman

+0

どのようなコードを見たいですか? ur recyclerviewアダプターの –

+0

は、グローバルクリックリスナーとアイテムクリックリスナーを置いていなければなりません。詳細についての投稿コード –

答えて

12

カスタムRecyclerViewのインプリメンテーションを作成する必要があります。ここでは、イベントをタッチしてそれに基づいてフィルタリングを行います。

class MyRecyclerView @JvmOverloads constructor(
     context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 
) : RecyclerView(context, attrs, defStyleAttr) { 

    private var isValid = false 
    private var x: Int = 0 
    private var y: Int = 0 
    // this will help us to understand whether the event can be considered a touch or scroll 
    private val delta: Int = ViewConfiguration.get(getContext()).scaledTouchSlop 

    override fun onTouchEvent(e: MotionEvent?): Boolean { 
     val onTouchEvent = super.onTouchEvent(e) 
     when (e?.action) { 
      MotionEvent.ACTION_DOWN -> { 
       // saving initial touch location 
       x = e.rawX.toInt() 
       y = e.rawY.toInt() 
       isValid = true 
      } 
      MotionEvent.ACTION_MOVE -> { 
       if (Math.abs(e.rawX - x) > delta || 
         Math.abs(e.rawY - y) > delta) { 
        // if a scroll happens - no longer consider this movement as valid 
        // this is needed for handling scroll on the inner part of `RecyclerView`        
        isValid = false 
       } 
      } 
      MotionEvent.ACTION_UP -> { 
       if (isValid && Math.abs(e.rawX - x) < delta && 
         Math.abs(e.rawY - y) < delta && 
         isInRightArea(e)) { 
        // 1. if the movement is still valid 
        // 2. we have actually performed a click        
        // 3. the click is in expected rectangle 
        // then perform click 
        performClick() 
       } 
      } 
     } 
     return onTouchEvent 
    } 

    // This is needed in order to handle the edge case, when a click listener 
    // would be fired when performing a click between the items of `RecyclerView` 
    private fun isInRightArea(e: MotionEvent): Boolean { 
     val r = Rect() 
     getGlobalVisibleRect(r) 
     r.left = paddingLeft 
     r.top = r.top + paddingTop 
     return !r.contains(e.rawX.toInt(), e.rawY.toInt()) 
    } 

} 

結果:

enter image description here

+1

魅力的に動作します。 –

+0

Javaコードを共有してください – Tariqul

-1

ここでは、(@azizbekianで答え)に変換するJavaコードです。

public final class MyRecyclerView extends RecyclerView { 
private boolean isValid; 
private int x; 
private int y; 
private final int delta; 

public boolean onTouchEvent(@Nullable MotionEvent e) { 
    boolean onTouchEvent = super.onTouchEvent(e); 
    Integer var3 = e != null?Integer.valueOf(e.getAction()):null; 
    boolean var4 = false; 
    if(var3 != null) { 
    if(var3.intValue() == 0) { 
     this.x = (int)e.getRawX(); 
     this.y = (int)e.getRawY(); 
     this.isValid = true; 
     return onTouchEvent; 
    } 
    } 

    byte var5 = 2; 
    if(var3 != null) { 
    if(var3.intValue() == var5) { 
     if(Math.abs(e.getRawX() - (float)this.x) > (float)this.delta || Math.abs(e.getRawY() - (float)this.y) > (float)this.delta) { 
      this.isValid = false; 
     } 

     return onTouchEvent; 
    } 
    } 

    var5 = 1; 
    if(var3 != null) { 
    if(var3.intValue() == var5 && this.isValid && Math.abs(e.getRawX() - (float)this.x) < (float)this.delta && Math.abs(e.getRawY() - (float)this.y) < (float)this.delta && this.isInRightArea(e)) { 
     this.performClick(); 
    } 
    } 

    return onTouchEvent; 
} 

private final boolean isInRightArea(MotionEvent e) { 
    Rect r = new Rect(); 
    this.getGlobalVisibleRect(r); 
    r.left = this.getPaddingLeft(); 
    r.top += this.getPaddingTop(); 
    return !r.contains((int)e.getRawX(), (int)e.getRawY()); 
} 

@JvmOverloads 
public MyRecyclerView(@NotNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 
    Intrinsics.checkParameterIsNotNull(context, "context"); 
    super(context, attrs, defStyleAttr); 
    ViewConfiguration var10001 = ViewConfiguration.get(this.getContext()); 
    Intrinsics.checkExpressionValueIsNotNull(var10001, "ViewConfiguration.get(getContext())"); 
    this.delta = var10001.getScaledTouchSlop(); 
} 

// $FF: synthetic method 
@JvmOverloads 
public MyRecyclerView(Context var1, AttributeSet var2, int var3, int var4, DefaultConstructorMarker var5) { 
    if((var4 & 2) != 0) { 
    var2 = (AttributeSet)null; 
    } 

    if((var4 & 4) != 0) { 
    var3 = 0; 
    } 

    this(var1, var2, var3); 
} 

@JvmOverloads 
public MyRecyclerView(@NotNull Context context, @Nullable AttributeSet attrs) { 
    this(context, attrs, 0, 4, (DefaultConstructorMarker)null); 
} 

@JvmOverloads 
public MyRecyclerView(@NotNull Context context) { 
    this(context, (AttributeSet)null, 0, 6, (DefaultConstructorMarker)null); 
} 
} 

これは、あなたがJavaへKotlinコードを変換することができる方法である - のAndroid Studioで開きKotlinファイルを、その後、ツール - > Kotlin->ショーKotlinバイトコードは、変換されたJavaコードをコピーして、逆コンパイルボタンを押してください。

関連する問題