小伍

小伍 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

小伍 发布了文章 · 10月25日

Android 开发入门-详解4种基本布局

3.3.1 线性布局 LinearLayout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    ...>

使用 android:orientation 属性指定排列方向:

  • vertical 垂直排列
  • horizontal 水平排列,默认
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 1"
        />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 2"
        />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 3"
        />
</LinearLayout>

使用 android:layout_gravity 指定控件在布局的对齐方式:

  • top 顶部对齐
  • center_vertical 垂直居中
  • bottom 底部对齐
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"                   # 指定为水平布局
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top"                   # 指定为顶部对齐
        android:text="Button 1"
        />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"       # 指定为垂直居中
        android:text="Button 2"
        />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"                # 指定为底部对齐
        android:text="Button 3"
        />

使用 android:layout_weight 以比例方式指定控件在布局的大小:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/input"
        android:layout_width="0dp"                      #将width指定为0dp
        android:layout_height="wrap_content"
        android:layout_weight="3"                       #水平方向宽度占比
        android:hint="Type something"
        />

    <Button
        android:id="@+id/send"
        android:layout_width="0dp"                      #将width指定为0dp
        android:layout_height="wrap_content"
        android:layout_weight="2"                       #水平方向宽度占比
        android:text="Send"
        />

width 和 weight 组合使用:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/input"
        android:layout_width="0dp"                      #将width指定为0dp
        android:layout_height="wrap_content"
        android:layout_weight="1"                       #水平方向宽度占比其余空间
        android:hint="Type something"
        />

    <Button
        android:id="@+id/send"
        android:layout_width="wrap_content"             #水平方向适配控件宽度
        android:layout_height="wrap_content"
        android:text="Send"
        />

3.3.2 相对布局 RelativeLayout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    # 左上角对齐
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="button1"
        />

    # 右上角对齐
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:text="button2"
        />
        
    # 居中对齐
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="button3"
        />
        
    # 左下角对齐
    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:text="button4"
        />
        
    # 右下角对齐
    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:text="button5"
        />
</RelativeLayout>

相对控件进行定位布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    # 居中对齐
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="button3"
        />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/button3"                   #位于button3上方
        android:layout_toLeftOf="@id/button3"                #位于button3左侧
        android:text="button1"
        />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/button3"                   #位于button3上方
        android:layout_toRightOf="@id/button3"               #位于button3右侧
        android:text="button2"
        />
        
    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/button3"                   #位于button3下方
        android:layout_toLeftOf="@id/button3"                #位于button3左侧
        android:text="button4"
        />
        
    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/button3"                   #位于button3下方
        android:layout_toRightOf="@id/button3"               #位于button3右侧
        android:text="button5"
        />
</RelativeLayout>

其他相对于控件进行定位的属性:

  • android:layout_alignLeft="@id/button3" 与button3左对齐
  • android:layout_alignRight="@id/button3" 与button3右对齐
  • android:layout_alignTop="@id/button3" 与button3上对齐
  • android:layout_alignBottom="@id/button3" 与button3下对齐

3.3.3 帧布局 FrameLayout

默认情况下控件重叠显示:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"          #控件宽度
        android:layout_height="wrap_content"         #控件高度
        android:text="This is TextView" />
    
    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:data-original="@mipmap/ic_launcher"
        />
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"          #控件宽度
        android:layout_height="wrap_content"         #控件高度
        android:layout_gravity="left"                #控件左对齐
        android:text="This is TextView" />
    
    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"          #控件宽度
        android:layout_height="wrap_content"         #控件高度
        android:layout_gravity="right"               #控件右对齐
        android:data-original="@mipmap/ic_launcher"
        />
</FrameLayout>

3.3.4 百分比布局 PercentFrameLayout

LinearLayout 本身支持按比例指定控件大小,因此百分比布局只为 FrameLayout 和 RelativeLayout 进行了功能扩展。

# app/build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.android.support:percent:24.2.1'        #引入依赖
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentFrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button1"
        android:text="Button 1"
        android:layout_gravity="left|top"   # 指定位置在左上角
        app:layout_widthPercent="50%"       # 指定宽度百分比
        app:layout_heightPercent="50%"      # 指定高度百分比
        />

    <Button
        android:id="@+id/button2"
        android:text="Button 2"
        android:layout_gravity="right|top"
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        />

    <Button
        android:id="@+id/button3"
        android:text="Button 3"
        android:layout_gravity="left|bottom"
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        />

    <Button
        android:id="@+id/button4"
        android:text="Button 4"
        android:layout_gravity="right|bottom"
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        />

</android.support.percent.PercentFrameLayout>
查看原文

赞 0 收藏 0 评论 0

小伍 发布了文章 · 10月18日

Android 开发入门-常用控件的使用方法

3.2.1 TextView

<?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/text_view"
        android:layout_width="match_parent"          #控件宽度
        android:layout_height="wrap_content"         #控件高度
        android:gravity="center"                     #内容对齐方式
        android:textSize="24sp"                      #字体大小,单位sp
        android:textColor="#00ff00"                  #字体颜色
        android:text="This is TextView" />           #显示的内容

layout_width 和 wrap_content 的可选值:

  • match_parent 指定控件大小与父布局一样。
  • wrap_content 指定控件大小由控件内容决定。

gravity的可选值:

  • top 顶部对齐
  • bottom 底部对齐
  • left 左边对齐
  • right 右边对齐
  • center 等同于center_vertical|center_horizontal

3.2.2 Button

<Button
    android:id="@+id/button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Button"
    android:textAllCaps="false" />           #不自动进行大写转换
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                // 按钮点击处理逻辑
                break;
            default:
                break;
        }
    }

}

3.2.3 EditText

<EditText
    android:id="@+id/edit_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Type something here"       #提示性内容
    android:maxLines="2"                     #最大可见行数
    />
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText editText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        // 获取 EditText 对象
        editText = (EditText) findViewById(R.id.edit_text);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                // 获取 EditText 内容
                String input = editText.getText().toString();
                Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
        }
    }
}

3.2.4 ImageView

app/src/main/res/drawable-xhdpi/img_1.png

app/src/main/res/drawable-xhdpi/img_2.png

<ImageView
    android:id="@+id/image_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:data-original="@drawable/img_1"
    />
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        imageView  = (ImageView) findViewById(R.id.image_view);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                // 更换图片
                imageView.setImageResource(R.drawable.img_2);
                break;
            default:
                break;
        }
    }
}

3.2.5 ProcessBar

    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText editText;

    private ImageView imageView;

    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        progressBar = (ProgressBar) findViewById(R.id.progress_bar);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                if (progressBar.getVisibility() == View.GONE) {
                    // 显示控件
                    progressBar.setVisibility(View.VISIBLE);
                } else {
                    // 隐藏控件
                    progressBar.setVisibility(View.GONE);
                }
                break;
            default:
                break;
        }
    }

}

水平进度条:

    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleHorizontal"    #设为水平进度条,默认圆形
        android:max="100"                                   #最大值为100
        />
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                int progress = progressBar.getProgress();
                // 进度+10
                progress = progress + 10;
                progressBar.setProgress(progress);
                break;
            default:
                break;
        }
    }

3.2.6 AlertDialog

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
                AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
                dialog.setTitle("This is a dialog");
                dialog.setMessage("something important.");
                dialog.setCancelable(false);
                // 确定按钮的点击事件
                dialog.setPositiveButton("OK", new DiaLogInterface.OnClickListener() {
                    @Override
                    public void onClick(DiaLogInterface dialog, int whick) {
                    }
                });
                // 取消按钮的点击事件
                dialog.setNegativeButton("Cancel", new DiaLogInterface.OnClickListener() {
                    @Override
                    public void onClick(DiaLogInterface dialog, int whick) {
                    }
                });
                // 显示dialog
                dialog.show();
                break;
            default:
                break;
        }
    }
    

3.2.7 ProgressDialog

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
                progressDialog.setTitle("This is ProgressDialog");
                progressDialog.setMessage("Loading...");
                // 不能通过返回键取消,注意要在程序中处理关闭
                progressDialog.setCancelable(false);
                progressDialog.show();
                break;
            default:
                break;
        }
    }
查看原文

赞 0 收藏 0 评论 0

小伍 发布了文章 · 10月18日

Android 开发入门-活动的最佳实践

2.6.1 知晓当前是在哪一个活动

右击 app/src/main/java/com/example/activitytest -> New -> Java Class -> BaseActivity

# app/src/main/java/com/example/activitytest/BaseActivity.java

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 获取当前实例的类名
        Log.d("BaseActivity", getClass().getSimpleName());
    }
}

修改活动类的继承关系,继承于 BaseActivity

public class FirstActivity extends BaseActivity {}
public class SecondActivity extends BaseActivity {}
public class ThirdActivity extends BaseActivity {}

2.6.2 随时随地退出程序

# app/src/main/java/com/example/activitytest/ActivityCollector.java

// 活动管理器类
public class ActivityCollector {

    // 存放活动的 List
    public static List<Activity> activities = new ArrayList<>();

    // 添加活动的方法
    public static void addActivity(Activity activity) {
        activities.add(activity);
    }

    // 移除活动的方法
    public static void removeActivity(Activity activity) {
        activities.remove(activity);
    }

    // 销毁全部活动
    public static void finishAll() {
        for (Activity activity : activities) {
            if (!activity.isFinishing()) {
                activity.finish();
            }
        }
    }

}
# app/src/main/java/com/example/activitytest/BaseActivity.java

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity", getClass().getSimpleName());
        // 将活动放入 List 中
        ActivityCollector.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 从 List 中移除活动
        ActivityCollector.removeActivity(this);
    }

}
# app/src/main/java/com/example/activitytest/ThirdActivity.java

public class ThirdActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("ThirdActivity", "Task id is " + getTaskId());
        setContentView(R.layout.third_layout);
        Button button3 = (Button) findViewById(R.id.button_3);
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ActivityCollector.finishAll();
                // 结束当前进程,保证程序完全退出
                android.os.Process.killProcess(android.os.Process.myPid());
            }
        });

    }
}

2.6.3 启动活动的最佳写法

# app/src/main/java/com/example/activitytest/SecondActivity.java

public class SecondActivity extends BaseActivity {

    // 对外提供启动活动的方法,并定义启动参数
    public static void actionStart(Context context, String data1, String data2) {
        Intent intent = new Intent(context, SecondActivity.class);
        intent.putExtra("param1", data1);
        intent.putExtra("param2", data2);
        context.startActivity(intent);
    }
}
button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 启动 SecondActivity 活动
        SecondActivity.actionStart(FirstActivity.this, "data1", "data2");
    }
});
查看原文

赞 0 收藏 0 评论 0

小伍 发布了文章 · 10月11日

Android 开发入门-活动的启动模式

2.5.1 standard

默认的启动模式。系统不关心这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d("FirstActivity", this.toString());
    setContentView(R.layout.first_layout);
    Button button1 = (Button) findViewById(R.id.button_1);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 在 FirstActivity 活动中启动 FirstActivity 活动
            Intent intent = new Intent(FirstActivity.this, FirstActivity.class);
            startActivity(intent);
        }
    });
}

2.5.2 singleTop

在启动活动时如果返回栈的栈顶已经是该活动,则直接使用,不创建新的活动实例。

# app/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.activitytest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".FirstActivity"
            android:launchMode="singleTop"                            #指定活动启动模式
            android:label="This is FirstActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

但如果该活动不是位于返回栈的栈顶,还是会创建新的活动实例。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d("FirstActivity", this.toString());
    setContentView(R.layout.first_layout);
    Button button1 = (Button) findViewById(R.id.button_1);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 在 FirstActivity 活动中启动 SecondActivity 活动
            Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
            startActivity(intent);
        }
    });
}
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("SecondActivity", this.toString());
        setContentView(R.layout.second_layout);
        Button button2 = (Button) findViewById(R.id.button_2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 在 SecondActivity 活动中启动 FirstActivity 活动,会创建一个新的 FirstActivity
                Intent intent = new Intent(SecondActivity.this, FirstActivity.class);
                startActivity(intent);
            }
        });
    }

2.5.3 singleTask

每次启动该活动时系统会在返回栈中检查是否存在该活动的实例,如果已经存在则直接使用该实例,并把这个活动之上的所有活动出栈,如果不存在则创建一个新的活动实例。

# app/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.activitytest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".FirstActivity"
            android:launchMode="singleTask"                            #指定活动启动模式
            android:label="This is FirstActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d("FirstActivity", this.toString());
    setContentView(R.layout.first_layout);
    Button button1 = (Button) findViewById(R.id.button_1);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 在 FirstActivity 活动中启动 SecondActivity 活动
            Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
            startActivity(intent);
        }
    });
}

@Override
protected void onRestart() {
    super.onRestart();
    Log.d("FirstActivity", "onRestart");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d("SecondActivity", this.toString());
    setContentView(R.layout.second_layout);
    Button button2 = (Button) findViewById(R.id.button_2);
    button2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 在 SecondActivity 活动中启动 FirstActivity 活动,不会创建一个新的 FirstActivity,而是复用旧的活动,触发 FirstActivity 的 onRestart 和本活动的 onDestory
            Intent intent = new Intent(SecondActivity.this, FirstActivity.class);
            startActivity(intent);
        }
    });
}

@Override
protected void onDestory() {
    super.onDestory();
    Log.d("SecondActivity", "onDestory");
}

2.5.4 singleInstance

为活动实例创建单独的返回栈,该活动位于新的返回栈中,其他活动位于原返回栈中。

<activity
    android:name=".SecondActivity"
    android:launchMode="singleInstance">                            #指定活动启动模式
    <intent-filter>
        <action android:name="com.example.activitytest.ACTION_START" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="com.example.activitytest.MY_CATEGORY" />
    </intent-filter>
</activity>
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d("FirstActivity", "Task id is " + getTaskId());
    setContentView(R.layout.first_layout);
    Button button1 = (Button) findViewById(R.id.button_1);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 在 FirstActivity 活动中启动 SecondActivity 活动
            Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
            startActivity(intent);
        }
    });
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d("SecondActivity", "Task id is " + getTaskId());
    setContentView(R.layout.second_layout);
    Button button2 = (Button) findViewById(R.id.button_2);
    button2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 在 SecondActivity 活动中启动 ThirdActivity 活动
            Intent intent = new Intent(SecondActivity.this, ThirdActivity.class);
            startActivity(intent);
        }
    });
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d("ThirdActivity", "Task id is " + getTaskId());
    setContentView(R.layout.third_layout);
}

结果是:FirstActivity 和 ThirdActivity 位于同一个返回栈中,SecondActivity 独立存放在新的返回栈中。

活动启动顺序:FirstActivity -> SecondActivity -> ThirdActivity

活动退出顺序:ThirdActivity -> FirstActivity -> SecondActivity -> 程序退出。

查看原文

赞 0 收藏 0 评论 0

小伍 发布了文章 · 10月11日

Android 开发入门-活动的生命周期

2.4.1 返回栈

每启动一个新的活动,会在返回栈中入栈,并处于栈顶的位置。每销毁一个活动,处于栈顶的活动会出栈,前一个入栈的活动会重新处于栈顶的位置。

2.4.2 活动状态

  1. 运行状态:位于返回栈栈顶的活动。
  2. 暂停状态:不在栈顶位置,但仍然可见。
  3. 停止状态:不在栈顶位置,完全不可见。可能会被系统回收。
  4. 销毁状态:在返回栈中移除的活动。

2.4.3 活动的生存期

  • onCreate():活动第一次被创建时调用,在此方法中完成活动的初始化工作。
  • onStart():活动由不可见变为可见时调用。
  • onResume():在活动准备好和用户进行交互时调用。此时活动位于栈顶,并处于运行状态。
  • onPause():系统准备去启动或恢复另一个活动时调用。启动新的对话框活动,此方法会被调用。
  • onStop():在活动完全不可见时调用。启动新的对话框活动,此方法不会被调用。
  • onDestroy():活动被销毁前被调用。
  • onRestart():活动由停止状态变为运行状态前调用。

可以将活动分为3中生存期:

  • 完整生存期。在 onCreate() 和 onDestroy() 之间所经历的。
  • 可见生存期。在 onStart() 和 onStop() 之间所经历的。
  • 前台生存期。在 onResume() 和 onPause() 之间所经历的。

img

2.4.4 体验活动的生命周期

# app/src/main/res/layout/normal_layout.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:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="This is a normal activity"
        />

</LinearLayout>
# app/src/main/res/layout/dialog_layout.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:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="This is a dialog activity"
        />

</LinearLayout>
# app/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.activitylifecycletest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".NormalActivity">
        </activity>
        <activity android:name=".DialogActivity"
            # DialogActivity 活动使用 Dialog 对话框主题
            android:theme="@android:style/Theme.Dialog">
        </activity>
    </application>

</manifest>
# app/src/main/res/layout/activity_main.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">

    <Button
        android:id="@+id/start_normal_activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start NormalActivity" />

    <Button
        android:id="@+id/start_dialog_activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start DialogActivity" />

</LinearLayout>
# app/src/main/java/com/example/activitylifecycletest/MainActivity.java

public class MainActivity extends AppCompatActivity {

    public static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        setContentView(R.layout.activity_main);
        Button startNormalActivity = (Button) findViewById(R.id.start_normal_activity);
        Button startDialogActivity = (Button) findViewById(R.id.start_dialog_activity);
        
        // 启动 NormalActivity 活动
        startNormalActivity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, NormalActivity.class);
                startActivity(intent);
            }
        });
        
        // 启动 DialogActivity 活动
        startDialogActivity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, DialogActivity.class);
                startActivity(intent);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(TAG, "onRestart");
    }

}

程序启动:Create - Start - Resume

按钮一:Pause - Stop

返回按钮:Restart - Start - Resume

退出程序:Pause - Stop - Destroy

程序启动:Create - Start - Resume

按钮二:Pause

返回按钮:Resume

退出程序:Pause - Stop - Destroy

2.4.5 活动被回收了怎么办

活动进入停止状态,可能会被系统回收。用户返回活动后,活动不会执行 onRestart() 方法,而是会执行 onCreate() 方法,重新创建一次该活动。

Android 提供了 onSaveInstanceState() 回调方法,保证在活动被回收前被调用,可用于保存上一个活动的临时数据:

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // 保存临时数据
        String tempData = "Something you just typed";
        outState.putString("data_key", tempData);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        setContentView(R.layout.activity_main);
        // 取出临时数据
        if(savedInstanceState != null) {
            String tempData = savedInstanceState.getString("data_key");
            Log.d(TAG, tempData);
        }
    }
查看原文

赞 0 收藏 0 评论 0

小伍 发布了文章 · 10月7日

Android 开发入门-使用 Intent 在活动之间穿梭

2.3.1 使用显式 Intent

# app/src/main/res/layout/second_layout.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">

    <Button
        android:id="@+id/button_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button 2"
        />

</LinearLayout>
# app/src/main/java/com/example/activitytest/SecondActivity.java

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_layout);
    }
}
# app/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.activitytest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".FirstActivity"                              #注册的活动名称,可省略包名
            android:label="This is FirstActivity">                     #指定活动标题
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />   #设为主活动
                <category android:name="android.intent.category.LAUNCHER" /> #设为启动器
            </intent-filter>
        </activity>
        <activity
            android:name=".SecondActivity">                            #注册第二个活动
        </activity>
    </application>

</manifest>
public class FirstActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        Button button1 = (Button) findViewById(R.id.button_1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 实例化 Intent,第一个参数为当前上下文,第二个参数为要启动的目标活动
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                // 启动目标活动
                startActivity(intent);
            }
        });
    }

2.3.2 使用隐式 Intent

<activity
    android:name=".SecondActivity">
    <intent-filter>
        # 指定当前活动相应的行为是 ACTION_START
        <action android:name="com.example.activitytest.ACTION_START" />
        # 指定当前活动相应的分类是 DEFAULT
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
public class FirstActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        
        Button button1 = (Button) findViewById(R.id.button_1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 实例化 Intent,并设置行为是 ACTION_START,不设置分类则默认分类是 DEFAULT
                Intent intent = new Intent("com.example.activitytest.ACTION_START");
                startActivity(intent);
            }
        });
    }

增加活动分类:

<activity
    android:name=".SecondActivity">
    <intent-filter>
        # 指定当前活动相应的行为是 ACTION_START
        <action android:name="com.example.activitytest.ACTION_START" />
        # 指定当前活动相应的分类是 DEFAULT
        <category android:name="android.intent.category.DEFAULT" />
        # 指定当前活动相应的分类是 MY_CATEGORY
        <category android:name="com.example.activitytest.MY_CATEGORY" />
    </intent-filter>
</activity>
public class FirstActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        
        Button button1 = (Button) findViewById(R.id.button_1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 实例化 Intent,并设置行为是 ACTION_START
                Intent intent = new Intent("com.example.activitytest.ACTION_START");
                // 为 Intent 设置分类是 MY_CATEGORY
                intent.addCategory("com.example.activitytest.MY_CATEGORY");
                startActivity(intent);
            }
        });
    }

2.3.3 更多隐式 Intent 的用法

button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 实例化 Intent,并设置行为是 ACTION_VIEW
        Intent intent = new Intent(Intent.ACTION_VIEW);
        // 设置 Intent 的 Uri
        intent.setData(Uri.parse("https://www.baidu.com"));
        // 启动活动,会打开系统浏览器访问设置的网址
        startActivity(intent);
    }
});
<?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">

    <Button
        android:id="@+id/button_3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button 3"
        />

</LinearLayout>
<activity android:name=".ThirdActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        # 指定数据的协议部分是 http
        <data android:scheme="http" />
    </intent-filter>
</activity>

调用系统拨号界面:

button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(Intent.ACTION_DIAL);
        intent.setData(Uri.parse("tel:10086"));
        startActivity(intent);
    }
});

2.3.4 向下一个活动传递数据

button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        String data = "Hello SecondActivity";
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        // 暂存数据到 Intent 中
        intent.putExtra("extra_data", data);
        startActivity(intent);
    }
});
public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_layout);
        Intent intent = getIntent();
        // 从 Intent 中取出数据
        String data = intent.getStringExtra("extra_data");
        Log.d("SecondActivity", data);
    }

2.3.5 返回数据给上一个活动

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.first_layout);
    Button button1 = (Button) findViewById(R.id.button_1);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
            // 启动活动,并接受活动销毁时返回的数据,第二个参数为请求码,用于判断数据的来源
            startActivityForResult(intent, 1);
        }
    });
}

// 下一个活动被销毁时的回调函数
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // 判断数据来源
    switch (requestCode) {
        case 1:
            if (resultCode == RESULT_OK) {
                String returnedData = data.getStringExtra("data_return");
                Log.d("FirstActivity", returnedData);
            }
            break;
        default:
    }
}
public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("SecondActivity", "Task id is " + getTaskId());
        setContentView(R.layout.second_layout);
        Button button2 = (Button) findViewById(R.id.button_2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                // 暂存数据到 Intent 中
                intent.putExtra("data_return", "Hello FirstActivity");
                // 向上一个活动返回数据,第一个参数一般为 RESULT_OK
                setResult(RESULT_OK, intent);
                // 销毁当前活动
                finish();
            }
        });
    }

    // 绑定按下返回键时的逻辑,与按钮点击的逻辑一致
    @Override
    public void onBackPressed() {
        Intent intent = new Intent();
        intent.putExtra("data_return", "Hello FirstActivity");
        setResult(RESULT_OK, intent);
        finish();
    }
}
查看原文

赞 0 收藏 0 评论 0

小伍 发布了文章 · 10月5日

Android 开发入门-活动的基本用法

2.1 活动是什么

活动(Activity)是一种可以包含用户界面的组件,主要用于和用户进行交互。

2.2 活动的基本用法

2.2.1 手动创建活动

右击 app/src/main/java/com/example/activitytest -> New -> Activity -> Empty Activity -> FirstActivity,不勾选 Generate Layout FileLauncher Activity ,勾选 Backwards Compatibility 启用向下兼容模式。

public class FirstActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}

2.2.2 创建和加载布局

右击 app/src/main/res -> New -> Directory -> layout

右击 layout -> Layout resource file -> first_layout & LinearLayout

<?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">

    <Button
        android:id="@+id/button_1"                    #定义按钮ID语法:@+id/id_name
        android:layout_width="match_parent"           #定义元素宽度:匹配父元素
        android:layout_height="wrap_content"          #定义元素高度:适配包含的元素
        android:text="Button 1"
        />

</LinearLayout>
public class FirstActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 在当前活动中加载 first_layout 布局
        setContentView(R.layout.first_layout);
    }
}

2.2.3 在 AndroidManifest 文件中注册

# app/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.activitytest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".FirstActivity"                              #注册的活动名称,可省略包名
            android:label="This is FirstActivity">                     #指定活动标题
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />   #设为主活动
                <category android:name="android.intent.category.LAUNCHER" /> #设为启动器
            </intent-filter>
        </activity>
    </application>

</manifest>

2.2.4 在活动中使用 Toast

public class FirstActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 在当前活动中加载 first_layout 布局
        setContentView(R.layout.first_layout);
        // 通过按钮ID获取按钮对象
        Button button1 = (Button) findViewById(R.id.button_1);
        // 设置按钮监听器
        button1.setOnClickListener(new View.OnClickListener() {
            // 绑定点击事件
            @Override
            public void onClick(View v) {
                // 注册 Toast 并显示
                Toast.makeText(FirstActivity.this, "You clicked button1", Toast.LENGTH_SHORT).show();
            }
        });
        
    }
}
  • Toast.LENGTH_SHORT 显示时长较短
  • Toast.LENGTH_LONG 显示时长较长

2.2.5 在活动中使用Menu

右击 app/src/main/res -> New -> Directory -> menu

右击 menu -> New -> Menu resource file -> main

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item                                # 第一个菜单项
        android:id="@+id/add_item"
        android:title="Add"/>
    <item                                # 第二个菜单项
        android:id="@+id/remove_item"
        android:title="Remove"/>
</menu>
public class FirstActivity extends AppCompatActivity {

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // 使用 MenuInflater 对象为当前活动创建菜单
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
    // 监听菜单选择事件
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.add_item:
                Toast.makeText(this, "You clicked Add", Toast.LENGTH_SHORT).show();
                break;
            case R.id.remove_item:
                Toast.makeText(this, "You clicked Remove", Toast.LENGTH_SHORT).show();
                break;
            default:
        }
        return true;
    }

2.2.6 销毁一个活动

button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        finish();
    }
});
查看原文

赞 0 收藏 0 评论 0

小伍 发布了文章 · 9月27日

Android 开发入门-简介

1.1 Android 简介

1.1.1 Android 系统架构

  1. Linux 内核层:为各种硬件提供底层驱动
  2. 系统运行库层:通过 C/C++ 库提供主要的特性支持。
  3. 应用框架层:提供构建应用程序时需要用到的各种 API。
  4. 应用层:安装在手机上的应用程序。

img

1.1.2 Android 已发布的版本

Android APIAndroid版本分布比例
28Android 9 (Pie)10.40%
27Android 8.1 (Oreo)15.40%
26Android 8.0 (Oreo)12.90%
25Android 7.1.1 (Nougat)7.80%
24Android 7.0 (Nougat)11.40%
23Android 6.0 (MarshMallow)16.90%
22Android 5.1 (Lollipop)11.50%
21Android 5.0 (Lollipop)3.00%
19Android 4.4 (Kitkat)6.90%
18Android 4.3 (Jelly Bean)0.50%
17Android 4.2.x (Jelly Bean)1.50%
16Android 4.1.x (Jelly Bean)1.20%
15Android 4.0.3 - 4.0.4 (Ice Cream Sandwich)0.30%
10Android 2.3.3 - 2.3.7 (Gingerbread)0.30%

1.1.3 Android 应用开发特色

  1. 四大组件:活动、服务、广播接收器、内容提供器
  2. 丰富的系统控件
  3. SQLite 数据库
  4. 强大的多媒体
  5. 地理位置定位

1.2 搭建开发环境

  • JDK8 或以上版本
  • Android SDK
  • Android Studio

1.3 创建 Android 项目

  1. Start a new Android Studio project
  2. 启动模拟器
  3. 运行 HelloWorld 项目

1.3.1 分析目录结构

首先将项目结构模式切换为 Project 模式。

.gradle                    自动生成的目录,无须关心
.idea                      自动生成的目录,无须关心
app                        项目主要目录,即工作目录
  build                    编译时自动生成的文件目录,无须关心
  libs                     第三方 jar 包存放目录
  src                      项目主要目录,即工作目录
    androidTest            测试用例目录,进行自动化测试
    main                   项目主要目录,即工作目录
      java                 JAVA 代码目录
      res                  资源目录
      AndroidManifest.xml  Android项目配置文件
    test                   单元测试用例目录
  .gitignore               Git 版本控制排除的配置文件
  app.iml                  IDEA 自动生成的文件,无须关心
  build.gradle             app 模块的 gradle 构建脚本
  proguard-rules.pro       配置项目代码的混淆规则
build                      编译时自动生成的文件目录,无须关心
gradle                     包含 gradle wrapper 的配置文件
.gitignore                 Git 版本控制排除的配置文件
build.gradle               全局的 gradle 构建脚本,通常不需修改
gradle.properties          全局的 gradle 配置文件
gradlew                    命令行执行 gradle 的文件(Linux)
gradlew.bat                命令行执行 gradle 的文件(Windows)
HelloWorld.iml             IDEA 自动生成的文件,无须关心
local.properties           指定本机 Android SDK 位置的配置文件,通常不需修改
settings.gradle            指定项目中引入的模块的配置文件

代码分析。

# app/src/main/AndroidManifest.xml

<!-- 对 HelloWorldActivity 活动进行注册 -->
<activity android:name=".HelloWorldActivity">
    <intent-filter>
        <!-- 指定 HelloWorldActivity 是项目的主活动 -->
        <action android:name="android.intent.action.MAIN" />
        <!-- 指定 HelloWorldActivity 是应用启动时首先启动的活动 -->
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
# app/src/main/java/com/example/helloworld/HelloWorldActivity.java

// 活动代码,需要继承 AppCompatActivity
public class HelloWorldActivity extends AppCompatActivity {
    // 活动创建时会自动执行的方法
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.hello_world_layout);
    }
}
# app/src/main/res/layout/hello_world_layout.xml

...
# 文本控件
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!" />
...

1.3.2 详解项目中的资源

res/drawable         图片目录
res/drawable-xxhdpi  图片目录,建议放在此目录
res/layout           布局文件
res/mipmap-hdpi      应用图标
res/mipmap-mdpi      应用图标
res/mipmap-xhdpi     应用图标
res/mipmap-xxhdpi    应用图标,建议放在此目录
res/mipmap-xxxhdpi   应用图标
res/values-w820dp    字符串、样式、颜色等配置
res/values           字符串、样式、颜色等配置
# app/src/main/res/values/strings.xml

# 定义字符串
<resources>
    <string name="app_name">HelloWorld</string>
</resources>
# 代码中使用
R.string.app_name

# XML中使用
@string/app_name

使用示例。

# HelloWorld/app/src/main/AndroidManifest.xml

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"   # 指定图标配置,使用@mipmap引用图标
    android:label="@string/app_name"     # 指定应用名称配置,使用@string引用字符串
    android:supportsRtl="true"
    android:theme="@style/AppTheme">     # 指定主题配置,使用@style引用风格目录

1.3.3 详解 build.gradle 文件

# build.gradle

buildscript {
    repositories {
        // 声明代码托管仓库
        jcenter()
    }
    dependencies {
        // 使用 gradle 构建 Android 项目
        classpath 'com.android.tools.build:gradle:2.2.0'
    }
}

allprojects {
    repositories {
        // 声明代码托管仓库
        jcenter()
    }
}
# app/build.gradle

// 应用的插件:com.android.application 为应用程序模块;com.android.library 为库模块
apply plugin: 'com.android.application'

android {
    // 指定项目的编译版本
    compileSdkVersion 24
    // 指定项目构建工具的版本
    buildToolsVersion "24.0.2"
    defaultConfig {
        // 指定项目包名
        applicationId "com.example.helloworld"
        // 指定项目最低兼容的安卓版本
        minSdkVersion 15
        // 指定在该版本上已经做了充分的测试,启动最新的功能和特性
        targetSdkVersion 24
        // 指定项目的版本号
        versionCode 1
        // 指定项目的版本名称
        versionName "1.0"
    }
    // 生成安装文件的相关配置
    buildTypes {
        // 生成正式版安装文件的相关配置
        release {
            // 是否对项目代码进行混淆
            minifyEnabled false
            // 代码混淆时使用的规则文件:安卓通用混淆规则&项目混淆规则
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

// 指定项目的依赖关系
dependencies {
    // 本地依赖声明
    compile fileTree(include: ['*.jar'], dir: 'libs')
    // 远程依赖声明
    compile 'com.android.support:appcompat-v7:24.2.1'
    // 测试用例库声明
    testCompile 'junit:junit:4.12'
}

1.4 日志工具的使用

Log.v()  verbose 级别,琐碎的、意义最小的日志
Log.d()  debug 级别,调试分析的日志
Log.i()  info 级别,重要的数据的日志
Log.w()  warn 级别,潜在风险的日志
Log.e()  error 级别,错误的的日志
public class HelloWorldActivity extends AppCompatActivity {

    private static final String TAG = "HelloWorldActivity";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate execute");
        setContentView(R.layout.hello_world_layout);
    }
}

打印的日志位于:Android Monitor -> logcat 面板。

查看原文

赞 0 收藏 0 评论 0

小伍 发布了文章 · 9月25日

图解 YII 框架 ActiveRecord、ActiveQuery、Query、Model 之间的关系

UML类图

总结:

  • ActiveRecord 主要提供了快捷查询、增删改操作及事件、配置关联关系、返回 ActiveQuery 对象等功能;
  • ActiveQuery 主要提供了单条数据查询、所有数据查询、别名等功能;
  • Query 主要提供了数据库链式操作等功能;
  • Model 主要提供了数据校验、场景、属性、字段等功能。
查看原文

赞 0 收藏 0 评论 0

小伍 关注了用户 · 9月24日

HelloWord @helloword_5f5f5114e5188

本人十余年开发,曾在阿里、滴滴等企业待过,架构师岗位,精通spring、多线程高并发、Redis、分布式等
喜欢技术交流,共同分享,欢迎加助理VX:MXW5308 领取个人整理的一系列面试宝典、pdf书籍、录制视频的系统学习资料

关注 194

认证与成就

  • 获得 0 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 9月24日
个人主页被 195 人浏览