sisterofDC / kotlin_study

0 stars 0 forks source link

android design #2

Open sisterofDC opened 3 years ago

sisterofDC commented 3 years ago

第一点 main/java/com.example.()中建立新的Empty Activity res/layout中建立新的layout 在新的activity建立layout的连接 setContentView(R.layout.first_layout) 最后在AndroidManifest.xml中重新定向

<intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
sisterofDC commented 3 years ago

第一个activity

 val button_one:Button = findViewById(R.id.button_one)
        button_one.setOnClickListener {
            Toast.makeText(this,"abc",Toast.LENGTH_SHORT).show()
        }
sisterofDC commented 2 years ago

activity的生存周期 onCreate() onStart() onResume() onPause() onStop() onDestroy() onRestart()

sisterofDC commented 2 years ago

LinearLayoutCompat的属性 下划线可以使用 backgroudcolor 的设置 @color/属性 在button属性中,背景色设定用backgroundTint来进行设定 用ctrl + /进行注释

帧布局 FrameLayout

组件的默认位置都是左上角,组件之间可以重叠。一层压一层 可以设置上下左右的对齐,水平垂直居中,和Linear Layout相似

后面的部件会压在前面的上方

sisterofDC commented 2 years ago

多个布局的嵌套可以实现界面的划动,

<LinearLayout
            <ScrollView
                <LinearLayout>
                </LinearLayout>
            </ScrollView>
    </LinearLayout>

这样通过层层嵌套,实现

动态添加Ui操作

            val newtext:TextView = TextView(this) //首先申请新的UI组件
            newtext.setText("this is my text $times !") //为新的组件设置视图
            layout.addView(newtext)//添加组件
sisterofDC commented 2 years ago

相对的布局的属性

<RelativeLayout>
 </RelativeLayout>

在button 有默认的上边距和下边距 默认的排序的顺序,从左上开始 insetTop insetBottom 都是(default6dp)

设置的函数 insetTop insetBottom

        android:insetTop="0dp"
        android:insetBottom="0dp"

都是相对于父元素摆放的位置,也是当前组件的拜访位置 想让位置到右下处

        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
//水平方向的居中对齐
        android:layout_centerHorizontal="true"
//垂直方向的居中对齐
        android:layout_centerVertical="true"
//同时使用就可以使元素在正中
        android:layout_centerInParent="true"

相对于兄弟元素摆放自己的位置 需要为每一个组件设置id 这里留一个问题,如果是动态添加的组件,怎么设置位置?????????????????????????


    <Button
        android:id="@+id/one"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerInParent="true"/>
    <Button
        android:id="@+id/two"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_toRightOf="@+id/one" />//右方
    <Button
        android:id="@+id/three"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_toLeftOf="@+id/one"/>//左方
    <Button
        android:id="@+id/four"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_above="@+id/one"/>//上面
    <Button
        android:id="@+id/five"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_below="@+id/one"/>//下面

兄弟组件的常用的对齐方式

        android:layout_below="@+id"
        android:layout_above="@+id/"
        android:layout_toLeftOf="@+id/"
        android:layout_toRightOf="@+id/"
        android:layout_alignLeft="@+id/"
        android:layout_alignRight="@+id/"
        android:layout_alignTop="@+id/"
        android:layout_alignBottom="@+id/"
sisterofDC commented 2 years ago

开始联系书上的列子 首先是更改标题栏 多使用weight权重的应用

sisterofDC commented 2 years ago

首先是自己的标题 在layout 中加上title

<?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/button_one"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_one" />

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="@string/title"
        android:gravity="center"/>

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

然后再values 加上

    <string name="button_one">返回</string>
    <string name="button_two">开始</string>
    <string name="title">sisterofDC</string>

在自己的主页面上加上 <include layout="@layout/title"/>

最后复写系统自己的标题栏 supportActionBar?.hide()

sisterofDC commented 2 years ago

创建自定义控制栏 首先自定义一个类继承一个组件

写自己的一个导航栏 重新定义一个类继承LinearLayout(context,attrs)


class TitleLayout(context:Context,attrs:AttributeSet):LinearLayout(context,attrs){
    init {
        LayoutInflater.from(context).inflate(R.layout.title,this)
        val buttonone=findViewById<Button>(R.id.button_one)
        buttonone.setOnClickListener {
            val activity = context as Activity /* 注销 */
            activity.finish()
        }
        val buttontwo=findViewById<Button>(R.id.button_two)
        buttontwo.setOnClickListener {
            Toast.makeText(context,"you click this button",Toast.LENGTH_SHORT).show()
        }
    }
}

然后就可以直接在界面加载

    <com.example.diolog.TitleLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

这里注意一个东西,diolog.是自己的组件名 新的项目中都要重新写

sisterofDC commented 2 years ago

加载自己的导航栏,还是用 RelativeLayout. 然后再在下面的空间进行编辑

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.example.diolog.TitleLayout
            android:id="@+id/titleLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <LinearLayout
            android:layout_below="@+id/titleLayout"
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:background="#FFC0CB">

        </LinearLayout>
    </RelativeLayout>
sisterofDC commented 2 years ago

今天是ListView 的用法

普通的基本用法 1.创建传入的数据 private val menberdata =ArrayList<menber>() val adapter =ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,data) 就有基本的只能传入字符串

进阶用法 首先设计每一个listitem 在layout下设计一个listitem

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

    <ImageView
        android:id="@+id/menberimage"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="10dp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/menbername"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"/>
</LinearLayout>

然后回到主函数 首先创建item中的类 class menber(val name:String,val imageID:Int) 然后复写adpter


class menberadapter(activity: Activity,val resourceId: Int,data:List<menber>):ArrayAdapter<menber>(activity,resourceId,data){
    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        val view =LayoutInflater.from(context).inflate(resourceId,parent,false) //加入方法
        val imageID:ImageView = view.findViewById(R.id.menberimage) //找到位置
        val name:TextView = view.findViewById(R.id.menbername) //找到位置
        val menber = getItem(position) //获取当前项的实列
        if (menber!=null){ //设置路径和text
            imageID.setImageResource(menber.imageID)
            name.setText(menber.name)
        }
        return view
    }
}

最后添加数据

    private fun initdata(){
        repeat(3){
            menberdata.add(menber("wjx1",R.drawable.wjx1))
            menberdata.add(menber("wsm1",R.drawable.wsm1))
            menberdata.add(menber("wjsm2",R.drawable.wsm2))
            menberdata.add(menber("wyx1",R.drawable.wyx1))

        }
    }
        initdata()
        val adapter =menberadapter(this,R.layout.menber_item,menberdata)
sisterofDC commented 2 years ago

提升listview的运行效率 加入一个缓存

        val view:View
        if(convertView == null){
            view =LayoutInflater.from(context).inflate(resourceId,parent,false)
        }else{
            view =convertView
        }

最后加入一个点击list内容

        listViewone.setOnItemClickListener { _, _, position, _ ->
            val menberitem = menberdata[position]
            Toast.makeText(this,menberitem.name, LENGTH_SHORT).show()
        }

可以实现的内容 点击图片进行放大 内容输入 编辑

sisterofDC commented 2 years ago

更加强大的控件,RecyclerView

还是先建立layout 的布局

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

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/waifu_name"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"/>

</LinearLayout>

布局中加入RecyclerView

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recyclerview"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

            </androidx.recyclerview.widget.RecyclerView>

然后再mainactivty中重新复写adapter

class anime_waifu(val name:String)
class study_RecclerView(val anime:List<anime_waifu>):RecyclerView.Adapter<study_RecclerView.ViewHolder>(){ //重新写适配器
    inner class ViewHolder(view:View):RecyclerView.ViewHolder(view){ //必须重写onCreateViewHolder()  onBindViewHolder()  getItemCount()
        val name:TextView = view.findViewById(R.id.waifu_name) //找到自己写item布局中的元素,有好多写好多
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {

        val view =LayoutInflater.from(parent.context).inflate(R.layout.anime_waifu,parent,false)

        val viewHolder = ViewHolder(view)//找到点击的元素
        viewHolder.itemView.setOnClickListener{
            val position =viewHolder.absoluteAdapterPosition //不能使用adapterPosition,这个已经被弃用了 ,而是用absoluteAdapterPosition
            val item =anime[position]
            Toast.makeText(parent.context,"you click this ${item.name}",Toast.LENGTH_SHORT).show()
        }
        return viewHolder
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = anime[position]
        holder.name.text =item.name
    }
    override fun getItemCount() = anime.size
}

    private val animeWaifu =ArrayList<anime_waifu>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        supportActionBar?.hide()
        init()
        val layoutManager =LinearLayoutManager(this)
//        layoutManager.orientation =LinearLayoutManager.HORIZONTAL
        val recyclerView =findViewById<RecyclerView>(R.id.recyclerview)
        recyclerView.layoutManager =layoutManager
        val adpter = study_RecclerView(animeWaifu)
        recyclerView.adapter=adpter
    }

    private fun init(){
        animeWaifu.add(anime_waifu("asuka"))
        animeWaifu.add(anime_waifu("明日香"))
        animeWaifu.add(anime_waifu("二乃"))
        animeWaifu.add(anime_waifu("远坂凛"))
        animeWaifu.add(anime_waifu("asuka"))
        animeWaifu.add(anime_waifu("asuka"))
        animeWaifu.add(anime_waifu("asuka"))

    }
sisterofDC commented 2 years ago

今天是正式写聊天框 首先还是正常的加入自己的顶部栏,加入成功 开始学习 首先是界面布局 采用RelativeLayout


<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.example.diologthree.TitleLayout
            android:id="@+id/titleLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"/> //相对布局的应用,放在顶部
<!--        <LinearLayout-->
<!--            android:layout_width="match_parent"-->
<!--            android:layout_height="match_parent"-->
<!--            android:layout_below="@+id/titleLayout"-->
<!--            android:background="#FFC0CB">-->
<!--        </LinearLayout>-->
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/RecyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/titleLayout"
            android:layout_above="@+id/bottomLinear" //相对布局子类的应用,卡死中间
            android:background="#FFC0CB">

        </androidx.recyclerview.widget.RecyclerView>
        <LinearLayout
            android:id="@+id/bottomLinear"
            android:layout_alignParentBottom="true" //放在底部
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#FFFFFF"
            android:orientation="horizontal">

            <EditText
                android:id="@+id/inputText"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:hint="Type something"
                android:maxLines="4" />

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

    </RelativeLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
sisterofDC commented 2 years ago

界面设计完后,还有左聊天框和右聊天框,都是采用帧布局 左聊天框

<?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="wrap_content"
    android:padding="10dp"
    >

    <LinearLayout
        android:background="#DB7093"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/LeftMeassage"
            android:layout_gravity="center"
            android:layout_margin="10dp"
            android:text=""
            android:textColor="#fff"/>

    </LinearLayout>

</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="wrap_content"
    android:padding="10dp">

    <LinearLayout
        android:background="#DB7093"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/RightMessage"
            android:layout_gravity="center"
            android:layout_margin="10dp"
            android:text=""
            android:textColor="#fff"/>
    </LinearLayout>

</FrameLayout>

然后编辑主函数 更换标题栏

class TitleLayout(context: Context, attrs: AttributeSet): LinearLayout(context,attrs){
    init {
        LayoutInflater.from(context).inflate(R.layout.title,this)
        val buttonone=findViewById<Button>(R.id.button_one)
        buttonone.setOnClickListener {
            val activity = context as Activity /* 注销 */
            activity.finish()
        }
        val buttontwo=findViewById<Button>(R.id.button_two)
        buttontwo.setOnClickListener {
            Toast.makeText(context,"you click this button",Toast.LENGTH_SHORT).show()
        }
    }
}

接下来声明消息类

/*如果想某个对象初始化和一个类实列捆绑一起,用companion。一个类只能有一个伴生对象*/
/*static在kotlin中的实现*/
class Message(val content:String,val type:Int){ //定义是发送消息,还是收到消息
    companion object{
        const val send =0
        const val receive =1
    }
}

然后就是复写RecyclerView的adetper 分为两个部分 左聊天框的,和右聊天框


class message_RecyclerView(val messageList:List<Message>):RecyclerView.Adapter<RecyclerView.ViewHolder>(){//这里最为不同的就是泛型类是RecyclerView.ViewHolder,有多少个部件去实列化

    inner class LeftmessageViewHolder(view: View):RecyclerView.ViewHolder(view){ //实现左边的
        val LeftMessage:TextView=view.findViewById(R.id.LeftMeassage)
    }

    inner class RightmessageViewHolder(view: View):RecyclerView.ViewHolder(view){//实现右边的
        val RightMessage:TextView=view.findViewById(R.id.RightMessage)
    }

    override fun getItemViewType(position: Int): Int { //找到数据的来源
        val typeofMessage = messageList[position]
        return typeofMessage.type
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder = //最重要的方法,这里注意,最后一排是lamdae的返回
        if(viewType==Message.receive){
            val view = LayoutInflater.from(parent.context).inflate(R.layout.left_message_item,parent,false)
            val leftmessageViewHolder =  LeftmessageViewHolder(view)

            leftmessageViewHolder.itemView.setOnClickListener {
                val position =leftmessageViewHolder.absoluteAdapterPosition //不能使用adapterPosition,这个已经被弃用了 ,而是用absoluteAdapterPosition
                val item =messageList[position]
                Toast.makeText(parent.context,"words is  ${item.content}",Toast.LENGTH_SHORT).show()
            }

            leftmessageViewHolder

        }else {
            val view = LayoutInflater.from(parent.context).inflate(R.layout.right_message_item,parent,false)
            val rightmessageViewHolder =  RightmessageViewHolder(view)

            rightmessageViewHolder.itemView.setOnClickListener {
                val position =rightmessageViewHolder.absoluteAdapterPosition
                val item =messageList[position]
                Toast.makeText(parent.context,"words is  ${item.content}",Toast.LENGTH_SHORT).show()
            }
            rightmessageViewHolder
        }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { //为部件设置内容
        val typeofMessage = messageList[position]
        when(holder){
            is LeftmessageViewHolder -> holder.LeftMessage.text=typeofMessage.content
            is RightmessageViewHolder -> holder.RightMessage.text =typeofMessage.content
            else -> throw IllegalAccessException()
        }

    }

    override fun getItemCount(): Int { //必须写的函数
        return messageList.size
    }

}

最后学习了新的方法 如果set的函数后面数据过多 可以复写函数

onclick()的应用


class MainActivity : AppCompatActivity(),View.OnClickListener{

    private var localdate = ArrayList<Message>()
    private var adapter:message_RecyclerView? =null
    private var number:Int=0
    private fun change(number: Int): Int {
        return number % 2
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        supportActionBar?.hide()
        initloacldata()
        val layoutManager =LinearLayoutManager(this)
        val recyclerView =findViewById<RecyclerView>(R.id.RecyclerView)
        recyclerView.layoutManager=layoutManager
        adapter= message_RecyclerView((localdate))
        recyclerView.adapter=adapter
        val Send =findViewById<Button>(R.id.send)
        Send.setOnClickListener(this)
    }

    private fun initloacldata(){
        localdate.add(Message("this is a test",Message.send))
    }

    override fun onClick(view: View?) {
        number += 1
        val inputtext =findViewById<EditText>(R.id.inputText)
        val conTent:String= inputtext.text.toString()
        if (conTent.isEmpty()){
            Toast.makeText(this,"please type some word",Toast.LENGTH_SHORT).show()
        }else{
            number=change(number)
            if (number==1){
                val leftmsg=Message(conTent,Message.receive)
                localdate.add(leftmsg)
                adapter?.notifyItemInserted(localdate.size - 1)
                val recyclerView =findViewById<RecyclerView>(R.id.RecyclerView)
                recyclerView.scrollToPosition(localdate.size -1)
                inputtext.setText("")
            }else if (number==0){
                val rightmsg=Message(conTent,Message.send)
                localdate.add(rightmsg)
                adapter?.notifyItemInserted(localdate.size - 1)
                val recyclerView =findViewById<RecyclerView>(R.id.RecyclerView)
                recyclerView.scrollToPosition(localdate.size -1)
                inputtext.setText("")
            }
        }
    }
}

这里是基础用法的总结了。明天开始看fragment看国庆之前弄的完不

sisterofDC commented 2 years ago

今天学习broadcast 分为标准广播和有序广播 标准广播是完全异步的广播 有序广播是同步的广播

动态和静态注册广播 写一个动态注册时间变化的广播 首先还是改变标题栏

在内容上写一个TEXTVIEW来接受变化

          <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                android:id="@+id/timechange"
                android:background="#FFFFFF"/>

然后再主函数中注册所有的东西 接受信号,信号接受类,取消注册 使用lateinit 的方法,变量会再后面进行申明

lateinit private var timechanger: Timechanger 注册信号

    inner class Timechanger:BroadcastReceiver(){
        override fun onReceive(context: Context, intent: Intent) {
            val changetext = findViewById<TextView>(R.id.timechange)
            changetext.setText("time is change")
        }
    }
        val intentFilter =IntentFilter()
        val action=Intent.ACTION_TIME_TICK //这个是时间变化的action,剩下的还有屏幕变化,电量变化,网络变化
        intentFilter.addAction(action)//这个感觉有点问题        timechanger =Timechanger()
        timechanger =Timechanger()
        registerReceiver(timechanger,intentFilter)

最后要注销监听

    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(timechanger)
    }

这里学习了一下网络的监听 还有前面的注册和消除

    lateinit private var internetchanger: Internetchanger
      val networkchange=ConnectivityManager.CONNECTIVITY_ACTION //在后面已经放弃的静态的广播,不能使用
        internetchanger=Internetchanger()CONNECTIVITY_ACTION
        registerReceiver(internetchanger,intentFilter)
        unregisterReceiver(internetchanger)
    inner class Internetchanger:BroadcastReceiver(){
        override fun onReceive(context: Context,intent: Intent) {
            val action =Context.CONNECTIVITY_SERVICE
            val connectivitymanager:ConnectivityManager = context.getSystemService(action) as ConnectivityManager
            val activework:Network?= if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                connectivitymanager.activeNetwork
            } else {
                Toast.makeText(context,"this upper idk",Toast.LENGTH_SHORT).show()
                null
            }
            val changenet= findViewById<TextView>(R.id.network)
            changenet.setText("${activework}")
            connectivitymanager.getNetworkCapabilities(activework)?.run {
                when {
                    this.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> Toast.makeText(
                        context,
                        "wifi",
                        Toast.LENGTH_LONG
                    ).show()
                    this.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> Toast.makeText(
                        context,
                        "cellular",
                        Toast.LENGTH_LONG
                    ).show()
                    else -> changenet.setText("there is no internet")
                }
            }

        }
    }

在注册中发现 网络监听不能用静态方法去注册,必须用动态方法去注册 所有接下来改写动态监听的方法 Android7.0为了提高用户体验和提升设备性能移除了这个隐式广播,所以利用静态注册的方式是不能接收到该广播的,如果需要使用广播方式监听网络变化可以使用动态注册的方式进行接收。

sisterofDC commented 2 years ago

网络监听 用的代码https://www.youtube.com/watch?v=To9aHYD5OVk 尝试使用 10.2今天是笔记的整理,分为三个部分 一·储存的使用 二intent的使用 三权限的申请

首先是储存

        savebutton.setOnClickListener {
            val data = input.text.toString()
            intent.putExtra("date",data)
            startActivity(intent)
            if(data.isNotEmpty()){
                savedate(data)
            }
        }
        readbutton.setOnClickListener {
            output.setText(raeddate())
            val readfile = getSharedPreferences("data",Context.MODE_PRIVATE)//只提供mode_private 的储存方式了
            val tost=readfile.getString("text","")
            Toast.makeText(this,"this is another${tost}",Toast.LENGTH_LONG).show()
        }
    }

    private fun savedate(input:String){
        try {
            val output = openFileOutput("data",Context.MODE_APPEND)
            val writer = BufferedWriter(OutputStreamWriter(output))
            writer.use {
                it.write(input)
            }
        }catch (e:IOException){
            e.printStackTrace()
            Log.d(TAG,"写入失败 ${e}")
        }
    }

其次是使用xml键值储存的方式

    private fun savedate(input:String){
        try {
            val output = openFileOutput("data",Context.MODE_APPEND)
            val writer = BufferedWriter(OutputStreamWriter(output))
            writer.use {
                it.write(input)
            }
        }catch (e:IOException){
            e.printStackTrace()
            Log.d(TAG,"写入失败 ${e}")
        }
    }

    private fun raeddate():String{
        val content = StringBuilder()
        try {
            val input = openFileInput("data")
            val reader =BufferedReader(InputStreamReader(input))
            reader.use{
                reader.forEachLine {
                    content.append(it)
                }
            }
        }catch (e:IOException){
            e.printStackTrace()
            Log.d(TAG,"读取失败${e}")
        }
        return content.toString()
    }

自带的数据库方式并没有学习,打算有空再看下mongoDB的使用

sisterofDC commented 2 years ago

然后是intent的重新学习 首先是正向传参 发送方

    private fun PositiveTransfer(){
        val intent =Intent(this,MainActivitytwo::class.java)
        val texttwo = findViewById<EditText>(R.id.two_input)
        val valuetwo =texttwo.text.toString()
        intent.putExtra(TWO_DATA,valuetwo)
        startActivity(intent)
    }

接收方

        val data =intent.getStringExtra(TWO_DATA)
        val showtext =findViewById<TextView>(R.id.two_text)
        showtext.setText(data)

反向传参和申请权限是一样,调用系统的方法 首先是创建固定的键值

const val DATA_RETURN=5
    companion object{
        private const val CAMERA_PERMISSION_CODE =1
        private const val CAMERA_REQUEST_CODE= 2
        private const val REQUEST_CODE_STORAGE_PERMISSION =3
        private const val REQUEST_CODE_SELECT_IMAGE =4
    }

因为所有的intent返回都是Activity.RESULT_OK,加入新的键值来准确确定那个intent

返回参数
        val threebutton =findViewById<Button>(R.id.three_return)

        threebutton.setOnClickListener {
            val threetext =findViewById<EditText>(R.id.three_input)
            val threevalue =threetext.text.toString()
            val intent = Intent()
            intent.putExtra("return_data",threevalue)
            setResult(DATA_RETURN,intent)
            Log.d(TAG,"活动三数据发送")
            finish()
        }

接受参数 startActicityForresult好像也是被弃用了,好像是用 startActivityFromFragment()

        val intent =Intent(this,MainActivitythree::class.java)
        startActivityForResult(intent, DATA_RETURN)
//        startActivityFromFragment()
//有空学习一下如何使用这个

然后再复写onActivityResult

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode== DATA_RETURN){
            Log.d(TAG,"收到三活动的数据")
            val threevalue = data!!.extras!!.get("return_data") as String
            val shownumber =findViewById<TextView>(R.id.three_text)
            shownumber.setText(threevalue)
        }
    }

接着是相机的申请和相册的选择

val add= findViewById<Button>(R.id.add)
        add.setOnClickListener {//相机的选择
            if (ContextCompat.checkSelfPermission(this,android.Manifest.permission.CAMERA)== PackageManager.PERMISSION_GRANTED){
                val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)//申请使用相机
                startActivityForResult(intent, CAMERA_REQUEST_CODE)
            }else{
                ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.CAMERA),
                    CAMERA_PERMISSION_CODE)
            }
        }
        val selcet = findViewById<Button>(R.id.select)
        selcet.setOnClickListener {//相册的选择
            if (ContextCompat.checkSelfPermission(this,android.Manifest.permission.READ_EXTERNAL_STORAGE)== PackageManager.PERMISSION_GRANTED){
                val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)//申请使用
                startActivityForResult(intent, REQUEST_CODE_SELECT_IMAGE)
            }else{
                ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
                    REQUEST_CODE_STORAGE_PERMISSION)
            }
        }
        val four_return =findViewById<Button>(R.id.four_return)
        four_return.setOnClickListener {
            Log.d(TAG,"four_activity_over")
            finish()
        }
    }

    override fun onRequestPermissionsResult(//申请权限
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED){
            val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
            startActivityForResult(intent, CAMERA_REQUEST_CODE)
            val intenttwo = Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
            startActivityForResult(intenttwo, REQUEST_CODE_SELECT_IMAGE)
        }else{
            Toast.makeText(this,"permission denied", Toast.LENGTH_SHORT).show()
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode == Activity.RESULT_OK&&requestCode == CAMERA_REQUEST_CODE){
            val picture: Bitmap = data!!.extras!!.get("data") as Bitmap
            val setpicture = findViewById<ImageView>(R.id.iv_image)
            setpicture.setImageBitmap(picture)
        }
        if (resultCode== Activity.RESULT_OK && requestCode== REQUEST_CODE_SELECT_IMAGE){
            val selectURI: Uri? = data!!.getData()
            if (selectURI!=null){
                val inputstream = contentResolver.openInputStream(selectURI)
                val picture: Bitmap = BitmapFactory.decodeStream(inputstream)
                val setpicture = findViewById<ImageView>(R.id.iv_image)
                setpicture.setImageBitmap(picture)
            }
        }
    }

在anifest.xml中加入

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

布局文件中显示图片的是

            <androidx.appcompat.widget.AppCompatImageView
                android:id="@+id/iv_image"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
sisterofDC commented 2 years ago

最后是广播的学习

定义一个秒钟的计时器

package com.example.taskthree

import android.app.Service
import android.content.Intent
import android.os.IBinder
import java.util.*
import android.util.Log

class Timeservice:Service() {
    override fun onBind(p0: Intent?): IBinder? {
        return null
    }
    private val timer = Timer()

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        val time = intent!!.getIntExtra(TIME_EXTRA,0)
        timer.scheduleAtFixedRate(TimeTASK(time),0,1000)
        return Service.START_NOT_STICKY
    }

    override fun onDestroy() {
        timer.cancel()
        super.onDestroy()
    }

    private inner class TimeTASK(private var time:Int):TimerTask(){
        override fun run() {
            val intent =Intent(TIMER_CHANGE)
            time++
            Log.d(TAG,"现在计时为${time}")
            intent.putExtra(TIME_EXTRA,time)
            sendBroadcast(intent)
        }
    }

    companion object{
        const val TIMER_CHANGE="time_change"
        const val TIME_EXTRA ="time_extra"
    }
}
package com.example.taskthree

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.TextView

class MainActivityfive : AppCompatActivity() {

    private var timerStarted = false
    private lateinit var serviceIntent: Intent
    private var time =0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main_activityfive)
        supportActionBar?.hide()

        serviceIntent = Intent(applicationContext,Timeservice::class.java)

        val startbutton = findViewById<Button>(R.id.starttime)
        val endbutton = findViewById<Button>(R.id.endtime)
        val returnbutton =findViewById<Button>(R.id.five_return)
        returnbutton.setOnClickListener {
            Log.d(TAG,"活动五结束")
            finish()
        }

        registerReceiver(updateTime, IntentFilter(Timeservice.TIMER_CHANGE))

        startbutton.setOnClickListener {
            stopandstartTimer()
        }
        endbutton.setOnClickListener {
            resetTimer()
        }
    }

    private fun resetTimer() {
        stoptimer()
        time =0
        val timechange =findViewById<TextView>(R.id.time_change)
        val text:String = time.toString()
        timechange.setText(text)
        val startbutton = findViewById<Button>(R.id.starttime)
        startbutton.text="开始"
    }

    private fun stoptimer() {
        stopService(serviceIntent)
        val startbutton = findViewById<Button>(R.id.starttime)
        startbutton.text="继续"
        timerStarted=false
    }

    private fun starttimer() {
        serviceIntent.putExtra(Timeservice.TIME_EXTRA,time)
        startService(serviceIntent)
        val startbutton = findViewById<Button>(R.id.starttime)
        startbutton.text="停止"
        timerStarted=true
    }

    private fun stopandstartTimer() {
        if (timerStarted==false){
            starttimer()
        }else if (timerStarted==true){
            stoptimer()
        }
    }

    private val updateTime: BroadcastReceiver = object : BroadcastReceiver(){
        override fun onReceive(context: Context, intent: Intent) {
            time = intent.getIntExtra(Timeservice.TIME_EXTRA,0)
            val timechange =findViewById<TextView>(R.id.time_change)
            val text:String = time.toString()
            timechange.setText(text)
        }
    }

}

如果想反转屏幕不闪退 android:configChanges="screenSize|orientation|keyboard"

sisterofDC commented 2 years ago

今天是笔记整理,从十月一号开始整理 主要从几个方面开始整理 首先列出还没有完成的方面 1.fragment (应该是实现了)

2.Dialog 3.ViewPager 4.Tablayout

5.平板上的显示 6.SQLite (弄完了,大致实现了增删改查) 7.ContentProvider 8.多线程和协程 9..书上后面所有的内容了 然后是今晚的总结 首先是recyclerView。的重新学习。书写格式仿照的youtuber的Mitch中的代码 https://www.youtube.com/channel/UCoNZZLhPuuRteu02rh7bzsw

大致分为四个部分 类 Data部分 adatper 主函数

kotlin 类的申请 class //( var 变量 ) { }

data的初始化

class Data { //申请一个类
    companion object{
        fun createDataSet():ArrayList<类>{
            val list=ArrayList<类>()
            list.add //加入初始化对象,当然后面是直接向网络数据库直接请求数据
            return list
        }
    }
}

然后是复写adapter 这是一个最基本的adapter有所有必须实现的方法 首先是三个必须实现的参数 override fun onCreateViewHolder(parent: ViewGroup, p1: Int): RecyclerView.ViewHolder override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) override fun getItemCount(): Int

然后因为需要返回getItemCount private var items:List<类> =ArrayList() 然后要创建一个返回参数的函数 private var Listener: (()->Unit)? = null fun adapterListener(l: ()->Unit) { Listener = l }

需要一个内置类,实现每一个元素 class PostViewHolder constructor( itemView: View ):RecyclerView.ViewHolder(itemView){ val workername= itemView.findViewById(R.id.name) fun bind(worker: Worker){ workername.setText(worker.name.toString()) } }

最后要传入item fun submistList(worker: List){ items = worker }

class Myadapter: RecyclerView.Adapter<RecyclerView.ViewHolder>()  {  
    private var items:List<类> =ArrayList()
    private var positionone:Int=0
    private var Listener: (()->Unit)? = null
    fun adapterListener(l: ()->Unit)
    {
        Listener = l
    }
    fun getposition():Int{
        return positionone
    }

    override fun onCreateViewHolder(parent: ViewGroup, p1: Int): RecyclerView.ViewHolder {
        return PostViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.worker,parent,false)
        )
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when(holder){
            is PostViewHolder->{
                holder.bind(items[position])
                holder.itemView.setOnClickListener {
                    positionone=position
                    Listener?.let {
                        it()
                    }
                }
            }
        }
    }

    override fun getItemCount(): Int {
        return items.size
    }
    class PostViewHolder constructor(
        itemView: View
    ):RecyclerView.ViewHolder(itemView){
        val workername= itemView.findViewById<TextView>(R.id.name)
        val workersex= itemView.findViewById<TextView>(R.id.sex)
        val workerage= itemView.findViewById<TextView>(R.id.age)
        fun bind(worker: Worker){
            workername.setText(worker.name.toString())
            workersex.setText(worker.sex.toString())
            workerage.setText(worker.age.toString())
        }
    }
    fun submistList(worker: List<Worker>){
        items = worker
    }
}

最后一步在主函数实现 初始化数据

    private fun addDateSet(){
        data = Data.createDataSet()
        postAdapter.submistList(data)
    }

初始化recylerview 这里注意 如果想要在recyclerview中注册就在这个函数中 需要加入这个 holder.itemView.isLongClickable=true

    private fun initRecyclerView(){
        val recyclerView = findViewById<RecyclerView>(R.id.recycler_View)
        recyclerView.apply {
            recyclerView.layoutManager=
                LinearLayoutManager(this@MainActivity)
            postAdapter= Myadapter()
            adapter=postAdapter
        }
        registerForContextMenu(recyclerView) 注册了长按按钮
    }

接下来是menu这注册 首先在layout中右键加入新的目录menu 然后在主函数中

//导出视图
    override fun onCreateContextMenu(
        menu: ContextMenu?,
        v: View?,
        menuInfo: ContextMenu.ContextMenuInfo?
    ) {
        super.onCreateContextMenu(menu, v, menuInfo)
        val inflater:MenuInflater=menuInflater
        inflater.inflate(R.menu.mymenu,menu)
    }
//选选项
    override fun onContextItemSelected(item: MenuItem): Boolean {
        when(item.itemId){
            R.id.add ->Toast.makeText(this,"this is add",Toast.LENGTH_SHORT).show()
            R.id.delete ->Toast.makeText(this,"this is delete",Toast.LENGTH_SHORT).show()
        }
        return false
    }

最后要在使用的地方注册菜单 registerForContextMenu()

sisterofDC commented 2 years ago

这里提一下,(这里学习完后就变灰一项) 网路配置的课程 三个部分 数据库访问 阿帕奇的 springboot mongodb ngiex 所有的配置学习

sisterofDC commented 2 years ago

fragment 和fragment直接不可能直接通信 然后数据库操作

这里有个问题 在build.gradle 文件中

    defaultConfig {
        applicationId "com.example.taskfourtest"
}

这个决定了,该程序在手机中的文件名字 明天做一些fragment 和sq数据库的笔记 还差的笔记更新,fragment于fragment 和数据库访问的

sisterofDC commented 2 years ago

今天通知,播放 sendlocalbroadcast hint 提醒