【android】Fragment上のListViewに置かれたボタンのonClickを処理する
はじめに
今回やりたかったのは、ListViewのセル上に削除ボタンとかをおいてクリックされたらListViewから削除するようなこと。
ListViewを作るのがActivityとFragmentとでやり方が違うみたい。
Activityの場合は以下みたいな形でボタンのイベントが取得できる。
<Button ・・・ android:id="@+id/myButton" android:onClick="myFunc" />
Adapter
public View getView(final int position, View convertView, ViewGroup parent) { ・・・ Button myButton = (Button)convertView.findViewById(R.id.myButton); myButton.setTag(position); ・・・ }
Activity
public void myFunc(View view) { // ListView上のボタンがおされたら呼ばれる // view.getTag()でどの行が押されたかわかる }
けど、Fragmentを使ってる場合はFragmentを呼び出してるActivityで実装されているmyFuncが呼ばれるためやりたいこととは違った。
Fragmentの場合
xmlのButtonにonClick属性はセットしない。
やり方わからなかったので、アダプターにインターフェースを定義して呼び出し元(Fragment)にメソッドを実装させる形で実装してみた。
<Button ・・・ android:id="@+id/myButton" />
Adapter
public class MyAdapter extends ArrayAdapter<MyData> { private MyAdapterListener listener; public interface MyAdapterListener { void myFunc(Object position); } public void setListener(MyAdapterListener listener) { this.listener = listener; } ・・・ @Override public View getView(final int position, View convertView, ViewGroup parent) { ・・・ Button myButton = (Button)convertView.findViewById(R.id.myButton); myButton.setTag(position); myButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listener.myFunc(v.getTag()); } }); return convertView; } }
Fragment
public class MyFragment extends Fragment implements MyAdapter.MyAdapterListener { ・・・ @Override public void onCreate(Bundle savedInstanceState) { ・・・ // アダプターで用意したsetListnerメソッドで関連づける mAdapter = new MyAdapter(getContext(), 0, ・・・); mAdapter.setListener(this); } public void myFunc(Object position) { // 呼ばれた!! } }
もっといいやり方ありそうだけど。。以上です
【android】ListViewひな型
試したりするときにとりあえずListView作ることが多いのでコピペ用にメモ
MainActivity.java
public class MainActivity extends AppCompatActivity { private ArrayList<Item> mItems; private ItemAdapter mAdapter; private ListView mListView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mItems = new ArrayList<>(); mItems.clear(); mAdapter = new ItemAdapter(this, 0, mItems); ListView listView = (ListView)findViewById(R.id.list_view); listView.setAdapter(mAdapter); setData(); } private void setData() { for (int i = 0; i < 10; i++) { Item item = new Item(); item.setTitle("タイトル " + String.valueOf(i+1)); mItems.add(item); } } } class Item { private String title; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } } class ItemAdapter extends ArrayAdapter<Item> { private LayoutInflater layoutInflater; public ItemAdapter(Context c, int id, ArrayList<Item> data) { super(c, id, data); this.layoutInflater = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View getView(final int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = layoutInflater.inflate(R.layout.list_item,parent,false); } Item data = getItem(position); TextView title = (TextView)convertView.findViewById(R.id.title); title.setText(data.getTitle()); return convertView; } }
main_activity.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"> <ListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent"></ListView> </RelativeLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="5sp" android:paddingTop="25sp" android:paddingBottom="15sp" android:textSize="24sp"/> </LinearLayout> ||<
【android】ViewPagerでタブ毎に戻れる画面を実装する方法
はじめに
今回やりたかったのはこんな画面。
なんでもiOSと比較するのはあれだけど、iOSだとUiNavigationControllerを持つUITabbarControllerみたいなイメージ。
今回はタブは表示していないけどViewPagerをタブ表示するサンプルはたくさんあるので問題なかった。
戻るボタンでの戻り先をタブごとに保持しているようなイメージ。
クラス構成としてはこんなイメージ。
Activityは1つでタブごとにRootFragmentを持たせて、実際に画面に表示するフラグメントを操作するイメージ(ここではFirstFragmentとSecondFragment)。
実装
MainActivityの実装
ここでやることはViewPagerとRootFragmentを紐づける処理。
あとは戻るボタンされた時に選択中のタブのバックスタックから1つ取り出して戻す処理。
戻るボタンされたときに選択中のタブがわかるようにタブ選択されるたびに選択中のタブ番号を保持する。
MainActivity.java
public class MainActivity extends AppCompatActivity { private ViewPager mPager; private String[] mTitles = {"タブ1", "タブ2"}; // 選択中のタブ番号を保持 private int selected; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setTitle("タブ1"); mPager = (ViewPager)findViewById(R.id.viewpager); mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int position) { selected = position; setTitle(mTitles[position]); } ・・・ }); FragmentPagerAdapter adapter = new FragmentPagerAdapter(getSupportFragmentManager()) { @Override public Fragment getItem(int position) { return RootFragment.newInstance(mTags[position]); } @Override public int getCount() { return 2; } ・・・ }; mPager.setAdapter(adapter); } // 戻るボタン @Override public void onBackPressed() { // 選択中のタブのRootFragmentにバックスタックがあれば戻る処理 FragmentManager fm = getSupportFragmentManager(); List<Fragment> fragments = fm.getFragments(); Fragment fragment = fragments.get(selected); FragmentManager fragmentManager = fragment.getChildFragmentManager(); if (0 < fragmentManager.getBackStackEntryCount()) { fragmentManager.popBackStack(); } } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" ・・・ /> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:background="@android:color/white" /> </RelativeLayout>
RootFragmentの実装
ここではFirstFragmentを表示するだけ。それならRootFragmentなんて不要と思って最初実装していた。
けど、ViewPagerの中のFragmentをreplaceしても中身がレイアウトの表示が変わらない問題に直面。で
http://www.pineappslab.com/post/fragments-viewpager/
ここの記事を発見。ここの通りにやらせていただきました。
RootFragment.java
public class RootFragment extends Fragment { public static RootFragment newInstance() { RootFragment fragment = new RootFragment(); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_root, container, false); FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction(); fragmentTransaction.replace(R.id.root_frame, FirstFragment.newInstance()); fragmentTransaction.commit(); return view; } }
fragment_root.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root_frame" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout>
FirstFragmentの実装
FirstFragment.java
public class FirstFragment extends Fragment { public static FirstFragment newInstance(String tag) { FirstFragment fragment = new FirstFragment(); Bundle args = new Bundle(); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_first, container, false); Button button = (Button) view.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { FragmentTransaction fragmentTransaction = getParentFragment().getChildFragmentManager().beginTransaction(); fragmentTransaction.replace(R.id.root_frame, SecondFragment.newInstance()); fragmentTransaction.addToBackStack(); fragmentTransaction.commit(); } }); return view; } }
fragment_first.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10sp" android:text="FirstFragment" android:textSize="30sp"/> <Button android:id="@+id/button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#ffff00" android:text="次へ" android:textSize="18sp"/> </LinearLayout>
SecondFragmentは画面表示するだけだからいいかな。。。
おわりに
よくわからないで調べながらやってたからこの画面実装するポイントは他にもけっこうあるはずなんだけど出てこない。。。
もうちょっと内容を分割して整理した方が良さそう。以上です
はてなブログ(はてな記法)で画像を横並びにする方法メモ
なにげに時間かかったのでメモしておく。
ちなみに自分は、はてな記法モードっていうのを使ってる。
手順は以下だった
・アップロードした画像のURLを取得
・tableタグとimgタグ使って整形
やりたかった画面 |
アップロードした画像のURLを取得
アップロードした画像ははてなフォトにあるのでここから取得できる。
1. マイフォトを開く
2.Hatena Blogフォルダを開く
3. フォルダ編集を開く
4. 画像を選択してブログを貼り付けるをクリックするとurlを取得できる
tableタグとimgタグ使って整形
あとはtableタグとimgでスタイルシートも使えるのでこんなかんじで。
<table style="border-style: none;" border="1"><tr> <td style="border-style: none;"> <img src="画像のURL" height="150"> </td> <td style="border-style: none;"> <img src="画像のURL" height="150" /> </td> </table>
以上です
【css】imgやvideoをアスペクト比を保ちつつ画面一杯に表示する
はじめに
機会ないかもしれないけど次やるときのためのメモ。
やりたいのはスマホでこんな感じの画面。画像でも動画でも同じcssで。
横画像
portrait |
landscape |
縦画像
portrait |
landscape |
実装
htmlはどちらの動画も共通で、cssは横長と縦長とでそれぞれ用意する。
html
<div id="wrapper"> <img src="/path/to/file" /> </div>
320x180(横長)のcss
body { margin:0; } #wrapper { position:relative; width: 100%; height:100%; background-color:black; } #wrapper > img { width: 100%; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; }
400x625(縦長)のcss
body { margin:0; } #wrapper { height: 100%; text-align:center; background-color:black; } #wrapper > * { height: 100%; }
以上です
【android】apiへリクエストしてcallbackを実装する方法メモ
はじめに
android調べながらやってるけどJavaの基礎もあんまないから時間かかる。
今回やりたいのはapiたたいてレスポンスによって成功用と失敗用のcallbackを実行するようなこと。
調べたり質問しながらやってるけどinterface使うといいらしい。
実装1
呼び出し側に成功時と失敗時のコールバック用インターフェスを実装させる。
すっきりしてる気もするけど、コールバックを必ず実装させなければならないのがちょっと嫌かも。
ApiManager.java(呼ばれる側)
public class ApiManager { public interface ApiManagerCallback { public void success(Object obj); public void failed(Object obj); } private ApiManagerCallback apiManagerCallback; public void setCallbacks(ApiManagerCallback apiManagerCallback) { this.apiManagerCallback = apiManagerCallback; } public void callApi() { try { apiManagerCallback.success("success"); } catch (Exception e) { apiManagerCallback.failed("failed"); } } }
MainActivity.java(呼び出す側)
public class MainActivity extends AppCompatActivity implements ApiManager.ApiManagerCallback { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ApiManager apiManager = new ApiManager(); apiManager.setCallbacks(this); apiManager.callApi(); } public void success(Object obj) { // 成功 } public void failed(Object obj) { // 失敗 } }
実装2
実装1より呼び出す側のコードが少し見辛い気もするけど、失敗時のコールバックが必須でないのがいいかも。
ApiManager.java(呼ばれる側)
public class ApiManager { public interface ApiManagerCallback { void call(Object obj); } void connect(final ApiManagerCallback success, final ApiManagerCallback failed) { try { success.call("success!!"); } catch (Exception e) { if (failed != null) { failed.call("failed"); } } } }
MainActivity.java(呼び出す側)
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ApiManager apiManager = new ApiManager(); apiManager.connect(new ApiManager.ApiManagerCallback() { @Override public void call(Object obj) { // 成功 } }, new ApiManager.ApiManagerCallback() { @Override public void call(Object obj) { // 失敗 } }); } }
きっともっといい書き方あるんだろうけど、自分の頭ではこんなものかな。難しい。。。もっといい書き方教えてください。以上です
石の上にも3年
初めて正社員として就職した会社を辞めると伝えたときに上司に言われた言葉。
何があっても3年は続けろって意味だと思うけど当時自分は1年半でその会社を辞めた。
その後あまり長続きすることもなく職場を転々としてきた気がする。適当な理由で退職したが本音は以下だったと記憶している。
1. 家庭の事情 〜1年半在籍(100人規模のSES事業)
2. 会社の新体制が嫌だった 〜5年在籍(70人規模の受託開発会社)
3. 社長が怖すぎた 〜3ヶ月在籍(3人規模の何か)
4. より技術を高められそうな環境で働きたかった 〜2年在籍(20人規模のCP)
今思うと自分の対応次第で辞める必要なかったと思えるものがいくつかある。
結局自分の言いたいことを言わずに勝手にイライラして何も言わずにやめるってパターンが1番もったいなかった気がする。
1と3は今考えても仕方ない。2と4は他にも選択肢があったと思う。
何も言わないことで丸く納めていたつもりでも、それがつもって辞めたら会社にとっては1番不利益。結局コミュニケーション能力ってそこなのかな。。。以上です