package com.ponyvillelive.pvlmobile.ui;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import com.ponyvillelive.pvlmobile.R;
import com.ponyvillelive.pvlmobile.model.Station;
import butterknife.ButterKnife;
import butterknife.InjectView;
/**
* A fragment representing a list of Items.
* <p>
* Large screen devices (such as tablets) are supported by replacing the ListView
* with a GridView.
* <p>
*/
public class StationFragment extends Fragment {
private static final String ARG_TYPE = "type";
@InjectView(android.R.id.list)
RecyclerView listView;
// @InjectView(android.R.id.empty)
// ImageView emptyView;
private String stationType;
private StationFragmentListener listener;
private StationAdapter adapter;
private RecyclerView.LayoutManager layoutManager;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public StationFragment() {
}
/**
* A basic {@link android.support.v4.app.Fragment} containing a {@link android.widget.AbsListView}
* of {@link com.ponyvillelive.pvlmobile.model.Station}s
*
* @param stationType {@link com.ponyvillelive.pvlmobile.model.Station#STATION_TYPE_AUDIO}
* or {@link com.ponyvillelive.pvlmobile.model.Station#STATION_TYPE_VIDEO}
* @return A new {@link com.ponyvillelive.pvlmobile.ui.StationFragment} instance
*/
public static StationFragment newInstance(String stationType) {
StationFragment fragment = new StationFragment();
Bundle args = new Bundle();
args.putString(ARG_TYPE, stationType);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
this.stationType = getArguments().getString(ARG_TYPE, "audio");
}
adapter = new StationAdapter(getLayoutInflater(savedInstanceState), this.stationType);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_station, container, false);
ButterKnife.inject(this, view);
layoutManager = new LinearLayoutManager(getActivity());
// Set the adapter
listView.setAdapter(adapter);
listView.setLayoutManager(layoutManager);
listView.setHasFixedSize(true);
listView.addOnItemTouchListener(new StationListTouchListener());
// final ItemClickSupport itemClickSupport = ItemClickSupport.addTo(listView);
// itemClickSupport.setOnItemClickListener((parent, child, position, id) -> {
// listener.handleStationSelected(adapter.getItem(position));
// });
return view;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (!(activity instanceof StationFragmentListener)) {
throw new RuntimeException("Activities must implement StationFragmentListener");
} else {
listener = (StationFragmentListener) activity;
}
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
/**
* The interaction contract that all {@link android.app.Activity}s embedding a
* {@link com.ponyvillelive.pvlmobile.ui.StationFragment} must implement
*/
public interface StationFragmentListener {
/**
* Handle a station being selected inside of the {@link com.ponyvillelive.pvlmobile.ui.StationFragment}
*
* @param station The {@link com.ponyvillelive.pvlmobile.model.Station} that was selected
*/
public boolean handleStationSelected(Station station);
}
/*
*============================================================================
* The following is lovingly borrowed from Lucas Roca's excellent TwoWay-View:
* https://github.com/lucasr/twoway-view
*============================================================================
*/
private final class StationListTouchListener implements RecyclerView.OnItemTouchListener {
private final GestureDetectorCompat gestureDetector;
StationListTouchListener() {
gestureDetector = new GestureDetectorCompat(listView.getContext(), new StationListGestureListener());
}
private boolean isAttachedToWindow(RecyclerView hostView) {
if (Build.VERSION.SDK_INT >= 19) {
return hostView.isAttachedToWindow();
} else {
return (hostView.getHandler() != null);
}
}
private boolean hasAdapter(RecyclerView hostView) {
return (hostView.getAdapter() != null);
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
if(isAttachedToWindow(rv) && hasAdapter(rv)) {
gestureDetector.onTouchEvent(e);
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
// This is a noop, since our gesture detector actually handles
// the event. We just use this class to snoop :)
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
// Also a noop
}
}
private final class StationListGestureListener extends GestureDetector.SimpleOnGestureListener {
private View touchTarget;
private boolean btnTouched;
public void handleTap(MotionEvent e) {
if(touchTarget != null) {
onSingleTapUp(e);
}
}
@Override
public boolean onDown(MotionEvent e) {
final int x = (int) e.getX();
final int y = (int) e.getY();
touchTarget = listView.findChildViewUnder(x, y);
if(touchTarget == null) {
btnTouched = false;
} else {
View btn = touchTarget.findViewById(R.id.station_menu);
Rect hitRect = new Rect();
btn.getHitRect(hitRect);
btnTouched = hitRect.contains(x, y);
}
return touchTarget != null && !btnTouched;
}
@Override
public void onShowPress(MotionEvent e) {
if(touchTarget != null) {
touchTarget.setPressed(true);
}
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
boolean handled = false;
if(btnTouched) {
return false;
}
if(touchTarget != null) {
touchTarget.setPressed(false);
int pos = listView.getChildPosition(touchTarget);
handled = listener.handleStationSelected(adapter.getItem(pos));
touchTarget = null;
}
return handled;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if(touchTarget != null) {
touchTarget.setPressed(false);
touchTarget = null;
return true;
}
return false;
}
}
}