项目中引用MPChartLib
1、 将MPChartLib文件夹拷贝到项目根目录
2、在根目录里的settings.gradle里增加include ':app', ':MPChartLib'
3、将文件MPChartLib.aar拷贝到libs文件夹里
4、在build.grade(app)中增加
dependencies { implementation project(':MPChartLib') }
设置app自动启动
增加权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
注册消息接收
<receiver android:name=".BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
消息接收函数
class BootBroadcastReceiver: BroadcastReceiver() {
override public fun onReceive(context: Context, intent: Intent) {
val mBootIntent = Intent(context, MainActivity::class.java)
mBootIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(mBootIntent)
}
}
获取位置信息(kotlin)
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
val location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
If (location != null) {
val sb = StringBuffer()
sb.append('实时的位置信息:经度:')
sb.append(location.longitude) sb.append('纬度:')
sb.append(location.latitude) sb.append('高度:')
sb.append(location.altitude) sb.append('速度:')
sb.append(location.speed) sb.append('方向:')
sb.append(location.bearing) sb.append('精度:')
sb.append(location.accuracy)
Toast.makeText(applicationContext, sb.toString(), Toast.LENGTH_LONG).show() }
添加权限
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
发送Notification消息(kotlin)
fun sendNotification(channel_id:String ,channle_name:String,nTitle:String,nContentText:String,id:Int){
var notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
var notification: Notification? = null
//val intent = Intent(Intent.ACTION_VIEW, Uri.parse('http://www.baidu.com/'))
//val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
//如需链接到网站使用注释代码
val intent = Intent()
intent.setClass(this@MainActivity, MainActivity::class.
val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val mChannel = NotificationChannel(channel_id, channle_name, NotificationManager.IMPORTANCE_LOW) notificationManager.createNotificationChannel(mChannel)
notification = Notification.Builder(this) .setChannelId(channel_id) .setContentTitle(nTitle) .setContentText(nContentText)
.setContentIntent(pendingIntent) .setSmallIcon(R.drawable.house).build()
}
else {
val notificationBuilder = NotificationCompat.Builder(this)
.setContentTitle(nTitle)
.setContentText(nContentText)
.setSmallIcon(R.drawable.house)
.setOngoing(true)
//.setChannel(id)//无效
notification = notificationBuilder.build() }
notificationManager.notify(id, notification) }
禁止使用http链接解决方法
访问网络时报异常
Cleartext HTTP traffic to not permitted
在<application标签里增加android:usesCleartextTraffic="true"即可
bitmap缩小显示
var matrix = Matrix()
matrix.postScale(0.3f,0.3f)//长和宽放大缩小的比例
val resizeBmp = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true)
textview 连续左移
设置一下参数,自动连续左移动
android:ellipsize="marquee"
android:focusable="auto"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
useAndroidx Error
编译报错
This project uses AndroidX dependencies, but the 'android.useAndroidX' property is not enabled.
在gradle.propeties文件里增加如下语句,允许AnsiroidX
android.useAndroidX=true
post获取数据(kotlin)
Thread(Runnable {
val toMain1 = mAppMesHandler.obtainMessage()
toMain1.arg1 = 1
var conn: HttpURLConnection? = null
var urlString = "http://server/new.php"
try {
conn = URL(urlString).openConnection() as HttpURLConnection
conn.requestMethod = "POST" // 指定POST请求
conn.doOutput = true // 设置请求过程可以传递参数给服务器
// post请求参数
val param = String.format("name=%s&age=%s&action=%s", "fengxueyan", "23", "query") DataOutputStream(conn.outputStream).use { os ->
os.writeBytes(param)
}
conn.connect()
conn.inputStream.use { input ->
val data = input.bufferedReader().readText() toMain1.obj = data.toString()
}
}
catch (e: Exception) {
toMain1.obj = e.toString()
}
finally {
conn?.disconnect()
}
mAppMesHandler.sendMessage(toMain1) }).start()
//访问网络必须使用线程,而且线程不允许更新UI
val mAppMesHandler = object : Handler() {
override fun handleMessage(msg: Message) {
if(msg.arg1 == 1){
var hList0 = msg.obj as String textView.setText(hList0)
// Toast.makeText(applicationContext,hList0,Toast.LENGTH_LONG).show()
}
}
}
时间日期选择
<TimePicker android:id="@+id/ptime"
android:layout_width="310dp"
android:layout_height="347dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button2" />
textView.setText(ptime.hour.toString()+":"+ptime.minute.toString())
<DatePicker
android:id="@+id/pdate"
android:layout_width="358dp"
android:layout_height="428dp"
android:layout_marginTop="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.566"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button2" />
textView.setText(pdate.year.toString()+"-"+(pdate.month+1).toString()+"-"+pdate.dayOfMonth.toString())
多个Fragment和Activity的简易数据交换方法(kotlin)
动态创建多个Fragment后,和Activity数据交换有很多种方式,消息方式简单快捷,代码量少
在Activity中定义消息处理 val mMainHandler = object : Handler() {
override fun handleMessage(msg: Message) { if (msg.arg1 == 1) { val sVerRes = msg.obj as String Toast.makeText(applicationContext, sVerRes, Toast.LENGTH_LONG).show() }
}
在Fragment里定义消息handle
private var aHandle:Handler? = null
建立初始化函数,将Activity的消息handle传入
fun setHandler(AHandler: Handler?) {
try { aHandle = AHandler } catch (e: Exception) { throw ClassCastException(context.toString() }
}
Activity向Fragment传递数据直接定义函数
Fragment向Activity传递数据发送消息
val toMain1 = aHandle!!.obtainMessage()
toMain1.obj = “message or data”
toMain1.arg1 = 1
aHandle!!.sendMessage(toMain1)
实现扫码二维码(kotlin)
dependencies增加引用
implementation 'com.hongyelinggu:scancode:1.0.0'
申请相机权限
<uses-permission android:name="android.permission.CAMERA"/>
val REQUEST_EXTERNAL_STORAGE = 1234
if (ActivityCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_EXTERNAL_STORAGE)
}
else{
}
执行扫描 startActivityForResult(Intent(this@MainActivity, CommonScanActivity::class.java), 1)
返回结果字符串
override fun onActivityResult(requestCode:Int, resultCode:Int, data:Intent?){
super.onActivityResult(requestCode, resultCode, data)
val rCode = data!!.extras!!.getString(Constant.REQUEST_SCAN_MODE) //得到新Activity关闭后返回的数据
Toast.makeText(applicationContext, rCode, Toast.LENGTH_LONG).show() }
读取写入文本文件(kotlin)
写入文件
val fn = filesDir.toString() + "文件名.txt"
var fff = "文本内容"
try {
val tfw = FileWriter(fn)
tfw.write(fff)
tfw.close()
Toast.makeText(applicationContext, "保存成功", Toast.LENGTH_LONG).show()
}
catch (e: Exception) {
Toast.makeText(applicationContext, e.toString(), Toast.LENGTH_LONG).show()
}
读取文件
val fn = filesDir.toString() + "文件名.txt"
try {
val fb = FileReader(fn)
val tv2:TextView = findViewById(R.id.textView2)
tv2.setText(fb.readText()) //显示到TextView
fb.close()
}
catch(e:Exception){
Toast.makeText(applicationContext, e.toString(), Toast.LENGTH_LONG).show()
}
如果路径访问需要权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
//获取sd卡读写权限
//val REQUEST_EXTERNAL_STORAGE = 1234
if (ActivityCompat.checkSelfPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE") != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(this, arrayOf(WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE), REQUEST_EXTERNAL_STORAGE)
}
else{
}
多项选择对话框 kotlin
val builder = AlertDialog.Builder(this)
builder.setTitle("请选择")
builder.setIcon(R.drawable.ic_launcher_foreground)
builder.setCancelable(true)
val items = arrayOf("第一项", "第二项", "第三项")
var selected = booleanArrayOf(true, false, true)
builder.setMultiChoiceItems(items, selected) { dialog, which, isChecked ->
// dialog.dismiss();
// Toast.makeText(this@MainActivity, items[which] + isChecked, Toast.LENGTH_SHORT).show()
}
//此代码实现输入文本对话框
//val filename :EditText = EditText(this)
//builder.setView(filename)
builder.setPositiveButton(" 确定发送 ") { dialogInterface, i ->
val tw: TextView = findViewById(R.id.textView1) var sd = ""
for (i in 0 until items.count()) {
if (selected[i])
sd += items[i]
}
tw.setText(sd)
Toast.makeText(this@MainActivity, sd, Toast.LENGTH_SHORT).show()
//tw.setText(filename.text.toString())
}
builder.setNegativeButton("取消发送") { dialogInterface, i ->
// finish()
}
builder.show()
OptionsMenu kotlin
app 右键 new=》android resouce file resouce type 选择Menu
创建菜单项目,编辑ID和title
//显示菜单
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.mainmanu,menu)
return true
// return super.onCreateOptionsMenu(menu)
}
//处理菜单点击响应
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if(item?.itemId == R.id.menu_exit){
finish()
}
if(item?.itemId == R.id.menu_upate){
Toast.makeText(this,"system update",Toast.LENGTH_LONG).show()
}
return super.onOptionsItemSelected(item)
}
ContextMenu kotlin
app 右键 new=》android resouce file resouce type 选择Menu 创建菜单项目,编辑ID和title
override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) { super.onCreateContextMenu(menu, v, menuInfo) menuInflater.inflate(R.menu.menupop,menu) menu!!.setHeaderTitle("请选择") }
重载函数
override fun onContextItemSelected(item: MenuItem): Boolean { if(item.itemId == R.id.media_route_menu_item1){ Toast.makeText(this,"11111111",Toast.LENGTH_LONG).show() } return super.onContextItemSelected(item) }
onCreate
val bt_menu: Button = findViewById(R.id.button_menu) registerForContextMenu(bt_menu) bt_menu.setOnClickListener { openContextMenu(it) }
如果在list view item弹出菜单,直接
val tv_houseList = findViewById(R.id.listview_house_list) as ListView registerForContextMenu(tv_houseList)
这样长按item自动会弹出菜单
androidstudio使用WebView显示网页(kotlin)
val wset = wview1.settings wset.javaScriptEnabled = true wview1.setWebViewClient(object : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean { view.loadUrl(url) return true } }) wview1.loadUrl(“http://www.baidu.com”)
在AndroidManifest.xml增加
android:usesCleartextTraffic="true"
需要添加网络权限
如果需要支持网页弹出alert:
wview1.setWebChromeClient (object : WebChromeClient() override fun onJsAlert(view: WebView,url: String,message: String,result: JsResult):Boolean{ return super.onJsAlert(view, url, message, result) } })
androidstudio使用viewPager显示多张图片并关联tabLayout(kotlin)
val mImgId = intArrayOf(R.drawable.h1, R.drawable.h2, R.drawable.h3)
val mList = ArrayList() var tabName : Array = Array(3,{""})
tabName[0] = "TAB1" tabName[1] = "TAB2" tabName[2] = "TAB3"
vpage.setAdapter(object : PagerAdapter() { override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { container.removeView(mList.get(position)) } override fun instantiateItem(container: ViewGroup, position: Int): Any { val imageView = ImageView(this@MainActivity) imageView.setImageResource(mImgId[position]) imageView.setScaleType(ImageView.ScaleType.CENTER_CROP) container.addView(imageView) mList.add(imageView) return imageView } override fun getCount(): Int { return mImgId.size } override fun isViewFromObject(view: View, `object`: Any): Boolean { return view === `object` } override fun getPageTitle(position:Int):CharSequence{ return tabName[position] }
}) tabcus.setupWithViewPager(vpage)
使用ViewPager2和TabLayout实现多frgment切换
private fun initTab(){ val viewpage = findViewById(R.id.viewpage2) as ViewPager2 viewpage.adapter = object : FragmentStateAdapter(this){ override fun getItemCount(): Int { return 3 } override fun createFragment(position: Int): Fragment { return when(position){ 0 -> myFragment() 1 -> hlistFragment() else -> hlistFragment() } } } val tabmain = findViewById(R.id.tabLayout) as TabLayout
TabLayoutMediator( tabmain, viewpage, object : TabLayoutMediator.TabConfigurationStrategy{ override fun onConfigureTab(tab: TabLayout.Tab, position: Int) { when(position){ 0 -> tab.text = "资源汇总" 1 -> tab.text = "我的房源" else -> tab.text = "房源资源库" } } }).attach()
xml文件
<com.google.android.material.tabs.TabLayout <androidx.viewpager2.widget.ViewPager2
建立Fragement list 用于访问每个动态创建的Fragment
var list_frm:ArrayList<Fragment> = ArrayList()
override fun createFragment(position: Int): Fragment { when(position){ 0 -> { val fg = myFragment() list_frm.add(fg ) return fg } 1 -> { val fg = hlistFragment() list_frm.add(fg) return fg } else -> { val fg = hlistFragment() list_frm.add(fg) return fg } } }
使用BaseAdapter为listview装入数据
class myAdapter (context: Activity,listValue:String): BaseAdapter(){ private var ct:Activity private var lv:String init { ct = context lv = listValue
} override fun getCount():Int{ val hma_list = lv.split("^") return hma_list.count() } override fun getItem(position: Int):String{ val hma_list = lv.split("^") return hma_list[position].toString() } override fun getItemId(position: Int):Long{ return position.toLong() }
override fun getView(position: Int, view: View?, parent: ViewGroup): View { val rowView = ct.layoutInflater.inflate(R.layout.layout_house_info_item, null, true) val hm_name = rowView.findViewById(R.id.tv_item_name) as TextView val hm_price = rowView.findViewById(R.id.tv_item_price) as TextView val hm_size = rowView.findViewById(R.id.tv_item_size) as TextView val hm_room = rowView.findViewById(R.id.tv_item_room) as TextView val hm_time = rowView.findViewById(R.id.tv_item_time) as TextView val hm_status = rowView.findViewById(R.id.tv_item_status) as TextView val hma_list = lv.split("^") var hma_value = hma_list[position].split("~") hm_name.text = hma_value[0] if(hma_value[12] == "2" ) hm_price.text = hma_value[4]+"/月" else hm_price.text = hma_value[2]+"万" hm_size.text = hma_value[9] +" "+ hma_value[1]+"平米" hm_room.text = hma_value[6]+"室"+hma_value[7]+"厅"+hma_value[8]+"卫 "+hma_value[5]+"层" hm_time.text = "最后跟进"+hma_value[11] return rowView } }
listview 操作
val adapter = myAdapter(this,listStr) tv_houseList.setAdapter(adapter)
让EditText不能编辑,只读
et_tel.keyListener = null
让WebView支持手机定位
静态申请权限
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_GPS" /> <uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" /> <uses-permission android:name="android.permission.ACCESS_LOCATION" />
动态申请权限
if (ActivityCompat.checkSelfPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE") != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions(this, arrayOf(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION), 1234) }
设置WebView参数
val wview1 = findViewById(R.id.vview1) as WebView val wset = wview1.settings wset.javaScriptEnabled = true wset.setGeolocationEnabled(true) //允许定位 wview1.setWebViewClient(object : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean { view.loadUrl(url) return true } })
wview1.setWebChromeClient (object : WebChromeClient() { override fun onJsAlert(view: WebView, url: String, message: String, result: JsResult):Boolean{ return super.onJsAlert(view, url, message, result) } override fun onGeolocationPermissionsShowPrompt( origin: String?, callback: GeolocationPermissions.Callback? ) { val remember = true val builder: AlertDialog.Builder = AlertDialog.Builder(this@MainActivity) builder.setTitle("位置信息") builder.setMessage(origin + "允许获取您的地理位置信息吗?").setCancelable(true) .setPositiveButton("允许", DialogInterface.OnClickListener { dialog, id -> callback?.invoke( origin, true, remember ) }) .setNegativeButton("不允许", DialogInterface.OnClickListener { dialog, id -> callback?.invoke( origin, false, remember ) }) val alert: AlertDialog = builder.create() alert.show() } })