ActionBar-PullToRefreshをメニューボタン等で連動させる
っていうActionBar-PullToRefreshを使っている場合において、メニューでリフレッシュボタンとかでActionBar-PullToRefreshを発生させるような要件を実現したい場合にはどうすれば良いのか。簡単に言えば上記画像中の右上にあるリフレッシュボタンをクリックする事でonRefreshStartedメソッドを発生させたいっていう所
っていうのをやってみた
SampleListFragment.java
package sample.test;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import com.actionbarsherlock.app.SherlockListFragment;
import uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.PullToRefreshLayout;
import uk.co.senab.actionbarpulltorefresh.library.ActionBarPullToRefresh;
import uk.co.senab.actionbarpulltorefresh.library.listeners.OnRefreshListener;
public class SampleListFragment extends SherlockListFragment
implements OnRefreshListener {
private static final String TAG = SampleListFragment.class.getName();
private final Handler mHandler = new Handler();
private ArrayAdapter<String> mAdapter;
private PullToRefreshLayout mPullToRefreshLayout;
@Override
public void onActivityCreated(Bundle bundle) {
super.onActivityCreated(bundle);
Log.v(TAG, "onActivityCreated");
counter++;
mAdapter = new ArrayAdapter<String>(
getActivity(),
android.R.layout.simple_list_item_1
);
setListAdapter(mAdapter);
}
@Override
public void onViewCreated(View view, Bundle bundle) {
super.onViewCreated(view, bundle);
Log.v(TAG, "onViewCreated");
mPullToRefreshLayout = new PullToRefreshLayout(view.getContext());
ActionBarPullToRefresh.from(getActivity())
.insertLayoutInto((ViewGroup) view)
.theseChildrenArePullable(getListView(), getListView().getEmptyView())
.listener(this)
.setup(mPullToRefreshLayout);
}
@Override
public void onRefreshStarted(View view) {
Log.v(TAG, "onRefreshStarted: " + view);
mHandler.postDelayed(
new Thread() {
@Override
public void run() {
if (mPullToRefreshLayout.isRefreshing())
mPullToRefreshLayout.setRefreshComplete();
}
},
5000
);
}
// PullToRefreshLayoutを取得できるようにメソッド追加
PullToRefreshLayout getPullToRefresh() {
return mPullToRefreshLayout;
}
}
MainActivity.java
恐らくは現状だとActionBar-PullToRefreshのリロード処理を促せるようなAPIが無い(てか見つけられなかった)。正確にはあるんだけれどもパブリックでは無い、なのでリフレクションという力技を使ってPullToRefreshAttacher?のstartRefreshメソッドを実行すれば良い模様
package sample.test;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.View;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher;
import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout;
public class MainActivity extends SherlockFragmentActivity {
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.menu_refresh) {
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentByTag(
// R.string.sample_list_fragment_tagは"sample_list_fragment"
// <fragment android:tag="@string/sample_list_fragment_tag">が必要
getString(R.string.sample_list_fragment_tag)
);
if (fragment instanceof SampleListFragment)
startRefresh((SampleListFragment)fragment);
}
return super.onOptionsItemSelected(item);
}
private void startRefresh(SampleListFragment fragment) {
PullToRefreshLayout pullToRefreshLayout = fragment.getPullToRefresh();
try {
Field f = PullToRefreshLayout.class.getDeclaredField("mPullToRefreshAttacher");
f.setAccessible(true);
PullToRefreshAttacher attacher = (PullToRefreshAttacher)f.get(pullToRefreshLayout);
Method m = PullToRefreshAttacher.class.getDeclaredMethod("startRefresh", View.class, boolean.class);
m.setAccessible(true);
m.invoke(attacher, new Object[] { fragment.getListView(), true });
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
てな感じでPullToRefreshLayoutなインスタンスからPullToRefreshAttacherなインスタンスを取って、そのプライベートメソッド?なstartRefreshメソッドをリフレクションを使ってコールするっていうただそれだけ
但し、onRefreshStartedメソッドの引数に指定されるandroid.view.ViewのインスタンスはListFragmentを使っているのであればListViewになる模様。ListFragmentを使うケースであればそうだと思うけど、そうじゃないケースには別のView実装が指定されるので(ry
検証動画
{% youtube nn89-8Lpoqo %}