show code block

2016年12月21日 星期三

Fragment當Activity使用,在Fragment上設置Button

前言:

許多人會覺得,奇怪我不是已經呼叫(findViewById)了嗎?怎麼我在fragment上的按鈕都完全無效?

其實都忽略了rootView這件事情。
fragment來說必須有底部View,才有辦法呼叫元件做事!




實作:
一開始創建一個Fragment,這會是你FragmentonCreateView

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_blank, container, false);
}
之後把returnView額外拉到全域變數來
private View view;
View就會是你的rootView了,這時候在fragment上面設置元件才會有效果。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.fragment_blank, container, false);
    return view;
}

開始控制元件囉。
在平時的findViewById前面加上rootview
Button yourButton=(Button)rootview.findViewById(R.id.button_fragment);

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.fragment_blank, container, false);
    button = (Button) view.findViewById(R.id.button_fragment);
    imageView = (ImageView) view.findViewById(R.id.show);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            imageView.setImageResource(R.drawable.hello);
        }
    });
    return view;
}
以下是專案所有CODE範例

MainActivity.xml


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/hello"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="hello"
        android:text="Call Fragment" />
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/hello" />
</RelativeLayout>
MainActivity.Java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void hello(View view) {
        //最簡易創建fragment的方式
        //不建議這樣做,因為初始化(init) fragment的方式被簡略(new BlankFragment())
        //會造成在控制fragment上的麻煩
        //創建方式詳情請見
        //http://nikeru8.blogspot.tw/2016/06/fragment-activity-fragment-activity.html
        getFragmentManager()
                .beginTransaction()
                .add(R.id.container, new BlankFragment())
                .commit();
    }
}
example_fragment.xml  創建的Fragment

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/darker_gray"
    android:clickable="true"
    tools:context="com.example.a015865.simplefragment.simpleExample">
    //android:clickable="true"防止點擊穿透
    <Button
        android:id="@+id/button_fragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Call ImageView" />
    <ImageView
        android:id="@+id/show"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>
simpleExample.java

public class simpleExample extends android.app.Fragment {
    private View view;
    private ImageView imageView;
    private Button button;
    public simpleExample() {
        // Required empty public constructor
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.example_fragment, container, false);
        button = (Button) view.findViewById(R.id.button_fragment);
        imageView = (ImageView) view.findViewById(R.id.show);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                imageView.setImageResource(R.drawable.hello);
            }
        });
        return view;
    }
}

Demo打包:







可能會遇到的問題:

當你創建了Fragment,在Activity呼叫它的時候發現跑紅字了?!


此時要注意你創建的Fragment繼承問題。


必須繼承android.app.Fragment
當然你只要在import的地方使用import android.app.Fragment;
就可以直接extends Fragment

不用extends android.app.Fragment那麼醜!






Fragment全集

Fragment的使用() ─ activity內放置Fragment

Fragment的使用() ─ activity內切換Fragment

Fragment 返回上一頁 OnBackPressed

Fragment點擊穿透

FragmentActivity使用,在Fragment上設置Button - 此篇


Fragment點擊穿透問題

Fragment點擊穿透問題



前言:
一言蔽之,發現很多人都有這問題。
之前會穿透真的是bug,後來的版本fragment已經做出相對應的修正。









實作:
主要程式碼
android:clickable="true"



在每個fragment布局內,偷加上這行。
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
xmlns:tools="http://schemas.android.com/tools"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
tools:context="com.stanley.a015865.image.AboutStanley"
   
android:clickable="true"
   
>










這篇就短短的,有問題留言囉!




Fragment全集

Fragment的使用() ─ activity內放置Fragment

Fragment的使用() ─ activity內切換Fragment

Fragment 返回上一頁 OnBackPressed

Fragment
點擊穿透

2016年12月20日 星期二

Fragment 返回上一頁 - OnBackPressed

Fragment 返回上一頁 - OnBackPressed

前言:
Fragment由於不繼承Activity,他無法使用到OnBackPressed這個方法。



@Override
public void onBackPressed() {

}
P.S.  OnBackPressed就是手機上內建的上一頁按鈕。



這也是為什麼我個人非常不喜歡用Fragment的原因,新手也實在不推薦使用。以我來說唯一的使用時機大概是ViewPager 的分頁模式,單純拿來跑圖用的。最單純,最不會有問題。

ViewPager分頁

返回鈕有個最單純的方法在之前的網誌介紹過了,這邊就不贅述,但那方法只能「指定」你要回到哪一頁,並不能做到真正的返回上一頁的效果。








實作:
 @Override
public void onBackPressed() {

    int count = getFragmentManager().getBackStackEntryCount();

    if (count == 0) {
        super.onBackPressed();
        //additional code
    } else {
        getFragmentManager().popBackStack();
    }
}

/**
*count 就是你開Fragment的分頁數量
*/


Fragment一定是依附著Activity生存的,這個OnBackPressed請寫在Activity內。


END






就不提供Demo了,有問題請留言。

Fragment全集

Fragment的使用() ─ activity內放置Fragment

Fragment的使用() ─ activity內切換Fragment

Fragment 返回上一頁 OnBackPressed

Fragment
點擊穿透




2016年12月19日 星期一

取消靜態廣播(static BroadcastReceiver)的方法


取消靜態廣播(static BroadcastReceiver)的方法


前言:

靜態廣播(static broadcastReceiver)的延伸:
http://nikeru8.blogspot.tw/2016/12/broadcastreceiver.html

取消靜態廣播真的搞了蠻久的,很多文章都說無法取消註冊靜態方法的廣播,其實是錯的,
是可以取消的。


在註冊靜態廣播後,因為沒辦法使用unregisterReceiver的方法取消註冊,我查了蠻多資料的終於找到解。




ComponentName component = new ComponentName(context, MyReceiver.class);
int status = context.getPackageManager().getComponentEnabledSetting(component);
/**
*用來創建 component ,伸手進去manifest.xml的功能
*/


//設置 (允許廣播)
getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);

//取消設置 (取消廣播)
getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);

/**
*component 設置目標位置,package
*PackageManager.COMPONENT_ENABLED_STATE_ENABLED enabled可讀取 disabled不可讀取
*PackageManager.DONT_KILL_APP 告訴這方法執行後別停止運行app
**/








如何判斷是否已經取消註冊或是成功註冊了?


//判斷成功與否
       if (status == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
                  Log.d("fsa", "receiver is enabled");//成功註冊狀態中
              } else if (status == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
                  Log.d("fsa", "receiver is disabled");//取消註冊狀態中
              }







2016年12月18日 星期日

Android元件:時間選擇器TimePickerDialog

時間選擇器TimePickerDialog





一切的出發點,主要程式碼:

private TimePickerDialog timePickerDialog;


timePickerDialog=new TimePickerDialog(this,onTimeSetListener,hours,mins,false);
timePickerDialog.show(); //調用


/**
*this  運行指定Activity
*onTimeSetListener 重製時間監聽、用戶選好時間後的監聽
*hours 設置初始hours 未選擇/初始 前的小時
*mins  未選擇/初始 前的分鐘
*false 鬧鐘顯示方式(true為上下午制、false為24小時制)
*/






實作:

*onTimeSetListener 重製時間監聽、用戶選好時間後的監聽

   onTimeSetListener = new TimePickerDialog.OnTimeSetListener() {

           @RequiresApi(api = Build.VERSION_CODES.N)
           @Override
           public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
               DecimalFormat decimalFormat = new DecimalFormat("00");
               textview.setText(decimalFormat.format(hourOfDay) + ":" + decimalFormat.format(minute));
           }
       };
/**
* DecimalFormat 數字格式轉換的方法,我們用到裡面的format 避免倒數到10秒內時(12:09),產生12:9 這種情況
*/


*hours 設置初始hours 未選擇/初始 前的小時
*mins  未選擇/初始 前的分鐘

final Calendar calendar = Calendar.getInstance();
               int hour = calendar.get(Calendar.HOUR_OF_DAY);
               int minute = calendar.get(Calendar.MINUTE);


*false 鬧鐘顯示方式(true為上下午制、false為24小時制)










簡單三步驟END!



全部參考程式碼:


MainActivity.xml


<code>
<?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"
   tools:context="com.example.a015865.timepicker.MainActivity">
<TextView
    android:id="@+id/hello"
    android:layout_width="wrap_content"
       android:layout_height="wrap_content"
    android:text="Hello World!" />
<Button
    android:onClick="picker"
    android:id="@+id/picker"
       android:layout_width="wrap_content"
    android:layout_height="wrap_content"
       android:layout_below="@id/hello"
    android:text="Picker" />
<Button
    android:onClick="pickertwo"
    android:id="@+id/pickertwo"
       android:layout_width="wrap_content"
    android:layout_height="wrap_content"
       android:layout_below="@id/picker"
    android:text="Pickertwo" />
</RelativeLayout></code>


MainActivity.Java


public class MainActivity extends AppCompatActivity {

   private TimePickerDialog timePickerDialog;
   private TimePickerDialog.OnTimeSetListener onTimeSetListener;
   private TextView textview;
   Calendar calendar;
   int hour;
   int minute;

   @RequiresApi(api = Build.VERSION_CODES.N)
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       textview = (TextView) findViewById(R.id.hello);
       calendar = Calendar.getInstance();
       hour = calendar.get(Calendar.HOUR_OF_DAY);
       minute = calendar.get(Calendar.MINUTE);
       onTimeSetListener = new TimePickerDialog.OnTimeSetListener() {


           @RequiresApi(api = Build.VERSION_CODES.N)
           @Override
           public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
               DecimalFormat decimalFormat = new DecimalFormat("00");
               textview.setText(decimalFormat.format(hourOfDay) + ":" + decimalFormat.format(minute));
           }
       };

   }



   public void picker(View view) {
       timePickerDialog = new TimePickerDialog(this, onTimeSetListener, hour,minute, true);
       timePickerDialog.show();
   }


   public void pickertwo(View view) {
       timePickerDialog = new TimePickerDialog(this, onTimeSetListener, hour,minute, false);
       timePickerDialog.show();
   }
}


完成囉!

協程(coroutine) - 協程為什麼要學它?

 Coroutine 協程 再強調一次 協程就是由kotlin官方所提供的線程api //Thread Thread { }.start() //Executor val execu...